TTS (Text To Speech) is a speech synthesis technology that allows the machine to play the input text in the form of speech, achieving The effect of machine speaking.
TTS is divided into speech processing and speech synthesis. The input text is first recognized by the machine, and then speech synthesis is performed based on the speech library. There are many TTS interfaces that can be called, such as the speech synthesis interface of Baidu Smart Cloud. Microsoft also provides a TTS interface in Windows systems, which can be called to implement offline TTS speech synthesis function.
This article will use the pyttsx3 library as a demonstration to write a speech synthesis gadget.
Install PyQt5 and its GUI design tools
# 安装PyQt5 pip install PyQt5 # 安装PyQt5设计器 pip install PyQt5Designer
The editor used in this article is VSCode, not PyCharm. There may be differences in how to use PyQt5, specifically It can be configured according to the actual situation during use.
Install pyttsx3
pip install pyttsx3
You can refer to the figure below to design a simple GUI interface. Since this article is mainly a functional example, the aesthetics of the interface are not considered.
The interface should have a text input box for inputting text to be converted into speech, and a play button to trigger the voice playback method. Speech speed, volume and language can be selected as needed.
Using the design tool of PyQt5, you can generate the following UI (XML) code based on the GUI interface configured above:
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Form</class> <widget class="QWidget" name="Form"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>313</width> <height>284</height> </rect> </property> <property name="windowTitle"> <string>语音合成器</string> </property> <property name="windowIcon"> <iconset> <normaloff>voice.ico</normaloff>voice.ico</iconset> </property> <widget class="QWidget" name="verticalLayoutWidget"> <property name="geometry"> <rect> <x>10</x> <y>10</y> <width>291</width> <height>261</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout"> <property name="spacing"> <number>20</number> </property> <item> <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QLabel" name="label"> <property name="text"> <string>播报文本</string> </property> <property name="alignment"> <set>Qt::AlignJustify|Qt::AlignTop</set> </property> </widget> </item> <item> <widget class="QTextEdit" name="tbx_text"/> </item> </layout> </item> <item> <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> <widget class="QLabel" name="label_3"> <property name="text"> <string>语速</string> </property> </widget> </item> <item> <widget class="QSlider" name="slider_rate"> <property name="maximum"> <number>300</number> </property> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> </widget> </item> <item> <widget class="QLabel" name="label_rate"> <property name="minimumSize"> <size> <width>30</width> <height>0</height> </size> </property> <property name="text"> <string>0</string> </property> <property name="alignment"> <set>Qt::AlignCenter</set> </property> </widget> </item> </layout> </item> <item> <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <widget class="QLabel" name="label_2"> <property name="text"> <string>音量</string> </property> </widget> </item> <item> <widget class="QSlider" name="slider_volumn"> <property name="maximum"> <number>100</number> </property> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> </widget> </item> <item> <widget class="QLabel" name="label_volumn"> <property name="minimumSize"> <size> <width>30</width> <height>0</height> </size> </property> <property name="text"> <string>0</string> </property> <property name="alignment"> <set>Qt::AlignCenter</set> </property> </widget> </item> </layout> </item> <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="label_4"> <property name="text"> <string>选择语言</string> </property> </widget> </item> <item> <widget class="QRadioButton" name="rbtn_zh"> <property name="text"> <string>中文</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item> <widget class="QRadioButton" name="rbtn_en"> <property name="text"> <string>英文</string> </property> </widget> </item> </layout> </item> <item> <layout class="QHBoxLayout" name="horizontalLayout_5"> <item> <widget class="QLabel" name="label_5"> <property name="minimumSize"> <size> <width>60</width> <height>0</height> </size> </property> <property name="text"> <string/> </property> </widget> </item> <item> <widget class="QPushButton" name="btn_play"> <property name="minimumSize"> <size> <width>0</width> <height>30</height> </size> </property> <property name="text"> <string>播放</string> </property> </widget> </item> </layout> </item> </layout> </widget> </widget> <resources/> <connections/> </ui>
Finally, using the interface tool of PyQt5, you can generate the following UI (XML) code based on the above UI code: The following form class:
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'd:\Program\VSCode\Python\TTS_PyQT\tts_form.ui' # # Created by: PyQt5 UI code generator 5.15.7 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets class Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") Form.resize(313, 284) icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap("./voice.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) Form.setWindowIcon(icon) self.verticalLayoutWidget = QtWidgets.QWidget(Form) self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 291, 261)) self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(20) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.label = QtWidgets.QLabel(self.verticalLayoutWidget) self.label.setAlignment(QtCore.Qt.AlignJustify | QtCore.Qt.AlignTop) self.label.setObjectName("label") self.horizontalLayout_2.addWidget(self.label) self.tbx_text = QtWidgets.QTextEdit(self.verticalLayoutWidget) self.tbx_text.setObjectName("tbx_text") self.horizontalLayout_2.addWidget(self.tbx_text) self.verticalLayout.addLayout(self.horizontalLayout_2) self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.label_3 = QtWidgets.QLabel(self.verticalLayoutWidget) self.label_3.setObjectName("label_3") self.horizontalLayout_4.addWidget(self.label_3) self.slider_rate = QtWidgets.QSlider(self.verticalLayoutWidget) self.slider_rate.setMaximum(300) self.slider_rate.setOrientation(QtCore.Qt.Horizontal) self.slider_rate.setObjectName("slider_rate") self.horizontalLayout_4.addWidget(self.slider_rate) self.label_rate = QtWidgets.QLabel(self.verticalLayoutWidget) self.label_rate.setMinimumSize(QtCore.QSize(30, 0)) self.label_rate.setAlignment(QtCore.Qt.AlignCenter) self.label_rate.setObjectName("label_rate") self.horizontalLayout_4.addWidget(self.label_rate) self.verticalLayout.addLayout(self.horizontalLayout_4) self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget) self.label_2.setObjectName("label_2") self.horizontalLayout_3.addWidget(self.label_2) self.slider_volumn = QtWidgets.QSlider(self.verticalLayoutWidget) self.slider_volumn.setMaximum(100) self.slider_volumn.setOrientation(QtCore.Qt.Horizontal) self.slider_volumn.setObjectName("slider_volumn") self.horizontalLayout_3.addWidget(self.slider_volumn) self.label_volumn = QtWidgets.QLabel(self.verticalLayoutWidget) self.label_volumn.setMinimumSize(QtCore.QSize(30, 0)) self.label_volumn.setAlignment(QtCore.Qt.AlignCenter) self.label_volumn.setObjectName("label_volumn") self.horizontalLayout_3.addWidget(self.label_volumn) self.verticalLayout.addLayout(self.horizontalLayout_3) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.label_4 = QtWidgets.QLabel(self.verticalLayoutWidget) self.label_4.setObjectName("label_4") self.horizontalLayout.addWidget(self.label_4) self.rbtn_zh = QtWidgets.QRadioButton(self.verticalLayoutWidget) self.rbtn_zh.setChecked(True) self.rbtn_zh.setObjectName("rbtn_zh") self.horizontalLayout.addWidget(self.rbtn_zh) self.rbtn_en = QtWidgets.QRadioButton(self.verticalLayoutWidget) self.rbtn_en.setObjectName("rbtn_en") self.horizontalLayout.addWidget(self.rbtn_en) self.verticalLayout.addLayout(self.horizontalLayout) self.horizontalLayout_5 = QtWidgets.QHBoxLayout() self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.label_5 = QtWidgets.QLabel(self.verticalLayoutWidget) self.label_5.setMinimumSize(QtCore.QSize(60, 0)) self.label_5.setText("") self.label_5.setObjectName("label_5") self.horizontalLayout_5.addWidget(self.label_5) self.btn_play = QtWidgets.QPushButton(self.verticalLayoutWidget) self.btn_play.setMinimumSize(QtCore.QSize(0, 30)) self.btn_play.setObjectName("btn_play") self.horizontalLayout_5.addWidget(self.btn_play) self.verticalLayout.addLayout(self.horizontalLayout_5) self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "语音合成器")) self.label.setText(_translate("Form", "播报文本")) self.label_3.setText(_translate("Form", "语速")) self.label_rate.setText(_translate("Form", "0")) self.label_2.setText(_translate("Form", "音量")) self.label_volumn.setText(_translate("Form", "0")) self.label_4.setText(_translate("Form", "选择语言")) self.rbtn_zh.setText(_translate("Form", "中文")) self.rbtn_en.setText(_translate("Form", "英文")) self.btn_play.setText(_translate("Form", "播放"))
If you copy this code directly, the icon may be lost. This requires modifying the icon configuration according to the actual situation and adding the ico icon file to be used.
First we need to initialize and obtain the speech engine object for speech synthesis.
# tts对象 engine = pyttsx3.init()
We can modify the properties of the speech synthesis object through the setProperty method of the object:
Attribute name | Explanation |
rate | Integer speech rate expressed in words per minute |
volume | Volume, take The value range is [0.0, 1.0] |
voices | String identifier of the voice |
Voice tool The class code is as follows. For the meaning of the code, please refer to the comments:
import pyttsx3 class VoiceEngine(): ''' tts 语音工具类 ''' def __init__(self): ''' 初始化 ''' # tts对象 self.__engine = pyttsx3.init() # 语速 self.__rate = 150 # 音量 self.__volume = 100 # 语音ID,0为中文,1为英文 self.__voice = 0 @property def Rate(self): ''' 语速属性 ''' return self.__rate @Rate.setter def Rate(self, value): self.__rate = value @property def Volume(self): ''' 音量属性 ''' return self.__volume @Volume.setter def Volume(self, value): self.__volume = value @property def VoiceID(self): ''' 语音ID:0 -- 中文;1 -- 英文 ''' return self.__voice @VoiceID.setter def VoiceID(self, value): self.__voice = value def Say(self, text): ''' 播放语音 ''' self.__engine.setProperty('rate', self.__rate) self.__engine.setProperty('volume', self.__volume) # 获取可用语音列表,并设置语音 voices = self.__engine.getProperty('voices') self.__engine.setProperty('voice', voices[self.__voice].id) # 保存语音文件 # self.__engine.save_to_file(text, 'test.mp3') self.__engine.say(text) self.__engine.runAndWait() self.__engine.stop()
We can create a form class that inherits from the PyQt5 we just created, and provide drag events for the form Register a callback function with the click event, and create an instance of the voice tool class to implement the voice operation that needs to be performed when the specified event is triggered.
import sys import _thread as th from PyQt5.QtWidgets import QMainWindow, QApplication from Ui_tts_form import Ui_Form class MainWindow(QMainWindow, Ui_Form): ''' 窗体类 ''' def __init__(self, parent=None): ''' 初始化窗体 ''' super(MainWindow, self).__init__(parent) self.setupUi(self) # 获取tts工具类实例 self.engine = VoiceEngine() self.__isPlaying = False # 设置初始文本 self.tbx_text.setText('床前明月光,疑似地上霜。\n举头望明月,低头思故乡。') # 进度条数据绑定到label中显示 self.slider_rate.valueChanged.connect(self.setRateTextValue) self.slider_volumn.valueChanged.connect(self.setVolumnTextValue) # 设置进度条初始值 self.slider_rate.setValue(self.engine.Rate) self.slider_volumn.setValue(self.engine.Volume) # RadioButton选择事件 self.rbtn_zh.toggled.connect(self.onSelectVoice_zh) self.rbtn_en.toggled.connect(self.onSelectVoice_en) # 播放按钮点击事件 self.btn_play.clicked.connect(self.onPlayButtonClick) def setRateTextValue(self): ''' 修改语速label文本值 ''' value = self.slider_rate.value() self.label_rate.setText(str(value)) self.engine.Rate = value def setVolumnTextValue(self): ''' 修改音量label文本值 ''' value = self.slider_volumn.value() self.label_volumn.setText(str(value / 100)) self.engine.Volume = value def onSelectVoice_zh(self): ''' 修改中文的语音配置及默认播放文本 ''' self.tbx_text.setText('床前明月光,疑似地上霜。\n举头望明月,低头思故乡。') self.engine.VoiceID = 0 def onSelectVoice_en(self): ''' 修改英文的语音配置及默认的播放文本 ''' self.tbx_text.setText('Hello World') self.engine.VoiceID = 1 def playVoice(self): ''' 播放 ''' if self.__isPlaying is not True: self.__isPlaying = True text = self.tbx_text.toPlainText() self.engine.Say(text) self.__isPlaying = False def onPlayButtonClick(self): ''' 播放按钮点击事件 开启线程新线程播放语音,避免窗体因为语音播放而假卡死 ''' th.start_new_thread(self.playVoice, ())
import sys import _thread as th from PyQt5.QtWidgets import QMainWindow, QApplication from Ui_tts_form import Ui_Form import pyttsx3 class VoiceEngine(): ''' tts 语音工具类 ''' def __init__(self): ''' 初始化 ''' # tts对象 self.__engine = pyttsx3.init() # 语速 self.__rate = 150 # 音量 self.__volume = 100 # 语音ID,0为中文,1为英文 self.__voice = 0 @property def Rate(self): ''' 语速属性 ''' return self.__rate @Rate.setter def Rate(self, value): self.__rate = value @property def Volume(self): ''' 音量属性 ''' return self.__volume @Volume.setter def Volume(self, value): self.__volume = value @property def VoiceID(self): ''' 语音ID:0 -- 中文;1 -- 英文 ''' return self.__voice @VoiceID.setter def VoiceID(self, value): self.__voice = value def Say(self, text): ''' 播放语音 ''' self.__engine.setProperty('rate', self.__rate) self.__engine.setProperty('volume', self.__volume) voices = self.__engine.getProperty('voices') self.__engine.setProperty('voice', voices[self.__voice]) # 保存语音文件 # self.__engine.save_to_file(text, 'test.mp3') self.__engine.say(text) self.__engine.runAndWait() self.__engine.stop() class MainWindow(QMainWindow, Ui_Form): ''' 窗体类 ''' def __init__(self, parent=None): ''' 初始化窗体 ''' super(MainWindow, self).__init__(parent) self.setupUi(self) # 获取tts工具类实例 self.engine = VoiceEngine() self.__isPlaying = False # 设置初始文本 self.tbx_text.setText('床前明月光,疑似地上霜。\n举头望明月,低头思故乡。') # 进度条数据绑定到label中显示 self.slider_rate.valueChanged.connect(self.setRateTextValue) self.slider_volumn.valueChanged.connect(self.setVolumnTextValue) # 设置进度条初始值 self.slider_rate.setValue(self.engine.Rate) self.slider_volumn.setValue(self.engine.Volume) # RadioButton选择事件 self.rbtn_zh.toggled.connect(self.onSelectVoice_zh) self.rbtn_en.toggled.connect(self.onSelectVoice_en) # 播放按钮点击事件 self.btn_play.clicked.connect(self.onPlayButtonClick) def setRateTextValue(self): ''' 修改语速label文本值 ''' value = self.slider_rate.value() self.label_rate.setText(str(value)) self.engine.Rate = value def setVolumnTextValue(self): ''' 修改音量label文本值 ''' value = self.slider_volumn.value() self.label_volumn.setText(str(value / 100)) self.engine.Volume = value def onSelectVoice_zh(self): ''' 修改中文的语音配置及默认播放文本 ''' self.tbx_text.setText('床前明月光,疑似地上霜。\n举头望明月,低头思故乡。') self.engine.VoiceID = 0 def onSelectVoice_en(self): ''' 修改英文的语音配置及默认的播放文本 ''' self.tbx_text.setText('Hello World') self.engine.VoiceID = 1 def playVoice(self): ''' 播放 ''' if self.__isPlaying is not True: self.__isPlaying = True text = self.tbx_text.toPlainText() self.engine.Say(text) self.__isPlaying = False def onPlayButtonClick(self): ''' 修改语速label文本值 ''' th.start_new_thread(self.playVoice, ()) if __name__ == "__main__": ''' 主函数 ''' app = QApplication(sys.argv) form = MainWindow() form.show() sys.exit(app.exec_())
The above is the detailed content of How to implement Python speech synthesis gadget. For more information, please follow other related articles on the PHP Chinese website!