🛠 ツール制作ログ

Whisperで文字起こしが遅い&変になるのは“無音”のせい!? 実録・生徒の声で精度爆上げできた話

Whisperで文字起こしが遅い&変になるのは“無音”のせい!? 実録・生徒の声で精度爆上げできた話

「Whisperで文字起こしすると、なんか変な日本語が出てくる…」

「ていうか、そもそも処理に時間かかりすぎじゃない?」

そんな風に感じたこと、ありませんか?

私も最初は「APIが重いのかな?」なんて思ってたんですが、原因はまさかの“無音”でした。

こんにちは、ノーコード+AIでちょっと便利なツールを作ってる、シランコーダーです。

今回は、英語コーチングセッションの生徒音声をWhisperで文字起こししたときに、不自然な発言が大量に出現&処理がやたら遅いという事件が発生。

「なにこれ…“アイノーダット”を10回くらい連呼してるんだけど!?」

「生徒さんそんなこと言ってないのに、なんで?」

そんな混乱から始まり、原因をひとつずつ検証し、最終的にたどり着いたのは

「音声の前処理が超大事だった」というシンプルだけど強烈な気づきでした。

この記事では、実際にどんな音声だったのか?

なにをどう処理したら、22秒で文字起こしが終わるレベルに改善されたのか?

非エンジニア視点でリアルに紹介していきます。

🔍 なにが起きた?謎の“アイノーダット”大量発生

ある日、いつもどおりWhisper APIでセッション音声の文字起こしを実行。

今回の対象は、生徒さん側の録音データ(Zoom録音の片チャンネル)です。

「処理にちょっと時間かかってるな〜」と思いつつ、しばらく待って出力されたログを確認すると…

[289.36s - 292.36s] アイノーダット  
[292.36s - 294.36s] アイノーダット  
[294.36s - 296.36s] アイノーダット  
[296.36s - 298.36s] アイノーダット  
[298.36s - 300.36s] アイノーダット  
[300.36s - 302.36s] アイノーダット  
[302.36s - 304.36s] アイノーダット

……おや?

生徒さん、こんなこと一言も言ってなかったはずなんですが……?

しかも、その前後にも「えー」「うん」「あー」みたいな

曖昧な発話っぽい文字が連続して出てきて、全体の内容もなにかおかしい。

これは明らかに異常。

ですが同時に、“よくある”ことでもあります。

実はこれ、Whisperが無音やノイズに「何かをしゃべってる」と勘違いしてしまったときに起きる、ありがちな現象なんです。

でも、そもそもなぜこうなってしまったのか?

その原因は次のセクションでくわしく見ていきます。

🎧 原因は“無音”? Whisperが悩んでしまう理由

今回の音声は、Zoomで録音した生徒さんのチャンネル音声

つまり、生徒が話していない時間は、ほぼ完全に“無音”でした。

ここに問題があります。

Whisperは、音声ファイル全体を通して「人間の発話っぽいもの」を探し、文字起こしを行うAIです。
ところが、無音が続くと👇

  • 📉「あれ、これなんか聞き逃してる?」と勘違い
  • 🎲 とりあえず「聞こえたっぽい何か」を出そうとする
  • 🌀 結果「アイノーダット」「うーん」「4時半」など謎ワードを連発…

まるで、無音のなかで幻聴を見てしまったAIのような出力になってしまうのです。

しかもこの無音部分に反応しようとするせいで、

  • 文字起こしにやたら時間がかかる
  • 出力が無意味な文字で埋まる
  • 使いたいログが見つけにくくなる

という、地味にダメージの大きい問題が連鎖的に発生します。

では、どうすればこの“無音の罠”を回避できるのか?

🛠 事前処理で解決!ベストな音声加工手順

Whisperにとって“無音”は天敵。

でも、その無音を削除するとタイムスタンプがズレてしまう…

かといって、そのままにすると処理は遅いし、精度も落ちる

この矛盾を解決するベストな方法がこちら👇

