← AIバイブコーディングTips 一覧へ Quality / TTS × ASR Round Trip

合成ナレーションをWhisperで聞き直したら、声質変換が数字を壊していた

AIに動画を作らせると、映像の検品はかなり機械化できます。フレームを全部デコードし、字幕の文字列を台本と照合し、音量を測る。ところが「ナレーションが正しく聞き取れるか」だけは、どの検査にも引っかかりません。自作のナレーション(VOICEVOX→RVCで自分の声に変換)を音声認識にかけ直してみたら、「18か月後」がまともに聞き取れない形に崩れていました。崩れた段の特定と、人の耳に何を渡したかまでを書きます。

この記事で手に入るもの

合成音声を音声認識で台本と照合する「往復検品」の手順と、崩れた原因が読み上げ・声質変換・倍速のどの段にあるかを切り分けるA/B比較の型。音声認識の結果を合格の証拠にしないための線引きも添えます。

01 — 検品の穴

映像の検査は全部通るのに、「聞き取れるか」だけ誰も見ていない

SURPLUS(経済学の読み物チャンネル)の解説動画は、台本から完成MP4までをAIに作らせています。約7分46秒の動画で、検品項目はこうでした。

全部PASSです。でも、どれもナレーションの中身は確かめていません。字幕が正しいのは台本からテキストを流し込んでいるからで、声がその通りに聞こえる保証にはなりません。

ナレーションは、VOICEVOXで読み上げた音声をRVCで自分の声に変換し、1.2倍速にしたものです。構成は以前Art38で書きました。そのときから未解決として残していたのが読み間違いです。VOICEVOXは読み上げ前にカナ読み(モーラ)を出せるので、そこは機械で確認できます。ただ、モーラが正しくても、声質変換を通った後の音が正しく聞こえるかは別問題でした。


02 — 往復検品

台本→音声→文字に戻して、台本と突き合わせる

やったことは単純です。完成したMP4から音声を切り出し、音声認識で文字に戻して、台本と並べました。

01

最終MP4から、字幕の区間ごとに切り出す

途中の音声ファイルではなく、公開するMP4そのものから切り出します。エンコードや倍速の影響まで含めて検品するためです。区間は字幕の開始・終了時刻をそのまま使い、126区間に分けました。

02

ローカルのWhisper-smallで文字起こし。台本はヒントに渡さない

Whisperには「この語が出てくるはず」と事前にテキストを渡す機能があります。これを使うと、崩れた音でも期待通りの文字が出やすくなり、検品の意味がなくなります。期待する文は渡さずに聞かせました。126区間で約2分、ローカルGPUで済みます。

03

台本と並べて、ずれた区間だけ拾う

漢字変換の揺れ(「随分」と「ずいぶん」など)は無視して構いません。見るのは数字と、意味が変わってしまう語です。

結果の一部です。左が台本、右がWhisperの出力です。

# 台本 → 文字起こし(最終MP4から)
例えば、1日8時間を週5日働くと…   → 1日8時間を週5が働くと…
短くする側は…勤務時間を4分の1… → …金の時間を4分の1…
改善は18か月後にも見られた。     → 改善は18日熱もにも見られた

結論を支える数字(週40時間→32時間、4分の1、18か月間)は多くが正しく残っていました。一方で、週5日・23分・9か月後・18か月後・6か月のあたりは認識が安定しません。中でも「18か月後」は、研究の効果が長続きしたことを示す一文です。ここが「18日」に聞こえたら、動画の主張が逆向きに伝わりかねません。


03 — 切り分け

崩れたのは読み上げか、声質変換か、倍速か

Whisperが聞き取れないだけなのか、音そのものが崩れているのか。ここで、同じ一文をパイプラインの段ごとに聞かせ比べました。

✓
VOICEVOXの原音3通りの認識条件すべてで「18か月後」と正しく認識。
✗
RVCで変換した直後(等速)3条件すべてで誤認識。
✗
RVC+1.2倍速同じく3条件すべてで誤認識。

読み上げの段では正しく、声質変換を通った時点で崩れていることが分かります。倍速は原因ではありませんでした。

