何をしたかったか
英語学習アプリ Words Admin に「AI-Lesson」という機能があります。レッスン1本の録音と資料の写真をまとめて見直す機能で、公開先は https://words-admin.web.app/lesson です。文字起こしと話者の分けには Google の Gemini API(gemini-2.5-flash)を使い、声の高さ・大きさ・間の測定は AI を使わない自前の信号処理で行っています。
2026-10-14 に、42分32秒の録音をこの機能に通しました。以下は、その1本を通す過程で測った数字と、そこから決めた直し方の記録です。録音の中身(誰が何を話したか)は扱いません。
何を測ったか: まず「上がらなかった」原因
最初の問題は、解析がそもそも始まらなかったことでした。推測で直す前に、どこで止まっているかを数えました。
| 測ったもの | 結果 |
|---|---|
| 解析の関数の呼び出し(直近30日) | 0回 |
| ファイル置き場に届いた物(当日) | 0件 |
| 元の録音 | 214.7MB(44.1kHz モノラル 16bit・2552.0秒=42分32秒) |
| 19MB ずつに分けたときの数 | 12 |
| その利用者の今月の残り回数 | 3 |
関数の呼び出しが0回、ファイル置き場に届いた物も0件。つまりサーバには何も届いていません。原因は画面側にありました。録音を 19MB ずつ12個に分け、「分けた数 12 > 残り回数 3」と判定して、上げる前に「残り回数が足りません 3 / 12」と断っていたのです。
一方、サーバ側は1本の録音を何個に分けても1回と数える作りでした。画面とサーバで数え方が食い違っていたため、サーバなら通る録音を画面が止めていました。
直し方は、分けるのをやめることです。録音は1本のままファイル置き場へ上げ、途中から再開でき、進み具合を表示する形にしました。16kHz モノラルへの変換と、処理の単位への分割はサーバ側で行います。
何が分かったか: 1回で投げると最後の275秒が返ってこない
上がるようになった次に出たのが、この記事の主題です。42分32秒を1回のリクエストで投げたところ、終了の理由は finishReason=STOP でした。これは正常終了を意味します。
ところが、返ってきた文字起こしの最後の発話は 2277秒の位置で、録音は 2552秒あります。最後の 275秒が返ってきていませんでした。
この 275秒が無音だった可能性も確かめました。平均は -23.8dB で、録音全体と同じです。さらに、末尾 280秒だけを切り出して単独で投げると、70ターン・496語が取れました。同じ区間が単独なら取れるのですから、落ちた原因は長さです。
ここで重要なのは、エラーにならないという点です。正常終了のまま末尾が欠けるので、「届いた秒数」を数えない限り気づけません。
どう直したか: 窓に割り、窓ごとに「届いたか」を数える
直した形は次のとおりです。
- 録音を8分の窓に割る。切れ目は、その付近でいちばん長い「間」を選び、話の途中で切らない。
- 窓ごとに文字起こしが返ってきたかを数え、取れなかった窓は画面に番号で出す。
直した後の本番の実測は、2552/2552秒・6/6窓、546ターン・4,143語でした。窓の数と秒数を両方数えることで、「正常終了したが欠けている」状態を検出できるようになりました。
AIが申告する秒数と、音量で決める発話時間は使わない
文字起こしの位置(何秒目か)についても、別の実測がありました。280秒の切り抜きに対して、Gemini は「419秒」の位置を答えたのです。切り抜きの長さを超えた値なので、そのままでは使えません。
そこで位置は、自前で測った「声が鳴っている区間」の並びに、文字起こしの語数で順番に割り当てる方法にしました。これは「おおよその位置」であり、画面にもそう書いています。
「声が鳴っている区間」の測り方にも落とし穴がありました。この録音は、短い枠ごとの音量が p5=-32.5dB〜p99=-13.4dB で、開きが 19dB しかなく、無音の床がありません。環境の雑音が常に乗っている状態です。音量に線を引くと、線の置き方で「話している時間」が 436秒にも 2042秒にもなり、測ったことになりませんでした。
そのため音量ではなく、周期性(自己相関)で声を見分けます。ここでも1点注意があり、自己相関は「最大値」ではなく「山の頂上」を選びます。最大値をそのまま採ると上限の 400Hz に貼り付き、42分の中央値が 400Hz ちょうどになっていました。
直した後の値は、声の高さの中央値 150Hz、上下の幅 10.7 半音、声が鳴っていた時間 731秒、0.5秒以上の間 716回、いちばん長い間 32.6秒、計算にかかった時間 5.8秒です。なお「声が鳴っていた時間」は無声の子音を含まないため、「話していた時間」とは同じではありません。用語も測ったとおりにしました。
費用と上限の決め方
費用は、2026-10-14 に公式の料金ページ https://ai.google.dev/gemini-api/docs/pricing で確認した単価と、実測のトークン数から出しました。gemini-2.5-flash は音声の入力 $1.00 / 100万トークン、出力 $2.50 / 100万トークンで、音声は 32 トークン/秒です。
42分32秒を1回で投げたときの実測は、入力が音声 81,633+文字 202、出力が 20,795+思考 799 トークンで、$0.136(約 ¥20)でした。窓に割ると指示文が増えるので、概算 $0.14 としています。
上限は3つで掛けています。1人1日 60分(無料)/180分(有料)、全体で1日 600分、1本 120分まで。数えられなかったら断ります。また、1語も取れなかった回は使った分数を返します。これは、全部落ちた回に 43分が引かれたままになっていたのを実測で見つけたためです。
業務に置き換えると
議事録・面談記録・通話の文字起こしを AI に任せるとき、今回の実測から点検できる項目は次のとおりです。
- 長い録音は「正常終了」のまま末尾が欠けることがある。届いた秒数と窓の数を必ず数える。
- AI が答える時刻は検算する。合わなければ使わない。
- 音量だけで発話区間を決めない。雑音の多い会議室では、線の位置で結果が数倍変わる。
- 1本あたりの費用は、実測のトークン数と公式単価から出せる。上限は「1人・全体・1本」の3つで掛ける。
- 画面とサーバで回数の数え方がそろっているかを確かめる。食い違うと、通るはずの依頼が送る前に止まる。
この記事は、TechAthletes が自社のサービスを作る中で記録した実測をもとに書いています。業務への導入のご相談は 仕事の窓口 で受け付けています。