同じ109秒の音声を、faster-whisper large-v3 は6.98秒、large-v3-turbo は2.35秒で書き起こした。精度の差は、実録音6本・参照2,442文字を合計して10文字だった。
前回の記事には「測っていない」と書いたモデルが2つある。速度が論点なら入れるべきだったと書いた large-v3-turbo と、日本語特化として最も名前が挙がる Kotoba-Whisper。今回はこの2つを、前回と同じハーネス・同じ音源に足して測る。
先に私の判断を書いておくと、日本語の文字起こしでモデルを1つ選ぶなら、今は large-v3-turbo を既定にする。冒頭の数字がほぼそのまま理由になる。以下、測る対象、設定の決め方、精度、速度の順で書いていく。
目次
何をどう測るか
並べたのは4モデルになる。
| モデル | 規模 | 実行経路 |
|---|---|---|
| nvidia/parakeet-tdt_ctc-0.6b-ja | 0.6B | NeMo |
| faster-whisper large-v3 | 1.55B | faster-whisper (CTranslate2) |
| faster-whisper large-v3-turbo | 0.81B | faster-whisper (CTranslate2) |
| kotoba-whisper-v2.0-faster | 0.76B | faster-whisper (CTranslate2) |
音源は前回と同じものを使い回す。主戦場は、人間が読み上げ原稿を読んだ実録音6本。マイクテスト用の原稿を読んだ4本と、ナレーション原稿を読んだ2本で、原稿がそのまま正解になる。正解を合成音声で作った4本は性質が別なので、最後に別枠で載せる。実行は各モデル3回ずつ。出力が毎回同じかどうかも見る。
成績はCERの小数ではなく、誤った文字数で書く。参照はマイクテストが257文字、ナレーションが707文字。前回、CERの0.089と0.093を見比べて優劣を付けかけたことがある。参照257文字に対する1文字の違いでしかなかった。以来、差は文字数に直してから読むことにしている。
設定はモデルごとに決める
測り始める前に、決めることが1つある。4モデルを全部同じ設定で回すか、それぞれの推奨設定で回すか。
同じ設定で回すほうが公平に見える。実際に測ると、ここでは逆だった。
気づかせてくれたのはKotoba-Whisperになる。届いたばかりのモデルをfaster-whisperの既定(30秒窓)のまま回したら、ナレーション音源のCERが0.248。turboの0.058と4倍以上離れている。公式モデルカードの公称値はCommonVoice 8 (ja)が9.2で、large-v3の8.5と拮抗しているのだから、水準が違いすぎる。この乖離の大きさが信号だった。モデルの実力を結論する前に、自分の呼び出し方を確認する番になる。
疑わしいものを順に潰した。幻聴対策のしきい値(no_speech_threshold や log_prob_threshold)を全部外しても、出力は1文字も変わらなかった。蒸留モデルはチャンク推論を前提に訓練されているから逐次のlong-formデコードが合わないのかと、VADでチャンクに割る BatchedInferencePipeline に通すと0.248が0.208。改善はしたが、まだ桁が合わない。
当たりはモデルカードの使用例にあった。faster-whisper向けの例に chunk_length=15 と書いてある。窓を30秒から15秒に変えて回すと、0.157まで下がった。
| 音源 | chunk 30(既定) | chunk 15(公式の例) |
|---|---|---|
| ナレーション(109秒・実発話) | 0.248 | 0.157 |
| clean(36秒・合成) | 0.323 | 0.110 |
| noisy(36秒・合成) | 0.103 | 0.123 |
| repetition(32秒・合成) | 0.198 | 0.310 |
窓を短くすれば良くなる、という単純な話でもない。同じ語を繰り返す音源では悪化した。それなら比較のために large-v3 と turbo も15秒窓に揃えるとどうなるか。両方悪くなった。誤り文字数の合計で large-v3 が292から354へ、turboが302から342へ。窓長の感度がモデルごとにばらばらなので、どこかの値に揃えた瞬間、誰かが不利を引く。
今回の本測定は、各モデルの推奨設定で回すことにした。kotobaは公式例の15秒窓、whisper系は既定の30秒窓、parakeetはNeMoの標準経路。他人のモデルを測るときは、モデルカードの推奨設定を読んでから条件を決める。テストの順序としてはこれが最初に来る。私は一度それを飛ばして、嘘の数字を作りかけた。
設定まわりで踏んだ罠を2つ書いておく。1つ目、faster-whisperの chunk_length はモデルオブジェクトの状態を書き換えて、そのまま残る。同じモデルで設定を切り替えて比べていたら、指定しなかった呼び出しが直前の値を引き継いでいた。
1) chunk_length 指定なし n_samples=480000 CER 0.323
2) chunk_length=15 n_samples=240000 CER 0.110
3) また指定なし n_samples=240000 CER 0.110 ← 15のまま
4) chunk_length=30 を明示 n_samples=480000 CER 0.323
3行目が1行目と同じ結果に戻っていない。これに気づかず一度、汚染された比較表を作った。設定を変えて比べるときはモデルを作り直す。
2つ目、kotoba-whisperに word_timestamps=True を渡すと、プロセスがアクセス違反で即死する。Pythonの例外にならないので try では受けられない。蒸留でデコーダが2層しかなく、単語の位置合わせが噛み合わないためになる。単語単位のタイムスタンプが要る用途では、このモデルは候補から外れる。
精度: turbo は large-v3 とほぼ並ぶ
実録音6本の誤り文字数がこの表になる。
| 録音 | parakeet | large-v3 | turbo | kotoba |
|---|---|---|---|---|
| マイクテスト Broadcast | 75 | 55 | 75 | 88 |
| マイクテスト Chat-Mic | 51 | 44 | 33 | 92 |
| Ver2 Chat-Mic | 23 | 24 | 32 | 65 |
| Ver2 Broadcast | 120 | 89 | 81 | 115 |
| ナレーション Chat-Mic | 47 | 39 | 41 | 111 |
| ナレーション Broadcast | 76 | 41 | 40 | 89 |
| 合計 | 392 | 292 | 302 | 560 |
turbo と large-v3 で明確に差がついたのは3本だけになる。large-v3 がマイクテストBroadcastで20文字勝ち、turboがマイクテストChat-Micで11文字、Ver2 Broadcastで8文字勝った。残る3本は2文字以内で、これを勝ち負けと呼ぶ気にはならない。パラメータ数が半分のモデルが、この音源群では同じ水準に立っている。
turboには揺れがある
6本のうちVer2 Broadcastという録音だけ、turboの3回の出力が一致しなかった。255文字、254文字、251文字。他のモデルは全6本・全3回が完全一致で、large-v3も揺れていない。
Ver2 Broadcastは6本の中で最も条件が悪い録音になる。誤りが81文字と、他の録音の2倍以上ある。苦しい音源でデコードが揺れるという性質は前回large-v3で観測したものと同じで、turboでも消えていない。文字起こしの結果を保存して後から突き合わせるような使い方をするなら、同じ音声から同じ結果が返る保証はないと考えておく。
Kotoba-Whisperは公式設定でも最下位だった
表のkotobaの列は、公式の15秒窓で測り直したあとの数字になる。それでも合計560文字で4モデルの最下位。出力を見ると全体に短く、ナレーションでは参照707文字に対して525文字しか出ていない。誤りの主体は書き間違いというより欠落になる。
学習データのReazonSpeechはテレビ音声から作られている。素材がその方向に近ければ結果は変わるかもしれない。ここは推測で、私の6本では確かめられていない。
速度: 測り方で順位が入れ替わる
前回は3分半の音源で、parakeetが2.5秒、large-v3が約60秒という数字を載せた。0.6Bと1.55Bの比較で、測った日も条件も揃えていない。今回は109.2秒のナレーション音源1本に固定して、モデル読み込みを除いた処理時間だけを測る。GPUは RTX 2070 SUPER。
それでも2回、測り方を間違えた。
間違い1: 同じプロセスで繰り返した
最初は1つのプロセスの中で5回続けて文字起こしを走らせ、中央値を採った。whisper系は安定していたのに、parakeetだけ数字が伸びていく。
parakeet 4.88s → 8.78s → 10.23s → 10.66s → 10.99s
turbo 3.33s → 3.15s → 3.14s → 3.14s → 3.14s
ウォームアップなら1回目が遅くて2回目以降が速くなる。逆向きに伸びているのだから、何かが積み上がっている。プロセスを分けて1回ずつ測ると5.3〜5.7秒に収まった。同一プロセスで5回まわして中央値を採ると、parakeetの処理時間を85%も過大に報告することになる。
間違い2: モデルごとにまとめて回した
プロセスを分けたあとも数字が落ち着かなかった。turboを5回、kotobaを5回、whisperを5回、parakeetを5回、という順で回していたときの結果がこれになる。
whisper 44.94s, 44.72s, 42.86s, 40.26s, 8.65s
parakeet 2.60s, 2.12s, 2.17s, 2.16s, 2.15s
whisperの5回目だけ8.65秒。他の回の5分の1で終わっている。出力を比べたら573文字・23セグメントで、他の4回と1文字も違わなかった。同じ仕事を5倍速で終えている。
GPUを別のプロセスが使っていた。私の環境では文字起こしのMCPサーバーが常駐していて、その混み具合が時間帯で動く。モデルごとにまとめて回すと、その変動がまるごと特定のモデルの計測値に乗る。実際、parakeetを最後にまとめて回した回と、最初にまとめて回した回で、parakeetとturboの優劣が入れ替わった。
やり直した手順はこうなる。GPUが空くのを待ち、4モデルを1回ずつ順番に回すのを5周して、中央値を採る。混み具合の変動を全モデルに等しくかけるためになる。
| モデル | 規模 | 処理時間 | 実時間比 | 実時間の何倍か |
|---|---|---|---|---|
| parakeet-tdt_ctc-0.6b-ja | 0.6B | 0.87秒 | 0.008 | 126倍 |
| faster-whisper large-v3-turbo | 0.81B | 2.35秒 | 0.021 | 46倍 |
| kotoba-whisper-v2.0-faster | 0.76B | 2.68秒 | 0.025 | 41倍 |
| faster-whisper large-v3 | 1.55B | 6.98秒 | 0.064 | 16倍 |
5周とも順位は変わらず、各モデルの5回の開きは最大でも4%に収まった。前回「約25倍」に見えていたparakeetとlarge-v3の速度差は、条件を揃えるとこの表の8倍になる。turboとparakeetの差は2.7倍。
1週間後に測り直したら、4モデルとも速くなった
上の表は2026年7月28日の測定になる。同じ音源・同じ手順で最初に測った7月21日は、parakeet 2.25秒、turbo 3.32秒、kotoba 3.51秒、large-v3 10.11秒だった。どちらの日も5周の開きは4%以内で、その日の中では安定している。
それでも1.3〜2.2倍ずれた。
間にPyTorchを2.6から2.13へ上げていたので、そこを切り分けた。7月28日に古いほうの環境へ戻して同じ測定をすると、parakeet 1.01秒、turbo 2.34秒、kotoba 2.66秒、large-v3 6.93秒。torchを使うのはparakeetだけで、更新で速くなったのもparakeetの16%ぶんだけだった。whisper系3つはCTranslate2で動くので、更新の前後で1桁ミリ秒しか動いていない。残りは測った日の違いになる。
私の環境ではGPUを文字起こしのMCPサーバーと分け合っている。7月28日は使用率1〜2%で、実行中はクロックが1995MHzまで上がっていた。7月21日にどれだけ空いていたかは記録に残していない。原因はここまでしか詰められていないので、断定はしない。
読者にとっての意味はひとつになる。他人の記事に出ている秒数を、自分の環境の見積もりにそのまま使わない。順位と比率は持ち出せても、絶対値は自分で測り直す。この記事の秒数も同じ扱いでいい。
合成音声でも測った
正解が分かる合成音声4本の結果も載せておく。作り方と限界は別記事に書いた。
| 音声 | parakeet | large-v3 | turbo | kotoba |
|---|---|---|---|---|
| clean | 0.071 | 0.013 | 0.000 | 0.110 |
| noisy | 0.071 | 0.013 | 0.000 | 0.123 |
| repetition | 0.095 | 0.017 | 0.017 | 0.310 |
| overlap | 0.348 | 0.348 | 0.368 | 0.452 |
turboがcleanとnoisyで完全一致を出している。ただしこの表をモデル同士の優劣に使ってはいけない。合成音声が台本どおり読まれたかの検定に、私はwhisperを使った。合格した音声は「whisperが完璧に書き起こせる音声」なので、whisper系に有利な素材になっている。turboもkotobaもwhisper系ではあるが、検定に使ったlarge-v3そのものが最も有利な立場にいる。
この表が使えるのは、同じモデルの中で条件を比べるときだけになる。
私ならこう選ぶ
既定は large-v3-turbo にする。large-v3から乗り換えて失うものが、実録音6本で10文字だった。得るものが3倍の速度になる。
large-v3を残すのは、1回しか処理できない素材を扱うときになる。取材の録音や、消えてしまう配信のアーカイブ。20文字ぶん良かった録音が1本あった以上、やり直しがきかない場面では重いほうを回す。
parakeetは今回も最速で、turboとの差は2.7倍に開いた。ただ誤りは90文字多い。前回書いた「日本語だけで、録音が安定していて、大量に処理したいときはparakeetを検討する」という基準は、この数字で読み替えてほしい。100本を続けて流すような用途なら2.7倍は効く。1本ずつの精度が要る素材ならturboを回す。日本語の数字・固有名詞に強い性質は前回の検証で確認しているので、そこが効く素材なら今でも選ぶ。
Kotoba-Whisperは、私の6本では選べなかった。手元の素材がテレビ音声に近いなら結果は変わるかもしれないので、測ってから決めてほしい。
他人の速度比較を読むときは、測り方を見る。私はこの記事を書く過程で、同じ4モデルの速度を3回測って、3回とも違う順位を出した。プロセスを分けていなかった回、モデルごとにまとめて回した回、GPUが空くのを待って交互に回した回。文字起こしの精度は測り方が多少雑でも大きくは動かないのに、速度は測り方でいくらでも変わる。
▶ 検証に使ったコードは GitHub に置いてある。モデルの追加は run_whisper.py に1行足すだけで、集計まで通る。台本と音声を差し替えれば、自分の音源でそのまま測れる。
音声合成: Irodori-TTS(Aratako, MIT)/使用モデルのライセンス(配布元で確認): Whisper・faster-whisper・kotoba-whisper-v2.0-faster = MIT、nvidia/parakeet-tdt_ctc-0.6b-ja = CC-BY-4.0