次に、RVCの設定(学習済みの声にどれだけ寄せるか、子音をどれだけ元の音のまま残すか)を変えた候補を2つ作りました。どちらも最終速度では改善しません。ここで、改善を確認できていない候補には差し替えないと決めています。「設定を変えたから直ったはず」で入れ替えると、検品済みの音声を検品していない音声で上書きすることになるからです。

ここが核心。崩れを見つけたら、まずパイプラインの段ごとに同じ文を通して比べる。原因の段が分かれば、直す場所も、直らなかったときに何を元に戻せばいいかも決まる。


04 — 線引き

音声認識は「判定」ではなく「どこを聞くか」の絞り込み

ここで判断に迷うのが、Whisperが聞き取れない=人にも聞き取れないとは限らないことです。声質変換された声は、音声認識が苦手とする音の特徴を持っているだけかもしれません。逆に、認識が通ったから人にも明瞭に聞こえるとも言えません。

そこで、検品記録には次のように書く運用にしました。

✓
字幕の一致・音量・モーラ・ASRの完走を、聴取の合格の代わりにしないどれも「聞き取れる」ことの証明にはならない。
✓
音声の総合判定は「人の聴取待ち(未完了)」のまま残す映像・技術の検査がPASSでも、全体をPASSと書かない。
✓
人に渡すのは、怪しい区間だけを抜いた確認用の音声数字を含む8区間を最終MP4から抜き出し、1秒の無音で区切った1本のwavにした。7分46秒を通しで聞く代わりに、約45秒で要所を確かめられる。

3つ目が、この検品でいちばん効いた点です。全編を通しで聞いて判断するのは、作った本人にも負担が大きい作業です。音声認識は、人が聞くべき場所を126区間から8区間に絞るふるいとして使うと、ちょうどいい役割に収まります。

この動画は、その後に企業事例を足した改訂版を作り、本人が聞いてOKを出したところで完成扱いにしました。最後に判断したのは人の耳です。AIの「できました」をそのまま信じず、証拠を確かめてから完了にする考え方はArt30にも書きました。音声の検品も同じで、自動で確認できるところまでは機械に任せ、聞き取れるかどうかの判断だけを人に残しています。


05 — 自分の環境でやるなら

最小構成は「切り出し→文字起こし→数字の照合」

TTSや声質変換でナレーションを作っているなら、規模が小さくても同じ検品を足せます。骨組みはこうです。

# 考え方を示す骨組み(そのままでは動きません)
import whisper, re
model = whisper.load_model("small")          # ローカル実行

for cue in subtitle_cues:                      # 字幕の開始/終了と台本の文
    clip = cut_from_final_mp4(cue.start, cue.end) # 完成品から切り出す
    heard = model.transcribe(clip, language="ja")["text"]  # 期待文は渡さない
    want = re.findall(r"\d+", cue.text)
    got  = re.findall(r"\d+", heard)
    if want != got:
        flag(cue, heard)                          # 人が聞くリストへ

# flagした区間だけを1本の確認用wavに連結して、人に渡す

照合は数字に絞るのが現実的です。日本語の文字起こしは漢字・かなの揺れが大きく、全文一致で比べると誤検知だらけになります。数字の言い方(「18か月」と「十八ヶ月」など)は正規化が要るので、最初はフラグが多めに出る前提で、出たものを人が聞いて判断します。

フラグが出たら、03で書いたように原音と変換後を同じ文で聞き比べるのが次の一手です。TTSの段で崩れているならVOICEVOX側の読み(辞書やアクセント)を直せますし、声質変換で崩れているなら、その文だけ別の言い回しに書き換える、変換前の声のまま使う、といった逃げ道も選べます。

まとめ。合成音声は、文字に戻して台本と突き合わせれば機械で怪しい場所を拾える。ただし音声認識は判定者ではなくふるい。最後に聞いて決めるのは人で、その人に渡す量を減らすのが自動化の仕事です。

本記事は筆者の動画制作パイプライン(2026年9〜10月)の検品記録に基づきます。使用した音声認識モデルはOpenAI Whisper-small(ローカル実行)。認識結果は条件やモデルの大きさで変わるため、ここで示した誤認識が他の環境でも同じように出るとは限りません。骨組みのコードは考え方を示すためのもので、切り出しや字幕データの読み込みは各自の環境に合わせて実装が必要です。