前提
tkinterとwhisperとsoundcardを用いて、再生中の動画の文字起こしができるアプリを作成中です。
実現したいこと
・GUIのボタンを押すと、音声を録音しながらリアルタイムにwhisperで文字認識をするようにしたいです。
発生している問題・エラーメッセージ
ボタンを押すとモデルのロードまでは完了しますが、その後の処理(音声の処理部分)でエラーが出ます。
Exception in thread Thread-1 (do_whisper): Traceback (most recent call last): File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1009, in _bootstrap_inner self.run() File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\threading.py", line 946, in run self._target(*self._args, **self._kwargs) File "C:\Users\user\Documents\app\do_whisper.py", line 15, in do_whisper whisper_main() File "C:\Users\user\Documents\app\do_whisper.py", line 60, in whisper_main with sc.get_microphone(id=str(sc.default_speaker().name), include_loopback=True).recorder(samplerate=SAMPLE_RATE, channels=1) as mic: File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\soundcard\mediafoundation.py", line 116, in default_speaker with _DeviceEnumerator() as enum: File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\soundcard\mediafoundation.py", line 216, in __init__ _com.check_error(hr) File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\soundcard\mediafoundation.py", line 98, in check_error raise RuntimeError('Error {}'.format(hex(hresult+2**32))) RuntimeError: Error 0x800401f0
該当のソースコード
do_main.pyを実行します。
do_main.py
Python
1import tkinter as tk 2from do_whisper import * 3import threading 4 5class Application(tk.Frame): 6 def __init__(self, master = None): 7 super().__init__(master) 8 9 self.master.geometry("250x250") 10 self.txt = tk.StringVar(value="test") 11 12 button_top = tk.Button(self.master, text = "TOP", width = 8, command=self.changeLabel) 13 label = tk.Label(self.master, textvariable=self.txt, font=("Ubunt Mono", 20)) 14 15 button_top.pack(side = tk.TOP) 16 label.pack() 17 18 def changeLabel(self): 19 self.txt.set("Start...") 20 t = threading.Thread(target=do_whisper, args=(True,), daemon=True) 21 t.start() 22 23if __name__ == "__main__": 24 root = tk.Tk() 25 app = Application(master = root) 26 app.mainloop()
do_whisper.py
Python
1import whisper 2import soundcard as sc 3import threading 4import queue 5import numpy as np 6import argparse 7import threading 8 9flag = True 10 11def do_whisper(do_flag): 12 global flag 13 if do_flag == True: 14 flag = True 15 whisper_main() 16 else: 17 flag = False 18 19def whisper_main(): 20 SAMPLE_RATE = 16000 21 INTERVAL = 3 22 BUFFER_SIZE = 4096 23 24 parser = argparse.ArgumentParser() 25 parser.add_argument('--model', default='small') 26 args = parser.parse_args() 27 28 print('Loading model...') 29 model = whisper.load_model(args.model) 30 print('Done') 31 32 q = queue.Queue() 33 b = np.ones(100) / 100 34 35 options = whisper.DecodingOptions(fp16=False) 36 37 def recognize(): 38 while True: 39 audio = q.get() 40 if (audio ** 2).max() > 0.001: 41 audio = whisper.pad_or_trim(audio) 42 43 # make log-Mel spectrogram and move to the same device as the model 44 mel = whisper.log_mel_spectrogram(audio).to(model.device) 45 46 # detect the spoken language 47 _, probs = model.detect_language(mel) 48 49 # decode the audio 50 result = whisper.decode(model, mel, options) 51 52 # print the recognized text 53 print(f'{max(probs, key=probs.get)}: {result.text}') 54 55 56 th_recognize = threading.Thread(target=recognize, daemon=True) 57 th_recognize.start() 58 59 # start recording 60 with sc.get_microphone(id=str(sc.default_speaker().name), include_loopback=True).recorder(samplerate=SAMPLE_RATE, channels=1) as mic: 61 audio = np.empty(SAMPLE_RATE * INTERVAL + BUFFER_SIZE, dtype=np.float32) 62 n = 0 63 while True: 64 while n < SAMPLE_RATE * INTERVAL: 65 data = mic.record(BUFFER_SIZE) 66 audio[n:n+len(data)] = data.reshape(-1) 67 n += len(data) 68 69 # find silent periods 70 m = n * 4 // 5 71 vol = np.convolve(audio[m:n] ** 2, b, 'same') 72 m += vol.argmin() 73 q.put(audio[:m]) 74 75 audio_prev = audio 76 audio = np.empty(SAMPLE_RATE * INTERVAL + BUFFER_SIZE, dtype=np.float32) 77 audio[:n-m] = audio_prev[m:n] 78 n = n-m
試したこと
・kivyを使用して同様のアプリを作成した際は問題なく実行できましたが、tkinterだと実行できませんでした。
・do_whisper.pyのwhisper_mainはこちらのサイトのコードをそのまま使っています。
・上記サイトで「メインスレッド以外では動作しない」とあるため、threadingを使用しているのが不味いと予想していますが、kivyでは動作しtkinterでは動作しないという理由が分かりません。また解決方法も見当がつかず、ご教示いただきたいです。
補足情報(FW/ツールのバージョンなど)
Wiondows10
Python 3.10.2
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/02/04 09:27