Answer the question
In order to leave comments, you need to log in
When playing pyttsx3, the program hangs. What to do?
Hello! I'm making a python program with a GUI for text-to-speech synthesis (there's also a function to save an audio file and select a voice). I have some problem. When you click on the listen button (that is, the playback of the text by the voice of the bot), the program stops until the playback ends (tobish cannot press buttons, etc.). <- This happens if I just run the script by clicking on it. But when run in PyCharm everything works fine. During playback, you can press buttons and further interact with the program.
For the solution, I decided to use multithreading, but when using it, an error occurred.
PS For speech synthesis I used pyttsx3
More details with videos -
Code:
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox, QFileDialog
import pyttsx3
import re
from os import chdir
# Replace way with just in case
chdir(u"{0}".format(os.getcwd().replace("/", "\\")))
engine = pyttsx3.init() # pyttsx3 initialization
# Get system voices
voices = engine.getProperty("voices")
voicesList = []
[voicesList.append(voice.name) for voice in voices]
class UiMainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(790, 618)
MainWindow.setMinimumSize(QtCore.QSize(790, 618))
MainWindow.setMaximumSize(QtCore.QSize(790, 618))
MainWindow.setStyleSheet("")
MainWindow.setWindowIcon(QtGui.QIcon("icons\\window_icon.png"))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.textEdit = QtWidgets.QPlainTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(20, 80, 751, 311))
self.textEdit.setObjectName("text")
self.windowLabel = QtWidgets.QLabel(self.centralwidget)
self.windowLabel.setGeometry(QtCore.QRect(280, 10, 241, 31))
font = QtGui.QFont()
font.setFamily("Zelek")
font.setPointSize(18)
self.windowLabel.setFont(font)
self.windowLabel.setObjectName("windowLabel")
self.choiceVoice = QtWidgets.QComboBox(self.centralwidget)
self.choiceVoice.setGeometry(QtCore.QRect(170, 430, 461, 41))
self.choiceVoice.setAccessibleDescription("")
self.choiceVoice.setCurrentText("")
self.choiceVoice.setIconSize(QtCore.QSize(32, 32))
self.choiceVoice.setObjectName("selectVoice")
self.choiceVoice.addItems(voicesList)
self.choiceVoice.setCurrentIndex(0)
self.choiceSaveFileButton = QtWidgets.QPushButton(self.centralwidget)
self.choiceSaveFileButton.setGeometry(QtCore.QRect(170, 550, 461, 41))
font = QtGui.QFont()
font.setFamily("Zelek")
font.setPointSize(15)
font.setBold(True)
font.setWeight(75)
self.choiceSaveFileButton.setFont(font)
self.choiceSaveFileButton.setObjectName("selectDirectoryButton")
self.textLabel = QtWidgets.QLabel(self.centralwidget)
self.textLabel.setGeometry(QtCore.QRect(330, 50, 131, 21))
font = QtGui.QFont()
font.setFamily("Zelek")
font.setPointSize(10)
self.textLabel.setFont(font)
self.textLabel.setStyleSheet("")
self.textLabel.setAlignment(QtCore.Qt.AlignCenter)
self.textLabel.setObjectName("textLabel")
self.voiceLabel = QtWidgets.QLabel(self.centralwidget)
self.voiceLabel.setGeometry(QtCore.QRect(220, 400, 350, 21))
font = QtGui.QFont()
font.setFamily("Zelek")
font.setPointSize(10)
self.voiceLabel.setFont(font)
self.voiceLabel.setStyleSheet("")
self.voiceLabel.setAlignment(QtCore.Qt.AlignCenter)
self.voiceLabel.setObjectName("voiceLabel")
self.listenButton = QtWidgets.QPushButton(self.centralwidget)
self.listenButton.setGeometry(QtCore.QRect(170, 490, 461, 41))
font = QtGui.QFont()
font.setFamily("Zelek")
font.setPointSize(15)
self.listenButton.setFont(font)
self.listenButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 790, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.choiceVoice.setCurrentIndex(-1)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.addFunctional()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Синтез текста в речь"))
self.windowLabel.setText(_translate("MainWindow", "Синтез текста в речь"))
self.choiceSaveFileButton.setText(_translate("MainWindow", "Сохранить аудиофайл"))
self.textLabel.setText(_translate("MainWindow", "Введите ваш текст"))
self.voiceLabel.setText(_translate("MainWindow", "Выберите голос (установленный на вашей системе)"))
self.listenButton.setText(_translate("MainWindow", "Слушать"))
def addFunctional(self):
def start():
saveFile = QFileDialog.getSaveFileName(filter=".mp3")[0]
if saveFile != "":
if not saveFile.endswith(".mp3"):
saveFile += ".mp3"
text = self.textEdit.toPlainText()
voiceName = self.choiceVoice.currentText()
errorMessage = QMessageBox()
errorMessage.setIcon(QMessageBox.Warning)
errorMessage.setWindowTitle("Ошибка!")
if (text == "" or [text] == re.findall("[ ]+", text) or voiceName == "" or saveFile == ""):
if text == "" or [text] == re.findall("[ ]+", text):
errorMessage.setText("Введите текст в поле для ввода текста!")
errorMessage.exec_()
elif voiceName == "":
errorMessage.setText("Выберите голос установленный на вашей системе!")
errorMessage.exec_()
elif saveFile == "":
errorMessage.setText("Выберите куда сохранять файл!")
errorMessage.exec_()
else:
voices = engine.getProperty("voices")
for voice in voices:
if voice.name == voiceName:
engine.setProperty("voice", voice.id)
break
engine.save_to_file(text, saveFile)
engine.runAndWait()
message = QMessageBox()
message.setIcon(QMessageBox.Information)
message.setWindowTitle("Операция успешно выполнена!")
message.setText(f"Операция успешно выполнена! Аудиофайл сохранен.\nЕсли вы ничего не услышали, то возможно выбранный\nвами голос не поддерживает тот, или иной язык.")
message.exec_()
def listenOrStopListenText():
if self.listenButton.text() == "Слушать":
text = self.textEdit.toPlainText()
voiceName = self.choiceVoice.currentText()
voices = engine.getProperty("voices")
for voice in voices:
if voice.name == voiceName:
engine.setProperty("voice", voice.id)
break
self.listenButton.setText("Остановить")
engine.say(text)
engine.runAndWait()
self.listenButton.setText("Слушать")
elif self.listenButton.text() == "Остановить":
engine.stop()
self.listenButton.clicked.connect(listenOrStopListenText)
self.choiceSaveFileButton.clicked.connect(start)
# Application launch
if __name__ == "__main__":
application = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = UiMainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(application.exec_())
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question