빠른 음성 예제

빠른 말하기 예제는 사용자가 제공한 텍스트를 읽어줍니다.

빠른 음성 예제에서는 TextToSpeech 유형을 애플리케이션에서 어떻게 사용하여 Qt Quick 애플리케이션에서 텍스트를 읽어주고 음성을 제어하는 방법을 보여줍니다.

이 예에서는 Qt Quick Controls 를 사용하여 음성의 높낮이, 볼륨 및 속도를 제어합니다. 또한 사용자가 엔진, 언어 및 음성을 선택할 수 있습니다.

텍스트 음성 변환 초기화하기

먼저 텍스트 음성 변환 객체 tts 를 초기화합니다:

    TextToSpeech {
        id: tts
        volume: volumeSlider.value
        pitch: pitchSlider.value
        rate: rateSlider.value

상태 가져오기

스위치 케이스는 바닥글의 statusLabel 레이블을 업데이트하는 데 사용됩니다.

        onStateChanged: updateStateLabel(state)

        function updateStateLabel(state)
        {
            switch (state) {
                case TextToSpeech.Ready:
                    statusLabel.text = qsTr("Ready")
                    break
                case TextToSpeech.Speaking:
                    statusLabel.text = qsTr("Speaking")
                    break
                case TextToSpeech.Paused:
                    statusLabel.text = qsTr("Paused...")
                    break
                case TextToSpeech.Error:
                    statusLabel.text = qsTr("Error!")
                    break
            }

말하는 대로 단어 강조 표시하기

TextArea input 은 입력할 텍스트와 onSayingWord 신호를 트리거로 가져오는 데 사용되며, 단어가 말할 때 강조 표시할 위치를 파악하는 데도 사용됩니다.

        onSayingWord: (word, id, start, length)=> {
            input.select(start, start + length)

TextArea input 은 여기에 선언됩니다:

    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 8
        id: inputForm

        TextArea {
            id: input
            wrapMode: TextEdit.WordWrap
            text: qsTr("Hello, world!")
            Layout.fillWidth: true
            Layout.minimumHeight: implicitHeight
            font.pointSize: 24
        }

음성 제어

Button 유형은 RowLayout 으로 배열되고 TextToSpeech tts 을 제어하도록 구성됩니다.

말하기 버튼

"말하기"라는 레이블이 붙은 Button 이 생성됩니다. tts 의 상태 속성이 Paused 또는 Ready 인 경우 활성화됩니다.

        RowLayout {
            Button {
                text: qsTr("Speak")
                enabled: [TextToSpeech.Paused, TextToSpeech.Ready].includes(tts.state)

버튼을 클릭하면 대상 장치에서 사용 가능한 음성이 검색되고 tts.voice 는 현재 선택된 voicesComboBox 의 음성으로 설정됩니다. 그런 다음 TextToSpeech::say()가 호출되고 inputbox 의 텍스트가 전달됩니다.

                onClicked: {
//! [say0]
                    let voices = tts.availableVoices()
                    tts.voice = voices[voicesComboBox.currentIndex]
//! [say1]
                    tts.say(input.text)
                }

일시 중지, 다시 시작 및 중지 버튼

이러한 버튼은 Speak 버튼과 구현 방식이 유사합니다:

            Button {
                text: qsTr("Pause")
                enabled: tts.state == TextToSpeech.Speaking
                onClicked: tts.pause()
                visible: tts.engineCapabilities & TextToSpeech.Capabilities.PauseResume
            }
//! [pause]
//! [resume]
            Button {
                text: qsTr("Resume")
                enabled: tts.state == TextToSpeech.Paused
                onClicked: tts.resume()
                visible: tts.engineCapabilities & TextToSpeech.Capabilities.PauseResume
            }
//! [resume]
            Button {
                text: qsTr("Stop")
                enabled: [TextToSpeech.Speaking, TextToSpeech.Paused].includes(tts.state)
                onClicked: tts.stop()
            }
        }

텍스트 음성 변환 옵션 선택

GridLayout 은 텍스트 음성 합성을 위한 엔진, 로캘, 음성, 볼륨, 피치 및 속도 옵션을 선택하기 위한 컨트롤과 레이블을 정렬하는 데 사용됩니다.

엔진, 로캘 및 음성 선택하기

이러한 매개변수를 선택하는 데는 ComboBox 컴포넌트 그룹이 사용됩니다.

엔진 선택의 경우 ComboBox, tts.availableEngines() 이 모델로 사용됩니다.

onActivated 은 콤보박스의 현재 인덱스에서 tts.engine에 현재 텍스트를 할당하도록 트리거합니다.

            Text {
                text: qsTr("Engine:")
            }
            ComboBox {
                id: enginesComboBox
                Layout.fillWidth: true
                model: tts.availableEngines()
                onActivated: {
                    tts.engine = textAt(currentIndex)
                    updateLocales()
                    updateVoices()

위 코드 조각의 마지막 두 줄은 사용 가능한 로캘과 음성이 선택한 엔진에 따라 달라지므로 이 시점에서도 업데이트된다는 것을 보여줍니다. 이러한 기능은 다음 섹션에서 다룹니다.

localesComboBoxengineComboBox 과 동일한 방식으로 구현되지만 사용 가능한 엔진은 업데이트하지 않습니다.

                }
            }
            Text {
                text: qsTr("Locale:")
            }
            ComboBox {
                id: localesComboBox
                Layout.fillWidth: true
                onActivated: {
                    let locales = tts.availableLocales()
                    tts.locale = locales[currentIndex]
                    updateVoices()
                }
            }
            Text {
                text: qsTr("Voice:")
            }
            ComboBox {
                id: voicesComboBox
                Layout.fillWidth: true
            }
볼륨, 피치 및 속도 선택하기

이러한 컨트롤은 Sliders 에서 다음과 같이 구현됩니다:

            Text {
                text: qsTr("Volume:")
            }
            Slider {
                id: volumeSlider
                from: 0
                to: 1.0
                stepSize: 0.2
                value: 0.8
                Layout.fillWidth: true
            }
            Text {
                text: qsTr("Pitch:")
            }
            Slider {
                id: pitchSlider
                from: -1.0
                to: 1.0
                stepSize: 0.5
                value: 0
                Layout.fillWidth: true
            }
            Text {
                text: qsTr("Rate:")
            }
            Slider {
                id: rateSlider
                from: -1.0
                to: 1.0
                stepSize: 0.5
                value: 0
                Layout.fillWidth: true
            }
        }
    }

사용 가능한 옵션 업데이트하기

Component.onCompleted 신호를 사용하여 ApplicationWindow 루트가 인스턴스화되면 다음 작업이 수행됩니다.

  • enginesComboBox 인덱스는 현재 설정된 엔진 tts 으로 설정됩니다.
  • 사용 가능한 로캘 및 보이스가 업데이트됩니다.
  • tts 의 현재 상태가 시그널링됩니다.
    Component.onCompleted: {
        enginesComboBox.currentIndex = tts.availableEngines().indexOf(tts.engine)
        // some engines initialize asynchronously
        if (tts.state == TextToSpeech.Ready) {
            engineReady()

애플리케이션 전체에서 사용되는 updateLocales()updateVoice() 함수는 다음과 같이 구현됩니다:

        } else {
            tts.stateChanged.connect(root.engineReady)
        }

        tts.updateStateLabel(tts.state)
    }

    function engineReady() {
        tts.stateChanged.disconnect(root.engineReady)
        if (tts.state != TextToSpeech.Ready) {
            tts.updateStateLabel(tts.state)
            return;
        }
        updateLocales()
        updateVoices()
    }

    function updateLocales() {
        let allLocales = tts.availableLocales().map((locale) => locale.nativeLanguageName)
        let currentLocaleIndex = allLocales.indexOf(tts.locale.nativeLanguageName)
        localesComboBox.model = allLocales
        localesComboBox.currentIndex = currentLocaleIndex
    }

    function updateVoices() {
        voicesComboBox.model = tts.availableVoices().map((voice) => voice.name)
        let indexOfVoice = tts.availableVoices().indexOf(tts.voice)
        voicesComboBox.currentIndex = indexOfVoice

예제 실행하기

에서 예제를 실행하려면 Qt Creator에서 Welcome 모드를 열고 Examples 에서 예제를 선택합니다. 자세한 내용은 예제 빌드 및 실행하기를 참조하세요.

예제 프로젝트 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.