✅ Normalize + Compressor(音量補正)

  • Normalize(ノーマライズ)
     音声全体の音量を均一に調整し、小さな声も聞き取りやすくします。
  • Compressor(コンプレッサー)
     突発的な大きな音を抑えて、聞きやすさをアップ。
     結果として、Whisperが発話部分を“発話”として認識しやすくなります。

🔎 この2つを組み合わせることで、無音に悩まず、発話だけをちゃんと拾うようになります。

✅ モノラル化+サンプリングレート統一(16kHz)

Whisperはステレオよりモノラルが得意。

また、16kHzなどの標準的なサンプリングレートでそろえることで、無駄な混乱を避けられます。

💡 実際にこの手順で処理した音声では、Whisperがスムーズに音を追えるようになり、処理時間も劇的に短縮されました

なお、無音を完全にミュートする方法も試しましたが、Whisperが逆に困って「幻聴」を見始めてしまったので不採用に。

📌 結論:無音は削らずに“静かにする”のが正解!

次は、実際にどういう文字起こし結果が得られたかを見ていきましょう。

ただし…完璧とは言えません。その理由も合わせてご紹介します。

📄 精度は?出力結果と課題まとめ

音声をしっかり整えて、満を持してWhisperで文字起こし!

その結果、処理速度と精度にはこんな変化がありました👇

⏱ 処理スピードの改善がすごい!

  • Before(生声そのまま)
     1ファイルあたり最大で 5分以上 待たされることも…
  • After(Normalize+Compressor処理済)
     同じ音声が わずか22秒 で完了!

🧠 Whisperが無音で迷わなくなり、「聞くべきところ」に集中できるようになった結果です。

✅ 精度の向上も体感レベル

  • 小声・ぼそぼそ声がしっかり拾われるように
  • 単語の切れ目や発話の始まりも認識しやすくなった
  • 発話ごとのタイムスタンプが安定して付くように

🎉 Whisperのポテンシャルを、ようやくちゃんと引き出せた感じ!

❗ でも完全ではない。課題も…

たとえば…

[302.36s - 307.36s] Thank you for listening
[338.36s - 341.36s] Thank you for listening
[368.36s - 372.36s] Thank you for listening
[379.36s - 382.36s] Thank you for listening
[389.36s - 392.36s] Thank you for listening

💥 同じフレーズを何度も幻聴のように出力する現象は、まだ解消しきれていません。

これは無音処理とは別の問題で、Whisperが音声の“雰囲気”だけを手がかりに勝手に再生してしまうことが原因。

この対策については、後述のセクション「🔍 連打対策:幻聴ループはどう防ぐ?」で詳しく紹介します。

🧩 ファイル統合&話者付けでセッション化

音声の前処理と文字起こしが終わったら、次はセッション全体の会話ログを1つに統合する作業です。ここでは以下の3つをセットで処理します。

① divisionファイルの結合

Whisper APIにはファイルサイズ制限があるため、20MBを超える音声は分割していました。

そこで必要になるのが、divisionごとの文字起こし結果を合体させる処理

input_audio/
  ├─ 〇〇__division_1.wav
  ├─ 〇〇__division_2.wav
  └─ 〇〇__division_3.wav
↓
input_json/
  └─ session_xxx_raw.json(タイムスタンプ順に結合されたログ)

② タイムスタンプ補正(division 2以降)

分割された音声は前後10秒の重複を含んでいるため、division 2以降のセグメントにはオフセットを加えて整合性をとります。

例:

division2_start_offset = 12 * 60  # 12分=720秒
segment["start"] += division2_start_offset
segment["end"] += division2_start_offset
division2_start_offset = 12 * 60  # 12分=720秒
segment["start"] += division2_start_offset
segment["end"] += division2_start_offset

これで、全体を通して正しいタイムラインが復元されます。

③ 発話者タグの自動付与

コーチと生徒の音声は別ファイルで処理しているため、話者の区別は簡単です。

{
  "speaker": "coach",
  "text": "じゃあ、次いってみましょうか。",
  "start": 33.2,
  "end": 35.1
}

これにより、セッション全体を通した「誰が何を言ったか」のログが完成!

