英語の動画や会議を見ながら、日本語字幕をリアルタイムに出したい。
そのために、OCI Speech Live TranscribeとOCI Languageを使ったリアルタイム英日翻訳アプリを作りました。
この記事で扱うのは、アプリの作り方そのものではなく、OCI Speech Live Transcribeの仕様を踏まえた「どのような結果を返すか」と「その結果を字幕としてどう見せるか」です。
結論(TL;DR)
- OCI Speech Live Transcribeは、音声を流し込みながら文字起こし結果を受け取るWebSocketベースの方式
- 認識途中の
partialと確定済みのfinalは、同じ字幕として扱わないほうが読みやすくなる - 自分が実装したアプリでは、
partialを「更新される下書き字幕」、finalを「翻訳して履歴へ残す確定字幕」とした - リアルタイム英日翻訳の難しさは、翻訳APIを呼ぶことよりも、いつ翻訳して、いつ画面に確定表示するかを決めることにあった
作ったもの
ブラウザから英語音声を入力すると、OCI Speech Live Transcribeが英語をリアルタイム認識し、OCI Languageが日本語へ翻訳します。
表示するのは日本語字幕で、必要に応じて英語認識文も併記できます。
OCI Speechの2つの文字起こし方法
OCI Speechには、大きく2つの利用方法があります。
| 機能 | 向いている用途 | 結果の受け取り方 |
|---|---|---|
| Transcription Job | 録音済みファイルの文字起こし | 処理が終わった後に受け取る |
| Live Transcribe | 会議、通話、動画再生などのライブ音声 | 音声送信中に随時 |
今回使用したのは後者のLive Transcribeです。
音声ストリームを送信し、認識結果をリアルタイムに受け取れます。
公式ドキュメントでも、Live Transcribeはストリーミング音声を送信し、テキスト結果をリアルタイムに受け取る機能として説明されています。
Using Live Transcribe(Oracle公式)
Live Transcribeの仕様
Live Transcribeは、音声ファイルを送って処理完了を待つ方式ではありません。
音声を送り続けながら、サービスから文字起こし結果や接続状態の知らせを受け取ります。
技術的には、この知らせを「イベント」と呼びます。
| イベント | 意味 | アプリでの扱い |
|---|---|---|
CONNECT |
接続できたという知らせ | 画面を「接続中」から次の状態へ進める |
ACKAUDIO |
音声を受け取ったという知らせ | 音声が届いているかを確認する |
RESULT |
文字起こし結果 | 途中か確定かを見て、字幕へ反映する |
ERROR |
問題が起きたという知らせ | 接続や音声設定を確認する |
アプリ側からは、SEND_FINAL_RESULT という「ここまでの認識結果を確定してほしい」という合図も送れます。
本アプリでは、停止時や発話の切れ目で使っています。
イベントの正式な名前と向きは、RealtimeMessageResultのSDKリファレンスで確認できます。
partial と final は何が違うのか
文字起こし結果には、発話の途中で変化する partial と、認識が完了してもう書き換わらない final があります。
本アプリでは、結果についている「確定済み」(isFinal)で区別しています。
話し手: "Today I would like to explain our new product."
partial "Today I would..." ← 次の結果で更新される
partial "Today I would like to..." ← 次の結果で更新される
partial "Today I would like to explain..." ← 次の結果で更新される
final "Today I would like to explain our new product."
← 確定結果
ここで大切なのは、「partialが間違い」なのではなく、「まだ書き換わる可能性がある」ということです。
partialをすぐに表示すれば反応は速く見えますが、そのまま翻訳・保存すると、英語も日本語も何度も更新されます。
英語と日本語は語順が異なるため、この問題は英日翻訳で特に目立ちます。
partial: We are going to ...
下書き訳: 私たちはこれから...
partial: We are going to release ...
下書き訳: 私たちはリリースします...
final: We are going to release the new version next week.
確定訳: 私たちは来週、新しいバージョンをリリースします。
Live Transcribeで調整できる主な設定
OCIコンソールでは、モデルタイプ、ドメイン、言語、句読点を選べます。Oracleモデルでは、途中結果と確定結果の振る舞いに関わる設定も用意されています。
| 設定名 | 内容 | 字幕への影響 |
|---|---|---|
partialSilenceThresholdInMs |
話すのを少し止めた後、途中字幕を出すまでの待ち時間 | 小さいほど途中字幕が早く出るが、細かく更新されやすい |
finalSilenceThresholdInMs |
話すのを止めた後、字幕を確定するまでの待ち時間 | 小さいほど確定が早いが、文の途中で区切られやすい |
stabilizePartialResults |
途中字幕が何度も変わるのを抑える設定 | 高くすると字幕の変化を抑えやすいが、表示が遅くなり得る |
punctuation |
句読点の付与方法 | 文末や区切りを判断しやすくなる |
公式ドキュメントでは、上の3つの設定はOracleモデル用とされています。
モデル、言語、句読点なども選べます。
Using Live Transcribe
注意: 途中字幕を変わりにくくすることと、字幕を確定することは別です。stabilizePartialResults を設定しても、partialはまだ途中の結果です。履歴に残すかどうかは、isFinal が付いているかで判断します。
リアルタイム英日翻訳では、字幕を2層に分けた
最初はpartialをそのまま翻訳して表示してみましたが、英語の認識結果が更新されるたびに日本語字幕も書き換わり、読みにくくなりました。
partialを捨てると字幕が出るまで待たせすぎます。
そこで、画面と内部状態を次の2層に分けました。
| 種別 | 表示 | 翻訳・保存 |
|---|---|---|
| partial | 最後の1行だけを下書きとして表示 | ある程度の長さになり、認識結果が落ち着いた場合だけ仮訳する。履歴には残さない |
| final | 下書きを消し、翻訳用の一時置き場へ入れる | 文脈を少しまとめて翻訳し、確定字幕と履歴へ追加する |
「翻訳用の一時置き場」は、finalをそのまま即時翻訳せず、短い断片が続く場合に数個だけまとめるための領域です。例えば We are going to と release the new version が別々のfinalで届いても、まとめてから翻訳すれば、より自然な日本語にできます。
この構成にした理由は、速さと読みやすさを別々に最適化するためです。
- 下書き字幕は、話している最中でも「今どの話題か」が分かる速度を担当します。
- 確定字幕は、あとから書き換わらず、読んだ内容が残る品質を担当します。
自分のアプリ実装で決めた3つのルール
1. final だけを履歴へ残す
partial は次の結果で変わるため、履歴、SRT、VTTには入れません。final を受け取った時点で下書きを消し、確定字幕だけを保存します。
これにより、エクスポートした字幕が「表示途中の断片」だらけになるのを防げます。
2. partialは少し待ってから仮訳する
partialは短い間隔で何度も届きます。そのたびに翻訳すると、翻訳回数が増えるだけでなく、古い翻訳結果が後から届いて、新しい字幕を上書きしてしまうことがあります。
本アプリでは、文字数を確認してから、500 ms(約0.5秒)だけ待ちます。この待ち時間の間に新しいpartialが届いたら、古いものは翻訳しません。さらに、翻訳結果が戻ったときに元のpartialがすでに更新されていれば、その結果も表示しません。
3. finalは少しだけまとめて翻訳する
finalでも、短い断片が連続することがあります。英日翻訳では、短すぎる単位で送るほど語順や主語が不自然になりやすくなります。
そこで、文末、語数、一定時間のいずれかを条件にして、複数のfinalを少しだけまとめてから翻訳します。完全な文を待ちすぎると遅くなるため、ここでも「意味優先」と「低遅延」のバランスを取ります。
料金の目安
| サービス | 課金の単位 | 無料枠 | 超過後の目安 |
|---|---|---|---|
| OCI Speech | 文字起こし時間 | 月5時間 |
$0.50 / 時間 |
| OCI Language Text Translation | 1,000文字ごとのトランザクション | 月1,000トランザクション |
$10 / 1,000トランザクション |
英語動画を1時間翻訳すると、約4.7万〜5.4万文字が目安です。finalだけを翻訳するこの実装なら、Languageの無料枠はおよそ18〜21時間分です。
注意: 価格や無料枠は変更される可能性があります。
公開・運用前には、OCI Speechの料金FAQとOCI Languageの価格表で、利用リージョン・契約に対応する最新価格を確認してください。
さいごに
OCI Speech Live Transcribeを使ったリアルタイム英日翻訳では、音声認識結果を受け取るだけでは十分ではありません。
partialとfinalの違いを前提に、下書き字幕と確定字幕を分けることで、反応の速さと字幕の読みやすさを両立できます。
OCI Speech Live Transcribeの仕様を確認すると、partial/finalの無音時間や途中字幕を安定させる設定は、まさにこの表示の調整に使うものだと分かります。
リアルタイム翻訳を作るときは、まずここを押さえると設計しやすくなります。

