Многопоточность 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 шт):

Автор решения: S. Nick

Пожалуйста, всегда предоставляйте минимально-воспроизводимый пример.
Сегодня ваш пример не воспроизводимый, но вам повезло у меня есть, то что вас интересует.

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())       

введите сюда описание изображения

Попробуйте поизучать. Если что-то конкретное будет не понятно - спросите.

→ Ссылка