オフラインでVosk を使ってマイクに喋りかけて音声を文字起こしする
インストール
pip install vosk
vosk-model-ja-0.22

コード
import tkinter as tk
from tkinter import scrolledtext as tk_scrolledtext
import time
from tkinter import messagebox
import threading
import queue
from vosk import Model, KaldiRecognizer
import pyaudio
import json
SAMPLE_RATE = 44100
MODEL_PATH = "model/vosk-model-ja-0.22" # VOSKのモデルパス
# ハルシネーションで出力される可能性があるテキストを定義
hallucinationTexts = [
"ご視聴ありがとうございました",
"Thanks for watching!",
]
# VOSKモデルの初期化
model = Model(MODEL_PATH)
recognizer = KaldiRecognizer(model, SAMPLE_RATE)
# 録音スレッドの処理
def record_audio():
global recording
global th2
global q
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=SAMPLE_RATE, input=True, frames_per_buffer=4000)
stream.start_stream()
while recording: # recordingがTrueの間、録音を継続
print('record_audio')
data = stream.read(4000, exception_on_overflow=False)
q.put(data)
print(str(q.qsize()) + ' Queue')
if not th2.is_alive():
th2 = threading.Thread(target=audio_to_text)
th2.start()
stream.stop_stream()
stream.close()
p.terminate()
# 音声を文字に変換する関数
def audio_to_text():
global q
print('audio_to_text')
while not q.empty():
print('audio_to_text2')
print(str(q.qsize()) + ' Queue')
data = q.get()
if recognizer.AcceptWaveform(data):
result = json.loads(recognizer.Result())
text = result.get("text", "")
else:
text = ""
print(f'VOSK Result: {text}')
if text in hallucinationTexts or not text:
continue
else:
output_text.insert(tk.END, f'{text}\n')
output_text.see(tk.END)
time.sleep(0.1)
# 録音を開始する関数
def start_recording():
global recording
global th
global th2
recording = True
th = threading.Thread(target=record_audio)
th.start()
print("start_recording ...")
th2 = threading.Thread(target=audio_to_text)
th2.start()
# 録音を停止する関数
def stop_recording():
global recording
recording = False
print("stop_recording ...")
# 録音ボタンがクリックされたときの処理
def toggle_recording():
global recording
if recording:
# 録音を停止
stop_recording()
record_button.config(text="Start Recording")
else:
# 録音を開始
start_recording()
record_button.config(text="Stop Recording")
def delete_window():
global recording
global starting
global th
global th2
global q
# 録音を停止
stop_recording()
record_button.config(text="Start Recording")
record_button["state"] = "disabled"
if not starting:
root.destroy()
elif q.empty() and not th.is_alive() and not th2.is_alive():
print(str(q.qsize()) + ' Queue')
root.destroy()
else:
messagebox.showerror('error', str(q.qsize()) + ' Queue or running. Wait a minute')
# クリアボタンとコピー用関数
def clear_text():
output_text.delete("1.0", tk.END)
def copy_text():
root.clipboard_clear()
root.clipboard_append(output_text.get("1.0", tk.END))
root.update() # クリップボードを更新
# messagebox.showinfo("コピー完了", "テキストがクリップボードにコピーされました!")
if __name__ == "__main__":
# オーディオキューを作成
q = queue.Queue()
# 録音中かどうかを示すフラグ
recording = False
starting = False
# Tkinterウィンドウを作成
root = tk.Tk()
root.title("Speech Recognition App")
# 録音ボタンを作成
record_button = tk.Button(root, text="Start Recording", command=toggle_recording)
record_button.pack(fill="x")
# 新しいボタンを追加
clear_button = tk.Button(root, text="クリア", command=clear_text)
clear_button.pack(fill="x")
copy_button = tk.Button(root, text="コピー", command=copy_text)
copy_button.pack(fill="x")
# 認識結果を表示するテキストウィジェットを作成
output_text = tk_scrolledtext.ScrolledText(root, width=70, height=10, font=('Arial', 14))
output_text.pack(pady=10)
root.protocol("WM_DELETE_WINDOW", delete_window)
print('Loading model...')
print('Done')
# GUIを表示
root.mainloop()
ディスカッション
コメント一覧
まだ、コメントがありません