🫦

音声認識ライブラリ「Vosk」を試してみた

2024/12/09に公開

こんにちは!『麦ちゃーはん』です。

今回は、音声認識ライブラリ「Vosk」を紹介します。
手軽に音声認識を行うことができますので、この記事を読んでぜひ試してみてください。

Voskの概要


Voskは、オープンソースの音声認識ライブラリで、オフライン環境で高精度な音声認識を実現します。Pythonをはじめ、JavaScript、Java、C#など複数のプログラミング言語に対応しており、クロスプラットフォームでの利用が可能です。

20以上の言語をサポートしており、日本語モデルも提供されています。モデルサイズは約50MBの軽量版(Smallモデル)と1GBの大規模版(Standardモデル)があり、用途に応じて選択できます。

また、ストリーミング音声認識にも対応しており、リアルタイムでの音声入力処理が可能です。これにより、マイク入力や音声ファイルからのリアルタイムな文字起こしが実現できます。

事前準備

モデルのダウンロード

以下のページから、日本語版モデルをダウンロードします。
https://alphacephei.com/vosk/models

モデルのフォルダ名を「model-standard」と「model-small」に変更し、以下のようなディレクトリ構造で配置します。

project/
├── vosk_test.py               # Voskを使用するPythonスクリプト
├── model-standard/            # Standardモデルのディレクトリ
└── model-small/               # Smallモデルのディレクトリ

ライブラリのインストール

Voskを使用するためのライブラリをインストールします。

pip install vosk sounddevice

使用するコード

import sounddevice as sd
import queue
import sys
from vosk import Model, KaldiRecognizer

# モデルディレクトリの指定
MODEL_PATH = "model-standard"  # モデルを解凍して、このディレクトリ名に変更

# モデルのロード
try:
    model = Model(MODEL_PATH)
except Exception as e:
    print(f"モデルが見つかりません: {e}")
    print("小型モデルを https://alphacephei.com/vosk/models からダウンロードし、解凍して 'model-small' フォルダに配置してください。")
    sys.exit(1)

# 音声データをキューで管理
q = queue.Queue()

def audio_callback(indata, frames, time, status):
    """マイクからの音声データをキューに追加"""
    if status:
        print(f"ステータス: {status}", file=sys.stderr)
    q.put(bytes(indata))

def main():
    recognizer = KaldiRecognizer(model, 16000)  # 16kHzで認識
    print("マイクに向かって話してください。Ctrl+Cで終了します。")

    # 音声ストリームを開く
    with sd.RawInputStream(samplerate=16000, blocksize=8000, dtype="int16",
                           channels=1, callback=audio_callback):
        while True:
            data = q.get()
            if recognizer.AcceptWaveform(data):
                result = recognizer.Result()
                print(f"認識結果: {result}")
            else:
                partial_result = recognizer.PartialResult()
                print(f"途中結果: {partial_result}")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\nプログラムを終了します。")
        sys.exit(0)
    except Exception as e:
        print(f"エラー: {e}")

実行結果

Standardモデル

はじめに、Standardモデルを試してみます。認識させる言葉は、「こんにちは。今日も一日頑張りましょう」です。結果は以下の通りになりました。

途中結果: {
  "partial" : "今日 は 今日 も"
}
途中結果: {
  "partial" : "今日 は 今日 も 一日 頑張る"
}
途中結果: {
  "partial" : "今日 は 今日 も 一日 頑張り ます"
}
認識結果: {
  "text" : "今日 は 今日 も 一日 頑張り ます"
}

語尾にミスがありますが、おおむね認識できています。

造語の認識がどうなるのか気になったので、「こんにちは。麦ちゃーはんです。」という言葉も認識させてみました。

途中結果: {
  "partial" : "今日"
}
途中結果: {
  "partial" : "今日 は 麦"
}
途中結果: {
  "partial" : "今日 は 麦 チャーハン です"
}
途中結果: {
  "partial" : "今日 は 麦 チャーハン です"
}
認識結果: {
  "text" : "今日 は 麦 チャーハン です"
}

なんと綺麗に認識してくれました。思った以上に精度が高いです。

Smallモデルの実行結果

次はSmallモデルを試します。認識させる言葉はStandardモデルと同様です。

途中結果: {
  "partial" : "今日"
}
途中結果: {
  "partial" : "今日 は 今日"
}
途中結果: {
  "partial" : "今日 は 今日 も 一 日"
}
途中結果: {
  "partial" : "今日 は 今日 も 一 日 がんばり ましょ"
}
途中結果: {
  "partial" : "今日 は 今日 も 一 日 がんばり ましょ"
}
途中結果: {
  "partial" : "今日 は 今日 も 一 日 がんばり ましょ"
}
認識結果: {
  "text" : "今日 は 今日 も 一 日 がんばり ましょ"
}

こちらも語尾にミスがありますが、認識できていると言えるでしょう。

途中結果: {
  "partial" : "今日 は 麦茶"
}
途中結果: {
  "partial" : "今日 は 麦 チャーハン です"
}
途中結果: {
  "partial" : "今日 は 麦 チャーハン です"
}
認識結果: {
  "text" : "今日 は 木 版 です"
}

途中までは正しく認識できていたものの、最後に明確なミスが発生しました。「麦ちゃーはん」が「木版」と誤認識されてしまっています。何度繰り返しても同じミスが発生するので、この部分で性能の違いが表れている可能性があります。

モデルの比較

試行回数が少ないため断定はできませんが、Smallモデルの認識精度はやや低いと感じられました。一方で、動作の軽さに関してはSmallモデルが圧倒的に優れており、デバイスの性能や必要とされる認識速度・精度に応じて使い分けるのが適切だと思われます。

おわりに

今回は、Pythonの音声認識ライブラリ「Vosk」について解説させていただきました。今後、「Vosk」と「YOLO」を組み合わせた作品を作成する予定ですので、ぜひご覧ください。

ここまでお付き合いいただき、心から感謝いたします!

Discussion