3分半の音声を文字起こししたら、30秒ぶんの会話が消えていた。
出力されたテキストは、ぱっと見ふつうだった。日本語として読んでもおかしくないし、前後もつながっている。消えた区間には「ハイ」という2文字が75回並んでいるだけで、そこに何が録音されていたのかは、テキストからは一切分からない。
気づいたのは、字幕ファイル(srt)のタイムスタンプを眺めていたときだった。
56
00:02:04,780 --> 00:02:34,780
ハイ ハイ ハイ ハイ ハイ ハイ ハイ ハイ …(×75)
開始2分4秒780、終了2分34秒780。ちょうど30.000秒。
Whisperは音声を30秒のウィンドウに区切って処理する。1つのセグメントがウィンドウ長ぴったりを占めているのは、そのウィンドウ全体が同じトークンの繰り返しで埋まったサインになりやすい。反復ループと呼ばれる現象で、その30秒に話されていた内容は失われる。
使っているのは faster-whisper の large-v3。反復ループの定番対策である condition_on_previous_text=False は最初から入れてある。それでこれが起きた。
なら、もっと良いモデルがあるんじゃないか。そう思って調べ始めた。
この記事は、動画や配信の音声をローカルで文字起こししている人向けに、無料で使える2つのモデルを自分の録音で比べた記録になっている。結論を先に書くと、私は英語が混じる素材なら今もWhisperを使う。速さでも日本語の数字でも別のモデルが上回る場面はあったけれど、そのモデルは苦しい箇所を黙って落とす。欠落に気づけない用途では使えない。
ただし、この記事で一番読んでほしいのは結論ではない。測り方を3回間違えて、そのうち2回は優劣が変わったという部分になる。1文字の違いが勝敗をひっくり返す世界で、他人のベンチマーク記事を信じる前に何を確認すべきかの話でもある。
目次
何を測って、何を測っていないか
先に射程を書いておく。実際に測ったのは faster-whisper large-v3 と nvidia/parakeet-tdt_ctc-0.6b-ja の2つだけになる。
測っていないものと、その理由。
- Kotoba-Whisper: 日本語特化として最も名前が挙がる。公式モデルカードの数値では CommonVoice 8 (ja) が 9.2 対 8.5、JSUT Basic 5000 が 8.4 対 7.1 で、いずれも large-v3 のほうが誤りが少ない。読み上げ音声で負けているモデルを最初の対抗馬に選ぶ理由がなかった。私が知りたかった「音楽や声の重なりがある条件」での成績は、公式値からは分からないままになっている
- large-v3-turbo / distil-whisper: 速度が論点なら入れるべきだった。後述する「2.5秒 対 60秒」は 0.6B と 1.55B の比較で、パラメータ数の差とモデル系統の差が分離できていない
- 【2026-07-21 追記】この2つは続編で測った。結果は本文の結論に影響したので、末尾の「私ならこう選ぶ」に追記を入れてある
- Canary-1B-v2 / Parakeet-TDT-0.6B-v3: 対応25言語に日本語がない。名前が似ているが、私が使った
parakeet-tdt_ctc-0.6b-jaは別のチェックポイントになる - Gemini や GPT 系のAPI: ローカル完結が条件だったので外した
日本語ASRの比較記事も探した。見つかったのは15発話で測ったもので、著者自身が「1〜2発話の認識差がスコアに大きく影響する」「参考値として捉えてほしい」と書いている。データセットの出所は非公開。別の記事の数値は、モデルの公式ページの値と6倍以上ずれていた。
音楽・歓声・声の重なりがある条件で日本語を測ったデータは、どこにも見当たらなかった。私が困っているのはまさにその条件になる。
自分で測るしかなかった。
測り方を3回間違えた
CERは、正解と出力の間の編集距離を正解の文字数で割った値になる。日本語では表記のゆれが全部「誤り」に化ける。
私は3回それを踏んだ。
1回目。 ネタ音源で「ちょ」の連続が何回出るかを数え、実行ごとに232回・5回・12回とばらつくので「これは幻聴だ」と判断した。実際には、ひらがなの「ちょ」しか数えていなかった。カタカナの「チョ」が26回あって、それを丸ごと見落としていた。違う基準で数えた数字を並べて比較していた。
2回目。 台本の数字を「いち、に、さん」と仮名で書いた。音声合成は正しく読み上げ、両モデルとも「1、2、3」と正しく書き起こした。どちらも正解なのに、読みに正規化しても数字は数字のまま残るので、20文字ぶんが誤りとして計上された。台本をアラビア数字に直したら、その音源のCERは0.165から0.039に下がった。
3回目。 parakeetは「ai」と小文字で出力し、Whisperは「AI」と大文字で出力する。台本にAIが10回出てくる音源で測ったら、大文字小文字の違いだけでCERが2ポイント動いた。この2ポイントで、片方の録音の優劣が逆転していた。
4回目もあった。 記事の下書きをレビューに出して指摘された。正規化のコードで、長音符「ー」を句読点と同じ扱いで除去していた。「ビール」と「ビル」が同じ文字列になる。長音の脱落はASRがよくやる誤りなので、それが丸ごと計上されていなかった。直して測り直したら、6本の録音のうち1本で優劣が入れ替わり、その差は1文字になった。
4つとも同じ種類のミスになる。正規化の不備を4回繰り返した。だから読者にはこう言っておきたい。この記事のCERも、まだ畳み忘れがあるかもしれない。 送り仮名、カタカナ英語の表記、句読点の扱い。私が気づいていない穴は残っている可能性が高い。
対策として、正規化にテストを書いた。
def test_cer_is_zero_for_reading_equivalent_text():
"""表記が違っても読みが同じなら誤り0。"""
assert cer("きょうとし に いきます", "京都市に行きます") == 0.0
def test_to_reading_keeps_long_vowel_mark():
"""長音符は句読点と違い音韻的に弁別的。落とすと脱落誤りが計上されない。"""
assert to_reading("ビール") != to_reading("ビル")
書いたテストが効いているかも確かめた。正規化のコードをわざと壊してテストが落ちるのを見てから、元に戻している。落ちないテストは書いていないのと同じなので。
ひとつ注意書きを。この正規化は漢字とかなの違いを吸収する代わりに、同音異義語の取り違えを見逃す。「橋」「箸」「端」がすべて「はし」になるので、変換ミスは誤りに数えられない。そして正規化が独自である以上、本記事のCERは、さきほど引用したモデルカードの公称値と直接は比べられない。
合成音声でも測ったが、モデル比較には使えなかった
先に音声合成で正解付きの音声を4パターン作って測っている。素直な読み上げ、意図的な繰り返し、音楽とノイズを重ねたもの、別の声を重ねたもの。
そこで2つのことが分かった。繰り返しの多い音声は両モデルとも問題なく書き起こせること。そして読み手の声を替えると優劣がひっくり返ることになる。同じモデル・同じ台本・同じ測り方で、Windows内蔵の声では clean で parakeet が勝ち、Irodori-TTS の声では Whisper が勝った。
生成した音声が台本どおりかの確認に、Whisper を使ってしまってもいた。評価される側が検定役を兼ねているので、あの表はモデル比較には使えない。作り方と限界の詳細は別記事に書いた。
だから人間の声で測り直した。
人間の声では、Whisperが明確に3本、わずかに2本
マイクの録音テスト用に、台本を読み上げた音源が手元にあった。読んだ原稿がそのまま残っているので、これも正解付きの音声になる。同じマイクを、ノイズ除去ソフトを通す経路と通さない経路に切り替えながら、台本を変えて6本ぶん録ってある。
読み上げた台本
ナレーション2本で読んだのが、この「AIと未来の働き方」になる。数字・固有名詞・英語・早口になりやすい部分を意図的に入れてある。
読み上げた台本「AIと未来の働き方」を開く
みなさん、こんにちは。今日は「AIが変えるこれからの働き方」についてお話しします。
まず、AIの進化は本当に目覚ましいものがあります。例えば、最近では音声認識の精度が大幅に向上し、会議の内容をほぼ正確に文字起こしできるようになりました。ただ、専門用語や人名、数字が入るとまだミスが起きやすいのが現状です。
実際に、私が今話しているこの文章にも、以下のようなポイントを意識して読んでみてください。
数字:2026年7月21日、現在午後2時6分です。
固有名詞:東京スカイツリーの高さは634メートル、富士山は3776メートルあります。
英語混じり:Artificial Intelligence、つまりAIは、Machine LearningやDeep Learningの技術を活用しています。
早口になりやすい部分:例えば「この文章を正確に文字起こしできたかどうか、後で確認してみましょう」。AIを上手に活用することで、業務効率は格段に上がります。たとえば議事録作成、顧客対応、データ分析など、さまざまな場面で活躍しています。しかし一方で、人間ならではの創造性や感情的なコミュニケーションは、AIにはまだ代替できない大切な部分です。
最後に、皆さんに伝えたいこと。それは「AIは道具であり、人間が主役である」ということです。AIを恐れるのではなく、うまく使いこなすことで、より豊かな未来を一緒に作り上げていきましょう。
それでは、今日はここまでです。ありがとうございました。
残る4本は、マイクの録音テスト用の台本を読んでいる。通常の声・小さい声・大きい声・サ行・パ行と、条件を変えて読み分ける内容になる。
BroadcastMic と Chat-Mic の違い
マイクは1本しか使っていない。コンデンサー型(RODE NT2-A)を口から15cm、TC-HELICONのGoXLRに挿してある。GoXLRの設定は6本すべて共通で固定した。
変えたのは、パソコンから見たときの入力デバイスになる。
Chat-Mic は GoXLR から直接届く音。BroadcastMic は、その手前に NVIDIA Broadcast を挟んだ仮想デバイスで、AIによるノイズ除去がかかっている。同じ声・同じマイクが、ソフト処理を通るか通らないかで分かれる。
収録はナレーション2本が Audacity、マイクテスト4本が自作の録音ツールになる。
参照は4本が284文字、ナレーション2本が629文字。差を文字数に直した列を付ける。
| 録音 | parakeet | Whisper | 差 |
|---|---|---|---|
| マイクテスト BroadcastMic | 0.292 | 0.214 | 22文字 |
| マイクテスト Chat-Mic | 0.198 | 0.171 | 8文字 |
| マイクテストVer2 Chat-Mic | 0.089 | 0.093 | 1文字 |
| マイクテストVer2 Broadcast | 0.467 | 0.346 | 34文字 |
| ナレーション Chat-Mic | 0.066 | 0.055 | 7文字 |
| ナレーション Broadcast | 0.107 | 0.058 | 31文字 |
3回ずつ実行して、12組すべてで出力が1文字も変わらなかった。実行ごとのばらつきはこの長さの音源では出ていない。
差が20文字を超えたのは3本で、いずれもWhisperが上。7文字と8文字の2本もWhisperが上だが、大文字小文字の畳み忘れだけで2ポイント動いた記事としては、この差を勝ちと呼ぶのは気が引ける。1文字差のVer2 Chat-Micは、差なしと書く。
「6本中5本でWhisperが上回った」と書くこともできたけれど、そう数えると1文字の差と34文字の差が同じ1勝になる。
録音レベルは、症状であって原因ではなかった
6本を発話の大きさ順に並べたとき、CERもだいたいその順になった。0.5秒ごとのRMSを出して上位25%の中央値を取った値で並べている。
| 録音 | 発話レベル | Whisper |
|---|---|---|
| ナレーション Broadcast | -35.5 dB | 0.058 |
| ナレーション Chat-Mic | -36.2 dB | 0.055 |
| マイクテストVer2 Chat-Mic | -37.2 dB | 0.093 |
| マイクテスト BroadcastMic | -39.7 dB | 0.214 |
| マイクテスト Chat-Mic | -40.3 dB | 0.171 |
| マイクテストVer2 Broadcast | -49.2 dB | 0.346 |
-35dBから-37dBの3本が0.055から0.093で並び、-39dBから-40dBの2本が0.17から0.21、最も小さい-49.2dBが0.346になる。
ここで「録音レベルを上げれば精度が上がる」と書きかけた。実際、下書きにはそう書いていた。
レビューで「レベル自体は原因になりにくいのでは」と指摘されて、確かめた。同じファイルの音量をデジタルで上げ下げして、測り直すだけになる。
| ファイル | 平均音量 | Whisper CER |
|---|---|---|
| Ver2 Broadcast そのまま | -53.6 dB | 0.346 |
| Ver2 Broadcast を +12dB | -41.6 dB | 0.335 |
| ナレーション Chat-Mic そのまま | -38.2 dB | 0.055 |
| ナレーション Chat-Mic を -12dB | -50.2 dB | 0.055 |
12dB動かしても、CERはほとんど変わらなかった。 最も悪かった録音を持ち上げても0.346が0.335になっただけで、良い録音を12dB落としても0.055のまま動かない。
理屈も合っている。いまのASRは対数メルスペクトログラムを取って特徴量を正規化するので、デジタルなゲインの違いはほぼ吸収される。
上の表の相関は、レベルが原因で起きているものではなかった。マイクが遠い、軸を外している、ノイズ除去が強くかかっている。そういう要因がレベルとCERの両方を同時に動かしていて、レベルはその症状として表に出ていただけになる。
だから正しい助言はこうなる。録音レベルが低いこと自体を直しても意味がない。低く録れている原因を直す。 音量ツマミを上げるのではなく、マイクに近づく、軸を合わせる、ノイズ抑制を弱める。
10分の実験で、記事の実用アドバイスがひとつ間違いから正しいものに変わった。相関を見て助言を書きたくなったら、その変数を直接動かして確かめるだけの価値がある。
なお、この6本は独立した6サンプルではない。3テイク×2デバイスで、台本も2種類、録音アプリも2種類ある。相関の話としては強く読まないでほしい。
固有名詞と数字は、どちらも落とさなかった
ナレーションの台本には難所を詰め込んだ。「2026年7月21日」「午後2時6分」「東京スカイツリー」「634メートル」「富士山」「3776メートル」、それに「Artificial Intelligence」「Machine Learning」「Deep Learning」。
日付・時刻・固有名詞・数値は、両モデルとも2本の録音すべてで正解だった。弱点だと言われている固有名詞と数字を、この録音品質なら取り切っている。
差が出たのは英語だった。
台本 : Artificial Intelligence
parakeet: rfficialintlaisens
Whisper : Artificial Intelligence
parakeetは2本の録音どちらでも崩した。「Machine Learning」も片方で「マシンランニング」になっている。Whisperは両方とも正しく出した。
黙って落とすほうが、うるさく間違えるより厄介だった
もう1つの差が欠落になる。ナレーションのBroadcast録音で、parakeetは「まず、AIの進化は本当に目覚ましいものがあります。」を出力しなかった。
Whisperが幻聴で足したんじゃないかと疑って、音声を確かめた。Whisperはその文を7.40秒から10.94秒に置いている。同じ区間の音量は-43から-35dBで、周囲の発話と同じ水準。parakeetの出力は6.64秒から11.36秒がまるごと空白になっていた。
音は入っていて、parakeetがそこを落としていた。
この落とし方は、合成音声のcleanで数字列が消えたのと同じ形をしている。マイクテストでは「セクション3。大きい声です。」を2本の録音どちらでも落とした。測ったうち4回で再現している。
ループしにくさと引き換えなのだと思う。フレーム同期で時間が必ず前進する仕組みは、裏を返せば「何も出さないまま時間を進める」判断もできる。その区間が丸ごと空白になる。
厄介なのは、欠落が無音として現れることだった。反復ループなら「ハイ」が75回並ぶので、テキストを見れば異常だと分かる。欠落は何も残らない。出力されたテキストは最後まで日本語として自然で、そこに一文あったことを知らなければ気づけない。
Whisperにも癖がある。何も話していない末尾に「ご視聴ありがとうございました」を付け足す。台本に無いのに出てきたのが4件あった。
数え方には気をつけた。ネタ音源の末尾にも「どうもありがとうございました」が出ていて、最初は捏造として数えていた。parakeetの出力を見たら同じ言葉が入っている。漫才の締めとして実際に言っていた。両方のモデルが独立に同じものを出したときは、たいてい音声にそう入っている。
VADは雑音のあるときだけ効く
Whisperには、音声のある区間だけを拾うVADというフィルタがある。反復ループの対策として名前が挙がることが多い。
合成音声で試したとき、音楽とノイズを重ねた音声では誤りが2文字から0文字になった。VADが雑音を落とした分だけ、素直に効いている。
同じフィルタを、雑音のない読み上げにかけたら悪化した。CERが0.013から0.103になる。出力を読むと、末尾に「ご視聴ありがとうございました」が付いていた。本文の認識は変わっていない。増えた14文字がまるごと誤りとして乗っただけになる。
1つの声、1つのファイルでの観察なので、VADが捏造を誘発すると言い切るには足りない。それでも既定でオンにする気にはならなかった。自作のMCPサーバでは既定をオフにして、環境変数で必要なときだけ有効にしている。
ひとつ補足を。VADを有効にするとタイムスタンプが再配置されるので、冒頭で使った「30秒ちょうど」の判定は効かなくなる。
「30秒ちょうど」は、どこを見に行くかの目印にすぎない
冒頭で私は、30.000秒というセグメント長を見て原因が分かったと書いた。書きながら少し都合よく整理していた。
実際に異常だと確定させたのは、長さではなく「ハイ」が75回並んでいる中身のほうになる。
長さだけで判定すると外れる場合がある。無音や音楽の区間では、タイムスタンプの予測に失敗してウィンドウ全体が1セグメントとして出てくる。息継ぎのない朗読や歌唱でも同じ形になりうる。逆に、数秒のセグメントが同じ一文を延々と繰り返すタイプのループは、この判定をすり抜ける。ファイル末尾のウィンドウは30秒未満なので、そこでループしても引っかからない。
使うなら、判定は繰り返しの多さで行い、30秒ちょうどは「どこを見に行くか」の目印にするのが正しい。手元の実装では、正規化したテキストの2-gramのユニーク率を裏返した値を反復スコアとして出している。「ハイ」×75の区間が0.9955。通常の文字起こしは、合成音声で0.06から0.08、人間の録音で0.18から0.29に収まった。素材によって幅はあるが、ループとの距離は十分に開いている。
私ならこう選ぶ
英語が混じる素材、録音条件が読めない素材はWhisper large-v3を使う。崩れても量を保つので、後から直せる。
日本語だけで、録音が安定していて、大量に処理したいときはparakeetを検討する。3分半の音声を2.5秒で処理した。Whisperは約60秒かかっている。ただしこれは0.6Bと1.55Bの比較なので、速度が目的なら large-v3-turbo も候補に入れて比べ直したほうがいい。
【2026-07-21 追記】宿題にしていた large-v3-turbo を続編で測った。精度は large-v3 とほぼ同じ(実発話6本の誤りが合計302文字 対 292文字)で、速度は large-v3 の3倍。parakeet との速度差は1.5倍だった。上に書いた「2.5秒 対 60秒」は条件を揃えた比較ではなかったので、この段落の速度の前提は続編の表で読み替えてほしい。速さを理由に parakeet を選ぶ場面は、続編の数字の上ではかなり狭くなっている。4モデルを同条件で測った表と、速度の測り方を2回間違えた記録は続編にある。
【2026-07-28 追記】同じ音源・同じ手順で測り直したら、4モデルとも速くなった。parakeet 0.87秒、large-v3-turbo 2.35秒、large-v3 6.98秒。parakeetとlarge-v3の差は8倍、turboとの差は2.7倍になる。間に入れたPyTorchの更新で説明が付くのはparakeetの16%ぶんだけで、残りは測った日の違いだった。速度の絶対値は環境と測る日で動くので、上の秒数は自分の環境で測り直してほしい。測り直した数字と切り分けの手順は続編の速度の節にある。
parakeetを使うなら、欠落を検出する仕掛けを付ける。ただし「1秒あたりの文字数が少なかったら警告」は当てにならなかった。測ってみると、正常な文字起こしでも1.15文字/秒から5.42文字/秒まで開く。間を取った音源と、詰めて読んだナレーションで4倍以上違う。固定のしきい値を置くと、正常なほうを叩く。
代わりに、出力が空いている区間に音が入っていないかを見る。私が欠落に気づいたのもこの方法だった。parakeetの出力は6.64秒から11.36秒が空白で、その区間の音量は-43から-35dB。周囲の発話と同じ水準の音が鳴っていた。タイムスタンプの空白と、音声の有音区間を突き合わせるだけになる。
録音については、レベルの数字を目標にしない。低く録れているなら、マイクの距離と向き、ノイズ抑制の強さを見る。
そして、他人のベンチマークを読むときは正規化を確認してほしい。この記事の数字も、4回目の畳み忘れを直すまでは1本の優劣が逆でした。
再現するときの情報
検証に使ったコードは github.com/BugattiAlpha/asr-ja-bench に置いた。音声生成・CER計算・実行ハーネス・欠落検出まで一式ある。台本と音声を差し替えれば、そのまま自分の音源で測れる。実行環境とデコード設定、NeMoをWindowsに入れるまでに4回止まった記録は、READMEにまとめた。
ひとつだけここに書いておきたいのが、日本語固有の落とし穴になる。分かち書きしない言語なので、単語単位のタイムスタンプを取ると全文が1語として返ってくる。文字単位のタイムスタンプを無音で区切ってセグメントを作った。英語圏の資料には出てこない話だと思う。
▶ 検証に使ったコードは GitHub に置いてある。台本と音声を差し替えれば、自分の音源でそのまま測れる。
音声合成: Irodori-TTS(Aratako, MIT)/使用モデルのライセンス(配布元で確認): Whisper・faster-whisper = MIT、nvidia/parakeet-tdt_ctc-0.6b-ja = CC-BY-4.0(NVIDIA への帰属表示が必要)