Вывод текста записанного с микрофона, Python, Vosk
Имеется код небольшой программы, которая должна распознавать речь и переводить её в текст.
Всё хорошо работает за исключением того, что после того как текст высвечивается на экране, через пару секунд он исчезает/обновляется,
а мне надо чтобы он оставался.
После нажатия кнопки end запись должна прекратиться.
main.py:
from gui import Ui_Dialog
from PyQt5 import QtWidgets
from vosk import Model, KaldiRecognizer
import pyaudio
import threading
import time
CHUNK = 1024 # определяет форму ауди сигнала
FRT = pyaudio.paInt16 # шестнадцатибитный формат задает значение амплитуды
CHAN = 1 # канал записи звука
RT = 44100 # частота
sec = 0
REC_SEC = 5 # длина записи
OUTPUT = "output.wav"
a = 50
class GuiProgram(Ui_Dialog):
""" Класс контроллер - интерпретирует действия пользователя """
def __init__(self, dialog: QtWidgets.QDialog) -> None:
""" Вызывается при создании нового объекта класса """
# Создание окна
Ui_Dialog.__init__(self)
# Установка пользовательского интерфейс
self.setupUi(dialog)
# Обработка нажатий клавиш
self.strt_btn.clicked.connect(self.start_record)
self.end_btn.clicked.connect(self.end_record)
self.stream = None
self.start_record = False
self.frames = []
self.pyaudio = pyaudio.PyAudio()
self.xte = None
def start_record(self):
self.label.setText("Recording...")
model = Model(r"vosk-model-small-ru-0.22")
self.rec = KaldiRecognizer(model, 44100)
self.pyaudio = pyaudio.PyAudio()
self.stream = self.pyaudio.open(
format=FRT,
channels=CHAN,
rate=RT,
input=True,
frames_per_buffer=CHUNK
)
self.start_record = True
self.thread = threading.Thread(target=self.record)
self.thread.start()
def record(self):
while self.start_record:
data = self.stream.read(44100)
if len(data) == 0:
break
self.label.setText(self.rec.Result()
if self.rec.AcceptWaveform(data)
else self.rec.PartialResult())
self.xte = (self.rec.Result()
if self.rec.AcceptWaveform(data)
else self.rec.PartialResult())
self.label.setText(self.rec.FinalResult())
def end_record(self):
self.start_record = False
print("done")
self.label.setText(self.xte)
Ответы (1 шт):
У меня не получилось проверить ваш код.
Строка model = Model(r"vosk-model-small-ru-0.22")
меня отругала: Folder 'vosk-model-en-us-0.22' does not contain model files...
И я не знаю все ли хорошо у вас работает, но я точно знаю, что взаимодействие с виджетами в дополнительном потоке не рекомендуется, т.к. это не безопасно.
Я не понимаю, почему вы решили отображать текст в виджете QLabel?
в котором setText(const QString &) удаляет все предыдущее содержимое.
Мне кажется, что ваш код должен выглядеть примерно так, проверьте.
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.Qt import *
from vosk import Model, KaldiRecognizer # pip install vosk
import pyaudio
CHUNK = 1024 # определяет форму ауди сигнала
FRT = pyaudio.paInt16 # шестнадцатибитный формат задает значение амплитуды
CHAN = 1 # канал записи звука
RT = 44100 # частота
sec = 0 # ???
REC_SEC = 5 # длина записи
OUTPUT = "output.wav" # ???
a = 50 # ???
class RecordingThread(QThread):
recorded_text = pyqtSignal(str)
def __init__(self, stream, rec):
super().__init__()
self.stream = stream
self.rec = rec
self.flag_record = True
self.xte = None # ???
def run(self):
while self.flag_record:
data = self.stream.read(44100)
if not data:
# нет данных
self.recorded_text.emit(f'Нет данных ?')
else:
self.xte = self.rec.Result() \
if self.rec.AcceptWaveform(data) \
else self.rec.PartialResult()
self.recorded_text.emit(f'{self.xte}')
self.msleep(100) # 100 мс, я не знаю какая пауза здесь нужна?
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.stream = None # ?
self.flag_record = False # ?
self.frames = [] # ?
self.pyaudio = pyaudio.PyAudio()
self.start_btn = QPushButton('? Start')
self.start_btn.setFont(QFont('Arial', 16))
self.start_btn.clicked.connect(self.start_record)
self.end_btn = QPushButton('? Stop')
self.end_btn.setFont(QFont('Arial', 16))
self.end_btn.setEnabled(False)
self.end_btn.clicked.connect(self.end_record)
self.result = QPlainTextEdit()
self.result.setFont(QFont('Arial', 12))
self.result.setReadOnly(True)
layout = QGridLayout(self)
layout.addWidget(self.start_btn, 0, 0)
layout.addWidget(self.end_btn, 0, 1)
layout.addWidget(self.result, 1, 0, 1, 2)
def start_record(self):
self.result.appendPlainText("Recording...")
self.start_btn.setEnabled(False)
self.end_btn.setEnabled(True)
model = Model(r"vosk-model-small-ru-0.22")
self.rec = KaldiRecognizer(model, 44100)
self.pyaudio = pyaudio.PyAudio()
self.stream = self.pyaudio.open(
format=FRT,
channels=CHAN,
rate=RT,
input=True,
frames_per_buffer=CHUNK
)
self.thread = RecordingThread(self.stream, self.rec)
self.thread.recorded_text.connect(self.result.appendPlainText)
self.thread.start()
def end_record(self):
self.thread.flag_record = False
self.result.appendPlainText("End Recording.\n")
self.start_btn.setEnabled(True)
self.end_btn.setEnabled(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.resize(500, 400)
w.show()
sys.exit(app.exec())
