Всем привет! Я делаю программу на python с графическим интерфейсом для синтеза текста в речь (также есть функция сохранения аудиофайла и выбора голоса). У меня возникла какая-то проблема. При нажатии на кнопку слушать (то есть воспроизведения текста голосом бота) программа останавливается пока не закончится воспроизведение (тобиш нельзя нажимать кнопки и т.д). <— Это случается если я просто запускаю скрипт нажав на него. Но при запуске в PyCharm все прекрасно работает. При воспроизведении можно нажимать кнопки и дальше взаимодействовать с программа.
Для решения решил использовать многопоточность но при его использовании возникала ошибка.
P.S Для синтеза речи использовал pyttsx3
Подробнее с видеоматериалами -
Код:
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_())