目次
この記事について
無料かつオフラインで音声をテキストに変換するためのライブラリ、モデルについて
普段自分が触っている言語で試してみて、精度が良かったものについてまとめました。
ライブラリについて
Whisper
OpenAIが開発した高精度な音声認識AIモデル
whisperのgithubページ
Whisperの言語対応状況
| 言語名 | 名称 | 備考 |
|---|---|---|
| Python | 公式ライブラリ(openai-whisper) | 標準・最も簡単 |
| C# | Whisper.net または whisper.cpp バインディング | .NET/Unity対応 |
| Node.js | whisper-node ライブラリ | JavaScript/TypeScript |
| Rust | whisper-rs | 高性能ネイティブ |
| C++ | whisper.cpp(コア実装) | 全言語の基盤 |
| Go | whisper-go | サーバーサイド向け |
| ブラウザ(Javascript) | Transformers.js | Node.js不要で埋め込み |
Vosk
Alpha Cephei社が提供するオフラインで動作する軽量なオープンソース音声認識ライブラリ
モデルサイズは50MBの軽量版から1GBの大規模版まで選択可能
Voskの公式ドキュメント
Voskのモデルダウンロードページ
Voskの言語対応状況
| 言語名 | 利用方法 | 備考 |
|---|---|---|
| Python | pip install vosk | 標準・最も簡単 |
| C# | NuGetパッケージ(Vosk.NET) | Windows/.NETアプリ向け |
| JavaScript | Node.jsバインディング | Web/サーバーサイド |
| Java | Maven/Gradle経由 | Android開発に最適 |
| Go | Goバインディング | 軽量サーバー向け |
| Rust | Rustバインディング | 高性能ネイティブ |
| C++ | コア実装 | 全言語の基盤 |
| ブラウザ(Javascript) | vosk-browser | Node.js不要で埋め込み |
動作確認した環境
- Python 3.11.9
- C# .NET8.0
- Chrome(ブラウザ)
OS
Windows11
Debian GNU/Linux 12 (bookworm) [rasberry PI]
Whisper
Python
モデルは5種類あります
| モデル名 | 備考 |
|---|---|
| base, tiny, small | 8GB RAMで動作を確認 |
| medium, large | サイズが大きいため、より大きいRAM,GPU環境などが必要 |
import datetime
import whisper
start_time = datetime.datetime.now()
model = whisper.load_model("small") # tiny/base/small/medium/largeから選択
result = model.transcribe(r"音声変換テスト.wav")
print(result["text"])
end_time = datetime.datetime.now()
print("処理時間:", end_time - start_time)
実行結果
音声的地質変換の制度と処理時間を調べるためのテストです。
処理時間: 0:00:05.424029
音声的スト変換の制度と初理時間を調べるためのテストです。
処理時間: 0:00:05.536967
音声テキスト変換の精度と処理時間を調べるためのテストです
処理時間: 0:00:23.686489
C#
モデルは5種類あります
| モデル名 | サイズ |
|---|---|
| Tiny | 約75MB |
| Base | 約142MB |
| Small | 約466MB |
| Medium | 約1.5GB |
| Large | 約2.9GB |
※コードは一部を抜粋しています。
// モデルをダウンロード
using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(modelInfo.GgmlType);
using var fileStream = File.Create(modelPath);
await modelStream.CopyToAsync(fileStream);
// モデルの読み込み
await Task.Run(() =>
{
_whisperFactory = WhisperFactory.FromPath(modelPath);
_whisperProcessor = _whisperFactory.CreateBuilder()
.WithLanguage("ja")
.Build();
});
ResultTextBox.Text = "";
// 16kHz 16bit monoに変換
var convertedFile = await ConvertToWhisperFormatAsync(audioFilePath);
await Task.Run(async () =>
{
// 音声ファイルを読み込んで変換
using var fileStream = File.OpenRead(convertedFile);
await foreach (var segment in _whisperProcessor!.ProcessAsync(fileStream))
{
Dispatcher.Invoke(() =>
{
ResultTextBox.AppendText(segment.Text);
});
}
});
// 変換が完了した文字列
ResultTextBox
実行結果
音声的地質変換の制度と処理時間を調べるためのテストです。
処理時間: 00:00:06.53
音声的スト変換の制度と初理時間を調べるためのテストです。
処理時間: 00:00:06.81
音声テキスト変換の精度と処理時間を調べるためのテストです
処理時間: 00:00:14.25
音声テキスト変換の精度と処理時間を調べるためのテストです
処理時間: 00:00:45.81
Javascript
こちらのモデルはXenova氏という方が提供してくださっているようです。
Xenova氏のHuggingFace
| モデル名 | サイズ | 備考 | URL |
|---|---|---|---|
| Xenova/whisper-tiny | ~39MB | 最軽量・多言語 | https://huggingface.co/Xenova/whisper-tiny |
| Xenova/whisper-base | ~74MB | 標準・多言語 | https://huggingface.co/Xenova/whisper-base |
| Xenova/whisper-small | ~244MB | 高精度・多言語 | https://huggingface.co/Xenova/whisper-small |
| Xenova/whisper-medium | ~769MB | 最高精度・多言語 | https://huggingface.co/Xenova/whisper-medium |
| Xenova/whisper-large-v3 | ~1.5GB | 最新最高精度 | https://huggingface.co/Xenova/whisper-large-v3 |
| Xenova/whisper-base.en | ~74MB | 英語特化・高速 | https://huggingface.co/Xenova/whisper-base.en |
※コードは一部を抜粋しています。
// モデルの読み込み
const{pipeline}=await import('https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.2');
model=await pipeline('automatic-speech-recognition','Xenova/whisper-small',{
progress_callback:updateProgress
});
// 音声ファイルの読み込み
const audioData=await fileToAudioData(file);
// 音声テキスト変換
const result=await model(audioData,{
language:'ja',
sampling_rate:16000,
task:'transcribe'
});
音声テキスト変換のセードとそれ時間を調べるためのテストです
処理時間: 00:00:03.87
音声的スト変換の制度と処理時間を調べるためのテストです。
処理時間: 00:00:07.23
音声テキスト変換の精度と処理時間を調べるためのテストです
処理時間: 00:00:33.83
Vosk
日本語のモデルは二種類あります
| モデル名 | サイズ | 備考 |
|---|---|---|
| vosk-model-small-ja | 約48MB | Windows,Linuxどちらでも動作する |
| vosk-model-ja | 約1GB | PythonのVosk for Windowsでは動作不可 |
Python
Windowsでは、「vosk-model-ja」モデルは動作不可
import wave
import json
import datetime
from vosk import Model, KaldiRecognizer
start_time = datetime.datetime.now()
model = Model("vosk-model-small-ja-0.22") #ここでモデルを指定
rec = KaldiRecognizer(model, 16000)
with wave.open(r"音声変換テスト.wav", "rb") as wf:
# リアルタイム出力(途中経過が見える)
while data := wf.readframes(4000):
if rec.AcceptWaveform(data):
result = json.loads(rec.Result())
print(result["text"], end=" ") # 即時出力
final = json.loads(rec.FinalResult())["text"]
print("\n最終結果:", final)
end_time = datetime.datetime.now()
print("処理時間:", end_time - start_time)
実行結果
音声 テキスト 変換 の 精度 と 処理 時間 を 調べる ため の テスト です
最終結果:
処理時間: 0:00:03.815468
音声 テキスト 変換 の 精度 と 処理 時間 を 調べる ため の テスト です
最終結果:
処理時間: 0:00:15.400256
C#
※コードは一部を抜粋しています。
// Voskログを無効化(オプション)
Vosk.Vosk.SetLogLevel(-1);
// modelPath = "./vosk-model-small-ja-0.22"
using var model = new Model(modelPath);
using var recognizer = new VoskRecognizer(model, 16000.0f);
// 部分結果を有効化
recognizer.SetWords(true);
var resultBuilder = new StringBuilder();
using var fileStream = File.OpenRead(audioPath);
// WAVヘッダーをスキップ(44バイト)
fileStream.Seek(44, SeekOrigin.Begin);
var buffer = new byte[4096];
int bytesRead;
// 音声ファイルを読み込んで変換する
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
if (recognizer.AcceptWaveform(buffer, bytesRead))
{
var result = recognizer.Result();
var text = ExtractText(result);
if (!string.IsNullOrWhiteSpace(text))
{
resultBuilder.AppendLine(text);
}
}
}
// 最終結果を取得
var finalResult = recognizer.FinalResult();
var finalText = ExtractText(finalResult);
if (!string.IsNullOrWhiteSpace(finalText))
{
resultBuilder.AppendLine(finalText);
}
// 変換が完了した文字列
resultBuilder.ToString();
実行結果
音声 テキスト 変換 の 精度 と 処理 時間 を 調べる ため の テスト です
処理時間: 00:00:08.916
音声 テキスト 変換 の 精度 と 処理 時間 を 調べる ため の テスト です
処理時間: 00:00:09.566
Javascript
※コードは一部を抜粋しています。
<!-- Vosk ブラウザ版ライブラリ(Node.js不要) -->
<script src="https://cdn.jsdelivr.net/npm/vosk-browser@0.0.3/dist/vosk.js"></script>
// モデルの読み込み
model = await Vosk.createModel('vosk-model-small-ja-0.22.zip');
// 音声ファイルを読み込んで音声テキスト変換
const audioBuffer = await fileToVoskBuffer(file);
const rec = new model.KaldiRecognizer(16000);
rec.acceptWaveform(audioBuffer);
実行結果
音声 テキスト 変換 の 精度 と 処理 時間 を 調べる ため の テスト です
処理時間: 00:00:18.63
まとめ
実行結果
Python
| ライブラリ名 | モデル名 | 処理時間 | テスト音声の変換精度 |
|---|---|---|---|
| Whisper | tiny | 0:00:05.424029 | 不完全 |
| Whisper | base | 0:00:05.536967 | 不完全 |
| Whisper | small | 0:00:23.686489 | 完全 |
| Vosk | vosk-model-small-ja | 0:00:03.815468 | 完全 |
| Vosk | vosk-model-ja | 0:00:15.400256 | 完全 |
C#
| ライブラリ名 | モデル名 | 処理時間 | テスト音声の変換精度 |
|---|---|---|---|
| Whisper | Tiny | 0:00:05.424029 | 不完全 |
| Whisper | Base | 0:00:05.536967 | 不完全 |
| Whisper | Small | 00:00:14.25 | 完全 |
| Whisper | Medium | 00:00:45.81 | 完全 |
| Vosk | vosk-model-small-ja | 00:00:08.916 | 完全 |
| Vosk | vosk-model-ja | 00:00:09.566 | 完全 |
Javascript(ブラウザ)
| ライブラリ名 | モデル名 | 処理時間 | テスト音声の変換精度 |
|---|---|---|---|
| Whisper | whisper-tiny | 00:00:03.87 | 不完全 |
| Whisper | whisper-base | 00:00:07.23 | 不完全 |
| Whisper | whisper-small | 00:00:33.83 | 完全 |
| Vosk | vosk-model-small-ja | 00:00:18.63 | 完全 |
処理時間
Vosk > Whisper
| モデルサイズ | 処理時間 | 精度 |
|---|---|---|
| 大きい | 長い | 高い |
| 小さい | 短い | 低い |
WhisperもVoskもモデルのサイズが上がるほど、処理時間が長くなり精度が高くなりました。
モデルサイズは用途に合わせて、大き過ぎず、小さ過ぎず適切なサイズにする必要がありそうです。
参考にさせていただいた記事サイト
検索で使用したAI