おはようございます。まさきんです。
習い事の体験説明を録音して、Whisper で文字起こししました。文章はそれらしく読めるのに、金額の数字だけが違っていました。録音を家計の判断材料にする人には関係がある話だと思うので、公式情報と合わせて整理しておきます。
※記事公開時点の情報です。最新の条件は公式サイトでご確認ください。
- 約11分の説明の録音を faster-whisper で起こすと、small では金額が全部違っていた
- medium でも料金の数字は別の数字のままで、large-v3 でやっとチラシと一致した
- initial_prompt にヒントを入れたら、静かな区間でプロンプト自体が繰り返し出力された
- 金額の確認は、該当箇所だけ切り出して large-v3 にかけるのが安全だと思う
- 設定は prompt なしと condition_on_previous_text=False を基本にして、最後は紙と突き合わせる
文字起こしは金額の数字を聞き違える
ある習い事の体験説明を、約11分録音しました。あとで月会費などを落ち着いて比べたかったからです。
文字起こしには faster-whisper を使いました。出てきた文章は、話の流れとしては自然に読めます。ただ、配られたチラシと並べてみると金額が合いませんでした。
例えば、数千円台の月会費の千の位が別の数字になっていました。文としては成立しているので、チラシが無ければ気づけなかったと思います。
small と medium では数字が違っていた
最初に使ったのは small です。金額として出てきた数字は、全部チラシと違っていました。
次に medium で起こし直しました。こちらでも料金の数字は別の数字になっていました。サイズを一段上げれば直る、という話ではなかったんですね。
厄介なのは、間違いが間違いに見えないところです。「月会費は◯千円です」という形は保たれています。数字だけが入れ替わっているので、読んでいて引っかかりません。
large-v3 で切り出した区間はチラシと一致した
最後に、金額を話している箇所だけを切り出しました。その短い音声を large-v3 で起こすと、チラシの金額と一致しました。
なので、僕の手元では「数字の確認は large-v3」という結果になっています。とはいえ、これは一つの録音での話です。large-v3 なら必ず合う、とまでは言えないと思います。
確かめられたのは、紙のチラシが手元にあったからでした。文字起こしだけで金額を確定させなかったのは、結果としてよかったのかもしれません。
モデルサイズの比較(公式READMEの数値)
OpenAI の Whisper 公式リポジトリには、モデルサイズの一覧が載っています。README の表をそのまま整理しました。
| サイズ | パラメータ数 | 必要VRAMの目安 | 相対速度 |
|---|---|---|---|
| tiny | 39 M | 約1GB | 約10倍 |
| base | 74 M | 約1GB | 約7倍 |
| small | 244 M | 約2GB | 約4倍 |
| medium | 769 M | 約5GB | 約2倍 |
| large | 1550 M | 約10GB | 1倍 |
| turbo | 809 M | 約6GB | 約8倍 |
相対速度は、large を1としたときの目安です。README には、A100 というGPUで英語の音声を起こして測った値だと書かれています。言語や話す速さや機材で、実際の速度は大きく変わるという注意もありました。
表の large には版があります。モデルカードによると、2022年12月に large-v2 が出ています。large-v3 は2023年11月の公開です。
turbo は2024年9月に追加されました。README では、large-v3 を最適化した版と説明されています。精度の低下は最小限で、速度が上がるとのことです。ちなみに turbo のパラメータ数は、README では 809 M ですがモデルカードでは 798 M でした。
faster-whisper は何が違うのか
faster-whisper は、Whisper を別の推論エンジンで動かす再実装です。公式 README では、CTranslate2 という高速な推論エンジンを使うと説明されています。
同じ README には、本家と同じ精度で最大4倍速いと書かれていました。メモリの使用量も少ないそうです。8ビット量子化で、さらに効率を上げられるともあります。
モデル名は WhisperModel("large-v3") のように指定します。この形で書くと、変換済みのモデルが自動でダウンロードされるとのことです。
initial_prompt と condition_on_previous_text の意味
今回関係した設定は2つあります。どちらも本家と faster-whisper の両方にあるものです。
initial_prompt は、最初のウィンドウに渡すヒントの文章です。本家のソースの説明では、固有名詞や独自の語彙を当てやすくする使い方が例に挙がっています。
condition_on_previous_text は、直前の出力を次の区間のヒントに回すかどうかです。既定値は True になっています。説明文には、切ると区間ごとに表記がばらつくかもしれないとあります。一方で、同じ文の繰り返しのような失敗のループに入りにくくなるとも書かれていました。
| 設定 | 意味(公式の説明) | 金額確認時のおすすめ |
|---|---|---|
| モデルサイズ | 大きいほど遅く、必要なメモリも増える | 該当箇所だけ large-v3 |
| initial_prompt | 最初のウィンドウに渡すヒント文 | 入れない |
| condition_on_previous_text | 直前の出力を次の区間のヒントにする(既定は True) | False にする |
| vad_filter | 声のない部分を取り除く(faster-whisper) | True にする |
| language | 話されている言語を指定する | ja を指定する |
右の列は、公式の説明と今回の体験から僕が選んだものです。公式がこの組み合わせを勧めている、という意味ではありません。
押すと楽天のログインページが開きます。ログイン後にキャンペーン内容が表示されます。
プロンプトを渡したら、プロンプト自体が繰り返された
数字を当ててほしくて、initial_prompt にヒントを渡してみました。すると静かなクリップで、プロンプト自体を繰り返す出力が出ました。
話されていない言葉が、文字として並んでいたわけです。金額の確認をしたいのに、ヒントの文面がそのまま返ってくる。これでは確認になりません。
なので、金額を確かめるときはプロンプトを入れないほうが安全だと考えています。ヒントに数字を書くと、それが出力に混ざるおそれもあると思います。
ハルシネーションについての公式の記述
話されていない言葉が出る現象は、公式のモデルカードにも書かれています。ハルシネーションと呼ばれるものです。
モデルカードによると、Whisper は大量の雑音まじりのデータで学習しています。そのため、音声で実際には話されていない文章が出力に含まれることがあるそうです。
繰り返しについても記述がありました。モデルの構造上、同じ文章を繰り返し生成しやすいとのことです。ビームサーチなどである程度は抑えられますが、完全ではないとされています。
文字起こしの間違いは、もっともらしい文章の形で出てきます。数字が違っていても、文として読めてしまうのが一番の落とし穴だと感じています。
無音区間は vad_filter で取り除ける
faster-whisper には VAD フィルタという機能があります。声が入っていない部分を、起こす前に取り除く仕組みです。公式 README では、Silero VAD というモデルを組み込んでいると説明されています。
使い方は、vad_filter=True を足すだけです。既定の動作は控えめで、2秒より長い無音だけを取り除くと書かれていました。細かい調整は vad_parameters で行えます。
もう一つ、hallucination_silence_threshold という設定もあります。単語単位のタイムスタンプを有効にしたときに使えるものです。ハルシネーションが疑われる場面で、指定した秒数より長い無音を飛ばすと説明されていました。
日本語の精度についての公式の記述
公式 README には、精度は言語によって大きく変わると書かれています。large-v3 と large-v2 の言語別の成績は、図で示されていました。
モデルカードには学習データの内訳もあります。68万時間のうち、65%が英語の音声と英語の書き起こしです。英語以外の音声とその言語の書き起こしは、17%とされています。
データの少ない言語では精度が下がる、という記述もありました。ハルシネーションや繰り返しも、そうした言語では悪化する可能性が高いそうです。日本語がどの程度かを示す数字は、この記事では挙げていません。
用途別の使い分け
全部を large-v3 で起こす必要は、たぶんありません。話の流れをつかむだけなら、軽いモデルでも足りる場面は多いと思います。
| 用途 | モデル | 範囲 | 確認の方法 |
|---|---|---|---|
| 全体の流れをつかむ・要約する | 軽いモデル | 録音の全体 | 細部は信用しすぎない |
| 金額・日付・回数を確かめる | large-v3 | 該当箇所だけ | 紙や公式の資料と突き合わせる |
| 契約に関わる条件を確かめる | large-v3 | 該当箇所だけ | 最後は自分の耳で聞き直す |
ポイントは、数字が出てくる箇所だけを別扱いにすることです。全体の起こしは「どこで金額の話をしていたか」を探す地図として使えます。
金額だけを確かめる手順
僕がやった流れを、手順の形にするとこうなります。
- 軽いモデルで全体を起こし、金額の話が出てくる時刻をメモする
- ffmpeg でその区間だけを切り出す
- 切り出した音声を large-v3 で起こす
- プロンプトは渡さず、condition_on_previous_text は False にする
- 出てきた数字を、チラシや書面と突き合わせる
切り出しは ffmpeg で1行です。公式ドキュメントによると、-i の前に置いた -ss は開始位置を指します。同じく -t は読み込む長さです。下の例は、5分30秒の位置から60秒ぶんを取り出します。
ffmpeg -ss 00:05:30 -t 60 -i recording.m4a clip.wav
起こす側は、公式 README の書き方をもとにするとこのようになります。GPUが無い場合の書き方も README にあったので、そちらに合わせています。
from faster_whisper import WhisperModel
model = WhisperModel("large-v3", device="cpu", compute_type="int8")
segments, info = model.transcribe(
"clip.wav",
language="ja",
condition_on_previous_text=False,
vad_filter=True,
)
for segment in segments:
print("[%.2fs -> %.2fs] %s" % (segment.start, segment.end, segment.text))
README には注意書きが一つありました。segments はジェネレータなので、ループで回したときに初めて処理が走るそうです。
よくある失敗・落とし穴
今回の件を振り返ると、つまずきやすい点はこのあたりだと思います。
- 文章が自然に読めるので、数字も合っていると思い込む
- モデルを一段上げれば直ると考えて、small から medium にだけ変える
- 数字を当てたくて、プロンプトに金額のヒントを書く
- 無音の多い音声を、そのまま全部かけてしまう
- 突き合わせる紙や資料を、その場でもらい忘れる
僕に当てはまったのは、上の3つです。最後の一つは、チラシが配られていたので助かりました。
口頭の説明だけで資料が無い場面もあると思います。その場合は、金額だけその場でメモしておくのが確実かもしれません。録音は、あくまで聞き直すための材料ですね。
始める前に確認すること
説明の録音を文字起こしで確かめたい方向けにまとめました。
- 録音してよいかをその場で確認した
- 金額が書かれた紙や資料を受け取った
- 金額の話が出てくる時刻をメモした
- 該当箇所だけを切り出して large-v3 で起こした
- プロンプトを渡さずに起こした
- 出てきた数字を紙と突き合わせた
特に二つ目が大事だと思います。突き合わせる相手があるだけで、文字起こしの使い方がずっと楽になります。
文字起こしを家計の判断に使うときの距離感
説明会や契約の説明は、情報が多くて覚えきれません。録音して文字にすると、あとで落ち着いて比べられます。これは非常に便利だと思います。
ただ、家計の判断で効いてくるのは金額と日付です。そこが一番間違いやすい、というのが今回の発見でした。便利な部分と信用できる部分は、同じではなかったんですね。
仕事でも、数字は元のデータに当たって確かめます。要約は流れをつかむために使い、数字は原本で見る。家の中でも同じ線引きでよいのかもしれません。
紙の情報を扱う話は、学校のプリントをカレンダーに登録する仕組みでも書きました。AIに任せる範囲の線引きは、ログイン必須の予約をAIに頼んだ話が近いと思います。通話の内容をまとめる機能については、Rakuten Link のAI通話要約機能の記事もあります。
- 全体の流れ:軽いモデルで起こして、要約や検索に使う
- 金額と日付:該当箇所を切り出して large-v3 で起こす
- 最終確認:紙や公式の資料と並べる。無ければ自分の耳で聞き直す
よくある質問
Q. Whisper はなぜ数字を間違えるのですか?
理由をはっきり書いた公式の記述は、見つけられませんでした。モデルカードには、話されていない文章が出力に含まれることがあると書かれています。数字に限った説明ではないので、原因は断定しないでおきます。
Q. small と medium ではどちらが正確ですか?
公式 README では、サイズごとに速度と精度のトレードオフがあるとされています。僕の録音では、どちらも金額の数字は違っていました。数字の確認が目的なら、サイズの比較より突き合わせを優先するのがよさそうです。
Q. large-v3 なら金額は必ず合いますか?
必ず合うとは言えないと思います。僕の場合は、切り出した区間でチラシと一致しました。とはいえ一つの録音での結果なので、紙との突き合わせは省かないほうが安全です。
Q. turbo と large-v3 はどう違いますか?
公式 README では、turbo は large-v3 を最適化した版とされています。精度の低下は最小限で、相対速度は約8倍という目安です。僕は turbo では試していないので、数字の聞き取りについては分かりません。
Q. initial_prompt は使わないほうがよいですか?
固有名詞を当てやすくする使い方は、公式の説明にも載っています。なので、使うこと自体が悪いわけではないと思います。ただ、僕は静かなクリップでプロンプトの繰り返しが出ました。なので金額の確認では外しています。
Q. condition_on_previous_text を False にすると何が変わりますか?
直前の出力を、次の区間のヒントに使わなくなります。公式の説明では、区間ごとに表記がばらつく可能性があるそうです。代わりに、繰り返しのループには入りにくくなるとされています。
Q. vad_filter は最初から有効ですか?
通常の transcribe では、既定値は False です。なので、使うときは自分で True を指定します。README によると、バッチ処理のほうでは既定で有効になっているそうです。
Q. faster-whisper を使うのに ffmpeg は必要ですか?
faster-whisper の README では、ffmpeg を別に入れる必要はないとされています。音声の読み込みに使うライブラリに含まれているためです。ただ、区間の切り出しをコマンドで行うなら ffmpeg 本体が要ります。
参考にした公式情報
- openai/whisper README(OpenAI 公式リポジトリ)
- Model Card: Whisper(OpenAI 公式リポジトリ)
- whisper/transcribe.py(OpenAI 公式リポジトリ)
- faster-whisper README(SYSTRAN 公式リポジトリ)
- faster_whisper/transcribe.py(SYSTRAN 公式リポジトリ)
- ffmpeg Documentation(FFmpeg 公式サイト)
まとめ
文字起こしは、話の流れを残すにはとても助かる道具です。ただ、金額の数字は small でも medium でも違っていました。large-v3 で切り出した区間を起こして、やっとチラシと一致しています。
なので、全体は軽いモデルで起こすことにしました。数字のところだけ別に確かめる形です。プロンプトは渡さず、最後は紙と並べます。
説明の録音が手元にある方は、金額の箇所だけでも資料と見比べてみてはいかがでしょうか。
押すと楽天のログインページが開きます。ログイン後にキャンペーン内容が表示されます。
本記事にはアフィリエイト広告を含みます。当サイトのリンクを経由して商品・サービスへお申し込みいただいた場合、提携先企業から成果報酬を受け取ることがあります。 また、運営者は楽天グループに所属する社員であり、紹介プログラムを通じた報酬を受け取る場合があります。記事内容・評価は広告の有無にかかわらず、運営者の実体験と調査に基づき作成していますが、 上記の関係性をご理解のうえお読みください。詳しくは免責事項・アフィリエイト表記をご覧ください。
楽天モバイルの通信エリア・電波状況について気になることがある方は、公式の電波改善・調査依頼フォームからご相談いただけます。