快速语音 示例演示了如何在 TextToSpeech 类型中在 Qt Quick 应用程序中读取文本和控制语音。
该示例使用 Qt Quick Controls 来提供对语音的音调、音量和速度的控制。它还允许用户选择引擎、语言和声音。
初始化 TextToSpeech
首先,我们初始化文本到语音对象 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 当前 ComboBox 当前索引处的文本。
Text {
text: qsTr("Engine:")
}
ComboBox {
id: enginesComboBox
Layout.fillWidth: true
model: tts.availableEngines()
onActivated: {
tts.engine = textAt(currentIndex)
updateLocales()
updateVoices()
上述代码的最后两行显示了在此处还会更新可用的区域和声音,因为它们依赖于所选的发动机。这些函数在接下来的部分中进行说明。
localesComboBox 的实现方式与 engineComboBox 相同,但不会更新可用的发动机。
}
}
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
}
选择音量、音高和
这些控件通过以下方式使用 滑块 实现
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 运行示例,打开 欢迎使用 模式,并在 示例 中选择示例。有关更多信息,请参阅构建和运行示例。
示例项目 @ code.qt.io