Многопоточность QThread в PyQt5
У меня проект по распознаванию речи и переводу её в текст.
Для этого я использую библиотеку speech_recognition.
Проблема в том, что я делаю для этого всего интерфейс при помощи PyQt5 и при распознавании речи интерфейс зависает.
Я пересмотрел не мало видео и статей по многопоточности в PyQt5 и везде практически одинаковый код, в зависимости от примера, но у меня это не работает.
Также мне нужно менять индикатор о записи речи через 1 секунду после начала записи, так как 1 секунда уходит на обработку шума как я понимаю.
Я пробовал просто threading использовать, и это иногда работает, но через раз и с ошибками типа:
QObject: Cannot create children for a parent that is in a different thread.
и
(Parent is QTextDocument(0x1e42b91a200), parent's thread is QThread(0x1e421aba7c0), current thread is QThread(0x1e42b9196c0).
Также пробовал использовать QThread, но с ним интерфейс зависает и не меняются индикаторы, хотя распознавание речи работает и выводит мне текст.
Я только недавно начал работать с PyQt5 и не понимаю как сделать отдельный поток способный изменять интерфейс в основном.
Текущий код:
Основной класс:
class MyClass(QMainWindow):
def __init__(self):
super().__init__()
f = io.StringIO(ui)
uic.loadUi(f, self)
self.record_button.clicked.connect(self.Record)
return
def Record(self):
self.th = MyThread()
self.th.signal.connect(self.GetSignal)
self.th.start()
return
def GetSignal(self, signal):
global str_text
if signal == "Слушаю":
QThread.msleep(1000)
self.status_label.setText("Слушаю")
elif signal == "":
self.status_label.setText("")
self.result_textedit.setText("Распознанный текст")
Класс моего потока:
class MyThread(PyQt5.QtCore.QThread):
signal = PyQt5.QtCore.pyqtSignal(str)
def __init__(self):
PyQt5.QtCore.QThread.__init__(self)
return
def run(self):
record = speech_recognition.Recognizer()
record.pause_threshold = 1
with speech_recognition.Microphone() as microphone:
record.adjust_for_ambient_noise(source=microphone, duration=1)
self.signal.emit("Слушаю")
audio = record.listen(source=microphone)
query = record.recognize_google(audio_data=audio, language="ru-RU")
self.signal.emit("")
return
Ответы (1 шт):
Пожалуйста, всегда предоставляйте минимально-воспроизводимый пример.
Сегодня ваш пример не воспроизводимый, но вам повезло у меня есть, то что вас интересует.
import speech_recognition as sr
from PyQt5 import QtCore, QtGui, QtWidgets
# для отладки
def log_uncaught_exceptions(ex_cls, ex, tb):
text = '{}: {}:\n'.format(ex_cls.__name__, ex)
import traceback
text += ''.join(traceback.format_tb(tb))
print(text)
QtWidgets.QMessageBox.critical(None, 'Error', text)
quit()
import sys
sys.excepthook = log_uncaught_exceptions
class SpeechRecognitionThread(QtCore.QThread):
about_text = QtCore.pyqtSignal(str)
language = "en-US"
def run(self):
try:
r = sr.Recognizer()
self.about_text.emit("Скажите что-нибудь...")
with sr.Microphone() as source:
audio = r.listen(source)
self.about_text.emit("Анализирую речь...")
text = r.recognize_google(audio, language=self.language)
self.about_text.emit('Фраза: "{}"'.format(text))
except sr.UnknownValueError:
self.about_text.emit("Робот не расслышал фразу")
except sr.RequestError as e:
self.about_text.emit("Ошибка сервиса: {}".format(e))
except Exception as e:
self.about_text.emit("Ошибка: {}".format(e))
finally:
self.about_text.emit('')
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Микрофон распознавания речи Google')
self.pb_microphone = QtWidgets.QPushButton('? SPEAK')
self.pb_microphone.setFont(QtGui.QFont('Arial', 16))
self.cb_lang = QtWidgets.QComboBox()
self.cb_lang.addItems(["en-US", "ru-RU"])
self.cb_lang.setCurrentIndex(1)
self.pte_result = QtWidgets.QPlainTextEdit()
self.pte_result.setFont(QtGui.QFont('Arial', 12))
self.pte_result.setReadOnly(True)
self.progress_bar = QtWidgets.QProgressBar()
self.progress_bar.setTextVisible(False)
self.progress_bar.hide()
self.progress_bar.setRange(0, 0)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.pb_microphone)
layout.addWidget(self.cb_lang)
layout.addWidget(self.pte_result)
layout.addWidget(self.progress_bar)
self.thread = SpeechRecognitionThread()
self.thread.about_text.connect(self.pte_result.appendPlainText)
self.thread.started.connect(self.progress_bar.show)
self.thread.finished.connect(self._speech_recognition_finish)
# Запустить распознавание речи
self.pb_microphone.clicked.connect(self._speech_recognition_start)
def _speech_recognition_start(self):
self.pb_microphone.setEnabled(False)
self.pte_result.clear()
self.thread.language = self.cb_lang.currentText()
self.thread.start()
def _speech_recognition_finish(self):
self.pb_microphone.setEnabled(True)
self.progress_bar.hide()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.resize(500, 500)
w.show()
sys.exit(app.exec())
Попробуйте поизучать. Если что-то конкретное будет не понятно - спросите.