🎯 この「話者付き・時間整列済み」のログが、レポートや分析の基礎データになります。

⚠️ Whisperの罠!?「連打ループ」と「空白ノイズ地獄」

Whisperの精度がすごいのは間違いないんですが、今回は想定外の落とし穴にハマりました。

特に「生徒の音声」によくある2大トラブルをご紹介します。

[289.36s - 304.36s] アイノーダット
[304.36s - 307.36s] アイノーダット
[308.36s - 341.36s] Thank you for listening(計4回)

生徒は一度しか言っていないのに、Whisperくんは鬼のように連打してくることがあります。

🤔 原因は?

  • 無音のあとにちょっとした音が入り、その前の発言を誤って繰り返している
  • 発音が不明瞭だと、Whisperが「さっきのやつかな?」と誤認

✅ 対処法(現状)

現時点では、あとで人の目でチェックして削除するしかありません。

ただし、こういった「連打っぽいフレーズ」だけを自動検知して省くルールづくりも可能です。

今後は、GPTや音響的特徴を使って対処する予定です。

🔇 ② 無音すぎてWhisperが迷子に!?

意外だったのが、無音が多すぎるとWhisperが迷うということ。

  • 話してないのに「うん」「あー」と勝手に書かれる
  • 空白時間に意味のない単語が補われる

🧪 実験の結果…

Normalize + Compressor をかけるだけで→ 変な発言が激減&処理速度も爆速になりました。

❌ 処理前:7分の音声に10分以上かかる+謎の連打だらけ  
✅ 処理後:22秒で完了+誤認識激減

🎯 本記事の最大の学び

Whisperは優秀だけど、

「人間の話し方」に最適化されてるから、無音が多いと逆に精度が落ちる!

だからこそ👇

  • Normalize + Compressor は神処理
  • 完全ミュート処理はむしろ逆効果
  • 今後は「発話の少ない人ほど音声前処理が重要」になる

🧩 最後のピース:「JSON構造化」&「レポート整形」へ

文字起こしが終わったら、いよいよ実用レベルの整形処理に入ります。

この段階では、「使えるデータかどうか」がすべて。

🗂 まずは構造化:session_{id}_raw.json の完成

Whisperで得られた発話ログをベースに、以下の形式で構造化します:

{
"start": 289.36,
"end": 291.36,
"speaker": "student",
"text": "アイノーダット"
}
  • 🔑 start / end:タイムスタンプ(divisionが複数ある場合はoffset加算済)
  • 🧑‍🏫 speaker:処理していた音声が生徒なので、全て "student" に固定
  • 💬 text:Whisperの認識結果(必要に応じて誤字補正も)

💡 division分割がある場合でも、すべてのログをタイムスタンプ順にソートして1つのJSONに統合しています。

この一貫性が、あとからの可視化やレポート整形の基盤になります。

📝 今回は整形ルールに未着手

今回は、「Normalize + Compressor の有効性」を検証することが主目的だったため、

整形(連打削除・誤認補正・前後文脈判断など)は未実施です。

ですが、今後のステップでは以下を計画しています:

  • ✅ 変な連打(同じ単語が連続してる)をGPTで検出・削除
  • ✅ 「発言の意図」や「思考のゆらぎ」なども拾えるログ整形
  • ✅ コーチ音声とのマージ(話者ごとのデータを時系列で統合)

🌱 最後に:声のゆらぎを“見える化”するために

今回の検証を通して改めて思ったのは、

いい文字起こしは、感情を伝える“声のメモ”になる

ということ。

だからこそ、ただの変換ではなく👇

  • 🧼 ノイズを整え
  • 🕰 時系列を守り
  • 💬 人の言葉らしさを保つ

この一連の流れが「AIでセッションを記録する」未来の基盤になると思っています。

  • この記事を書いた人

SHIRAN

「コードは知らない。でも作れる。」AIとツールで便利を生む非エンジニア。挫折も経験しながら、今は作る楽しさを発信中。詳しくはこちら

-🛠 ツール制作ログ
-, , ,