リアルタイム音声翻訳の構築方法(28 分読了)
OpenAI は、専門通訳データを基に最適化され、双方向ストリーミングを可能にする「gpt-realtime-translate」モデルを発表し、ライブ通訳の精度と遅延問題を解決した。
キーポイント
通訳特化型アーキテクチャ
汎用音声モデルとは異なり、数千時間のプロ通訳データを学習しており、文脈を待ってから翻訳するよう最適化され、構文の違いによる誤訳を防ぐ。
双方向低遅延ストリーミング
入力音声を処理しながら同時に翻訳された音声ストリームを返す機能により、会話の自然な流れを損なわない超低遅延を実現している。
人間拡張型アプローチ
AI 音声エージェントの構築ではなく、人間の多言語能力を拡張・支援することを主目的としており、既存の通訳ワークフローへの統合を意図している。
3 つのライブ翻訳実装パターン
ブラウザタブ音声のキャプチャ、Twilio を介した電話通話、LiveKit を使ったビデオ通話の 3 つの異なる Audio Path にリアルタイム翻訳を追加する方法が紹介されています。
必要な環境とリソース
実装には OpenAI API キー、Node.js、および各デモ(電話・ビデオ)用に Twilio 電話番号または LiveKit プロジェクトの準備が必要です。
設定と制限
ターゲット言語を指定してセッションを設定し、70以上の入力言語と13の出力言語に対応していますが、カスタムプロンプトや音声選択はサポートされていません。
動的音声適応
固定された出力音声ではなく、入力話者のトーンやピッチ、話し方に合わせて翻訳された発声がリアルタイムで適応します。
重要な引用
Unlike general-purpose voice models, gpt-realtime-translate is optimized for interpretation.
It can process input audio while simultaneously streaming translated audio back.
This model is unique in that it is primarily about empowering humans to be multilingual as opposed to building AI voice agents.
Keep your OpenAI API key on a server. Browser examples should use short-lived client secrets rather than exposing the API key to client code.
Realtime Translation uses dynamic voice adaptation. Instead of selecting a fixed output voice, translated speech follows the source speaker's general tone, pitch, and speaking style.
There is no response.create, assistant turn, tool call, or conversation state to manage.
影響分析・編集コメントを表示
影響分析
この発表は、AI を用いたリアルタイム通訳における「遅延」と「文脈理解」の長年の課題に対する決定的な解決策を示すものであり、ライブストリーミングや国際的なビジネス会議、カスタマーサポートなどの現場で、人間による通訳を補完・代替する新たな標準となる可能性が高い。特に、AI エージェントではなく人間の能力拡張に焦点を当てている点は、倫理的かつ実用的な AI 導入の重要な指針を示している。
編集コメント
汎用モデルの限界を打破し、通訳という特定タスクに特化した実装は、AI の実社会への浸透において非常に重要な一歩です。特に「人間の能力拡張」を掲げている点は、技術的な革新性だけでなく、人間中心設計の観点からも評価できます。
gpt-realtime-translate は、放送、ストリーミング、通話、ビデオ会話など across 多言語オーディオ体験を構築するためのライブ音声対音声翻訳モデルです。発話された入力を接受し、自動的にソース言語を検出するとともに、翻訳された音声とテキスト文字起こしの両方を返します。開発者はターゲットとなる出力言語のみを指定すればよいのです。
このモデルには、独自に優れた能力をもたらす 2 つの新機能があります:
- 汎用型音声モデルとは異なり、gpt-realtime-translate は通訳用に最適化されています。数千時間のプロフェッショナルな通訳者のオーディオでトレーニングされているため、翻訳に専念し、十分な文脈が揃うまで発話を待機するよう設計されています。これは、文構造が異なる言語間での通訳において特に重要です。
- 入力オーディオを処理しながら、同時に翻訳されたオーディオをストリーミングして返すことができます。これにより、連続した発話においても真に低遅延を実現できます。
既存の AI 音声対話とは異なり、ライブ通訳には異なる要件があるため、私たちは gpt-realtime-translate を構築しました。汎用型モデルでも翻訳を指示することは可能ですが、質問に応えたり指示に従ったりする可能性があり、必ずしも翻訳に専念するわけではありません。また、これらはターンベースの相互作用に依存しており、モデルが翻訳されたオーディオを生成している間に話者が一時停止する必要があり、流暢な通訳には適していません。
これらが、自然なライブ通訳に必要な高精度と低遅延に対する主な障壁であり、gpt-realtime-translate で解決しようとしている課題です。
このモデルは、AI 音声エージェントを構築するのではなく、人間が多言語化できるように支援することに主眼を置いている点でユニークです。音声エージェントを構築される場合は、新しい gpt-realtime-2 モデルをご利用ください。
gpt-realtime-translate の主な利用パターンとして二つ挙げられます。一つ目は放送型翻訳です。ライブストリーミング、ウェビナー、講義、決算電話会議、カンファレンスの基調講演など、一つの主要なソースからの音声を受聴者多数に翻訳して届けるケースが該当します。二つ目は対話型翻訳で、通話センター、ビデオチャット、またはその他の電話ベースのワークフローのように、複数の参加者が異なる言語を介して互いに話し合うケースです。
このクックブックではこれらのパターンを取り扱います:まずは基礎を解説し、次に任意のブラウザタブの音声から一方向ライブ翻訳を行う Web アプリケーションを構築し、Twilio を用いて電話通話への翻訳機能を追加し、LiveKit で多言語グループビデオチャットルームを作成します。最後に、本番環境でのベストプラクティス、モデルの制限事項、および評価(evals)について解説します。
既存の音声経路にライブ翻訳を追加する三つの方法を構築します:
- ブラウザタブ翻訳:getDisplayMedia() を使用してタブの音声をキャプチャし、WebRTC を介してリアルタイム翻訳サービスへ送信し、ブラウザ内で翻訳された音声と字幕を再生します。
- 電話通話の翻訳:Twilio Media Streams を使用して WebSockets を経由して電話のオーディオを受信し、リアルタイム翻訳にブリッジして、翻訳されたオーディオをもう一方の通話者に送信します。
- ビデオ通話の翻訳:リモートの LiveKit マイクトラックを購読し、各リモートスピーカーをリスナー向けに翻訳し、翻訳されたオーディオとキャプションをローカルでレンダリングします。
完全なデモアプリは、同梱のフォルダーにあります:
- ブラウザタブの翻訳
- Twilio 電話通話の翻訳
- LiveKit ビデオ通話の翻訳
必要なもの:
- OpenAI API キー。
- ブラウザおよび Twilio デモ用の Node.js。
- 電話通話デモを実行する場合は、Twilio の電話番号が必要。
- ビデオルームデモを実行する場合は、LiveKit プロジェクトまたはセルフホストされた LiveKit サーバーが必要。
OpenAI API キーはサーバー上に保管してください。ブラウザの例では、API キーをクライアントコードに公開するのではなく、短期有効なクライアントシークレットを使用する必要があります。
WebRTC および WebSocket セッションの設定、クライアントおよびサーバーイベント、設定オプションの詳細については、Live Translation docs をご覧ください。
主な違い
リアルタイム翻訳セッションは、ターゲット出力言語を中心に構成されます。セッション.audio.output.language でターゲット言語を設定します。このモデルは現在、70 以上の入力言語と 13 の出力言語をサポートしています。このモデルは、現在、カスタムプロンプトや音声選択パラメータをサポートしていません。
ソース言語の文字起こしを翻訳された音声と一緒に取得したい場合は、gpt-realtime-whisper を使用して入力文字起こしを設定してください。
リアルタイム翻訳では動的な音声適応が使用されます。固定された出力音声を事前に選択するのではなく、翻訳された音声は話者の一般的なトーン、ピッチ、話し方のスタイルに従います。複数人の参加者がいるセッションでは、新しい話者の音声が入力されるたびに翻訳された音声も変化します。
セッションライフサイクル
セッションのライフサイクルも、標準的なリアルタイム音声セッションとは異なります:
- 専用エンドポイント: /v1/realtime/translations に接続してください。
- 連続した入力音声: session.input_audio_buffer.append を使用して、フレーズ間の沈黙を含む 24 kHz PCM16 オーディオをストリーミングします。
- 連続した翻訳出力: モデルは 200 ミリ秒ごとの PCM16 チャンクとして翻訳された音声を生成し、ターゲット言語の文字起こしの差分(deltas)も同時に出力します。
- トーンライフサイクルなし: 翻訳は入力される音声ストリームそのものから開始されます。response.create やアシスタントのターン、ツール呼び出し、会話状態を管理する必要はありません。
プロトコル
ブラウザベースのアプリケーションでは WebRTC を使用してください。ブラウザはマイク、タブ、またはリモート参加者の音声をメディアトラックとして送信し、翻訳された音声をリモートオーディオトラックとして受信します。セッションの更新、文字起こしの差分、エラーについては oai-events データチャネルを使用してください。実装例については「Browser Tab Translation」セクションまたは「LiveKit」セクションを参照してください。
バックエンドのメディアパイプラインには WebSockets を使用してください。サーバーがすでに Twilio Media Streams、SIP、ブロードキャスト取り込み、またはメディアワーカーから生音声を受信している場合にこれが最適です。session.input_audio_buffer.append を使用して、発話間の沈黙を含む base64 符号化された 24 kHz PCM16 音声を送信してください。例については「Twilio との電話通話」セクションを参照してください。
まずは、片方向のライブ翻訳を行う小さなブラウザアプリから始めましょう。このアプリはブラウザタブからの音声をキャプチャし、WebRTC を介してリアルタイム翻訳セッションを開始し、モデルが出力するたびに翻訳された音声と字幕を再生します。
元の体験がすでにブラウザ内で発生している場合にこのパターンは有用です。例えば、公開会議、ライブストリーミング、カンファレンスの講演、オンラインクラス、または組み込みのライブ吹き替え機能がない動画などです。プレイヤーを再構築したり、別言語のフィードを公開したりする代わりに、アプリはページと共に動作し、リスナーにリアルタイムで翻訳された音声と字幕を提供します。

仕組み
- サーバーが短期間の有効期限を持つ翻訳クライアントシークレットを作成します。
- ブラウザは getDisplayMedia() を使用してタブの音声をキャプチャします。
- ブラウザは RTCPeerConnection を作成し、キャプチャした音声トラックを追加し、oai-events データチャネルを開きます。
- ブラウザはクライアントシークレットと共に SDP オファーをリアルタイム翻訳コールエンドポイントにポストします。
- モデルは、リモートの WebRTC オーディオトラック上で翻訳されたオーディオを返し、トランスクリプトの差分(デルタ)をデータチャネル経由で送信します。
翻訳クライアントシークレットの作成
標準的な OpenAI API キーがブラウザに到達しないように、サーバー側でクライアントシークレットを作成してください。モデルと出力言語は、クライアントシークレットリクエスト内に含まれます。
const TRANSLATION_CLIENT_SECRET_URL =
"https://api.openai.com/v1/realtime/translations/client_secrets";
app.post("/session", async (req, res) => {
const language = req.body.targetLanguage ?? "es";
const response = await fetch(TRANSLATION_CLIENT_SECRET_URL, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
session: {
model: "gpt-realtime-translate",
audio: {
input: {
transcription: { model: "gpt-realtime-whisper" },
noise_reduction: { type: "near_field" },
},
output: { language },
},
},
}),
});
res.status(response.status).json(await response.json());
});完全なブラウザデモでは、OpenAI リクエストを実行する前にターゲット言語コードを検証し、短期有効期限のクライアントシークレットのみをブラウザに返します。
タブオーディオのキャプチャ
getDisplayMedia() を使用して、ユーザーが明示的にソースタブを選択できるようにしてください。サポートされている場合、suppressLocalAudioPlayback オプションをリクエストして、リスナーが元の音声と翻訳された音声を同時に聞かないようにします。
async function captureTabAudio() {
const audio = {
echoCancellation: false,
noiseSuppression: false,
autoGainControl: false,
};
if (navigator.mediaDevices.getSupportedConstraints?.().suppressLocalAudioPlayback) {
audio.suppressLocalAudioPlayback = true;
}
const stream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio,
});
if (!stream.getAudioTracks().length) {
stream.getTracks().forEach((track) => track.stop());
throw new Error("Choose a browser tab and enable tab audio.");
}
return stream;
}
WebRTC 翻訳セッションを開く
短期有効なクライアントシークレットを使用して、ブラウザの SDP オファーをリアルタイム翻訳コールエンドポイントにポストします。音声出力はリモートトラックとして到着し、翻訳結果と入力トランスクリプトの差分(デルタ)はデータチャネルを通じて配信されます。
const sessionResponse = await fetch("/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ targetLanguage }),
});
const session = await sessionResponse.json();
const pc = new RTCPeerConnection();
const events = pc.createDataChannel("oai-events");
for (const track of sourceStream.getAudioTracks()) {
pc.addTrack(track, sourceStream);
}
pc.ontrack = ({ streams }) => {
translatedAudio.srcObject = streams[0];
};
events.onmessage = ({ data }) => {
const event = JSON.parse(data);
if (event.type === "session.output_transcript.delta") {
translatedSubtitles.textContent += event.delta;
}
if (event.type === "session.input_transcript.delta") {
sourceTranscript.textContent += event.delta;
}
};
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const sdpResponse = await fetch(
"https://api.openai.com/v1/realtime/translations/calls",
{
method: "POST",
headers: {
Authorization: Bearer ${session.client_secret},
"Content-Type": "application/sdp",
},
body: offer.sdp,
}
);
await pc.setRemoteDescription({
type: "answer",
sdp: await sdpResponse.text(),
});
完全なデモを実行するには:
cd examples/voice_solutions/realtime_translation_guide/browser-translation-demo
npm install
npm run dev
次に、ローカル URL を開き、音声を含むタブを選択し、対象言語を選び、翻訳を開始してください。
次に、gpt-realtime-translate を Twilio の通話パスに組み込んでみましょう。会話型翻訳は、各参加者が個別のオーディオストリームを持つ場合に最も効果的に機能します。Twilio Media Streams は、電話用オーディオのためにバックエンドにサーバーサイド WebSocket を提供し、サーバーがフォーマット境界を処理します。具体的には、発信者のオーディオを受信し、リアルタイム翻訳用に形式変換した後、翻訳されたオーディオを Twilio メディアメッセージに変換して戻す処理を行います。

仕組みについて
- 発信者が参加し、希望する出力言語を伝えます。
- Twilio はその発信者のオーディオをバックエンドにストリーミングします。
- バックエンドは、Twilio のオーディオをリアルタイム通訳が期待するオーディオ形式に変換します。
- 各通訳方向に対して、バックエンドはリスナーの目標言語でリアルタイム通訳セッションを開きます。
- OpenAI から翻訳されたオーディオが戻ってくると、バックエンドはそれを Twilio のメディアメッセージとして再度変換します。
- Twilio は、その翻訳されたオーディオをもう一方の参加者に再生します。
2 人通話の場合、通常は A→B と B→A の 2 つの通訳セッションが必要です。より大規模な通話では、すべての参加者を一つの共有ストリームに混ぜるのではなく、誰がどのソーススピーカーの音をどの言語で聞く必要があるかという要件に基づいて通訳セッションを作成してください。
**
プロダクションノート:** gpt-realtime-translate は、すでにリスナーが選択した出力言語で既に存在するオーディオを翻訳しない可能性があります。このデモでは元の Twilio オーディオを他参加者に直接転送していないため、同じ言語での発話が無音になる場合があります。本番の電話ブリッジでは、元のオーディオのパススルーまたはミキシング機能を追加する必要があります。このデモは通話者を 1 対 1 でペアリングしており、追加の通話者は別の通話者が現れるまで待機し、別々のペアを形成します。
Twilio ウェブフックの設定
サーバー用のパブリックエンドポイントを作成し、Twilio 電話番号の Voice webhook を設定して、着信通話をアプリケーションにルーティングしてください。ローカル開発環境では、トンネルを使用してサーバーを公開するか、ポート 443 で Twilio からアクセス可能な場所にデプロイしてください。同じホストで HTTP ウェブフックルートと WebSocket Media Stream ルートの両方を提供する必要があります。
通話者に目標言語を尋ねる
通話者がダイヤルすると、翻訳に希望する言語を尋ねる TwiML を返します。
<Response>
<Gather input="speech" timeout="10" speechTimeout="auto" action="/choose-language" method="POST">
<Say>What language do you want to hear?</Say>
</Gather>
<Redirect method="POST">/choose-language</Redirect>
</Response>
Twilio Media Stream の開始
通話者がサポートされている言語を選択した後、双方向の Media Stream を返します。選択された言語をカスタムパラメータとして渡して、WebSocket ハンドラーが通話者の希望する出力言語で登録できるようにしてください。
<Response>
<Say>You chose Spanish. Wait for the other caller, then begin speaking.</Say>
<Connect>
<Stream url="wss://YOUR_PUBLIC_HOST/media-stream">
<Parameter name="callSid" value="CALL_SID" />
<Parameter name="language" value="es" />
<Parameter name="languageLabel" value="Spanish" />
</Stream>
</Connect>
</Response>
サーバーサイドでの翻訳セッションの開始
この統合はバックエンド上で動作するため、ブラウザクライアントのシークレットは不要です。OpenAI API キーを使用してサーバーから直接 Translation WebSocket を開き、URL でモデルを選択してください。
import WebSocket from "ws";
function openTranslationSession({ targetLanguage }) {
const ws = new WebSocket(
"wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate",
{
headers: {
Authorization: Bearer ${process.env.OPENAI_API_KEY},
},
}
);
ws.on("open", () => {
ws.send(JSON.stringify({
type: "session.update",
session: {
audio: {
input: {
transcription: { model: "gpt-realtime-whisper" },
noise_reduction: { type: "near_field" },
},
output: { language: targetLanguage },
},
},
}));
});
return ws;
}
Twilio のオーディオをリアルタイム翻訳にブリッジする
Twilio は 8 kHz の base64 オーディオ/x-mulaw を送信します。一方、リアルタイム翻訳は 24 kHz の base64 little-endian PCM16 を期待しているため、ブリッジでは u-law をデコードし、24 kHz にリサンプリングしてオーディオバッファに追加します。翻訳セッションはターンベースではなくレスポンス作成を待たないため、沈黙を含むオーディオを継続的に送信し続けてください。
function sendTwilioAudioToTranslation(realtimeWs, twilioMessage) {
if (twilioMessage.event !== "media") return;
const realtimeAudio = twilioMediaToRealtimeAudio(
twilioMessage.media.payload
);
realtimeWs.send(JSON.stringify({
type: "session.input_audio_buffer.append",
audio: realtimeAudio,
}));
}
Bridge translated audio back to Twilio
Realtime Translation は、セッション.output_audio.delta 内で翻訳されたオーディオを base64 24 kHz PCM16 として出力します。Twilio に送信する前に、これを 8 kHz u-law に変換し、Twilio のメディアメッセージでラップする必要があります。
function sendTranslationToTwilio(twilioWs, streamSid, realtimeEvent) {
if (realtimeEvent.type !== "session.output_audio.delta") return;
const twilioPayload = realtimeAudioToTwilioMedia(realtimeEvent.delta);
twilioWs.send(JSON.stringify({
event: "media",
streamSid,
media: {
payload: twilioPayload,
},
}));
}
Pair callers and create one session per direction
2 人の通話者が待機状態になったら、ペアリングして双方向それぞれに 1 つずつ Realtime Translation セッションを開きます。各セッションの出力言語は、話者ではなく聴取者が選択した言語です。
function pairCallers(a, b) {
const aToB = openTranslationSession({ targetLanguage: b.language });
const bToA = openTranslationSession({ targetLanguage: a.language });
a.onAudio = (message) => sendTwilioAudioToTranslation(aToB, message);
b.onAudio = (message) => sendTwilioAudioToTranslation(bToA, message);
aToB.on("message", (data) => {
sendTranslationToTwilio(b.ws, b.streamSid, JSON.parse(data));
});
bToA.on("message", (data) => {
sendTranslationToTwilio(a.ws, a.streamSid, JSON.parse(data));
});
}
完全なデモを実行する:
cd examples/voice_solutions/realtime_translation_guide/twilio-translation-demo
npm install
npm run dev
twilio の電話番号の音声 webhook を設定し、POST リクエストを https://YOUR_PUBLIC_HOST/incoming-call へ送信するようにしてください。
最後に、gpt-realtime-translate をグループビデオ会議に統合しましょう。すでにビデオルームが存在しており、会話にライブ通訳を追加したい場合にこのパターンを使用します。LiveKit は、ルーム、参加者、マイクトラック、カメラトラック、デバイス選択、再接続動作を処理します。リアルタイム翻訳は、各リスナーが受信するオーディオトラックに付随する通訳レイヤーとして機能します。

仕組みについて
- 参加者がマイクとカメラのトラックを LiveKit ルームに公開します。
- リスナーは、LiveKit を介してリモート参加者のマイクトラックを購読します。
- リスナーのブラウザは、そのリモートの MediaStreamTrack をリアルタイム翻訳のサイドカーへ渡します。
- サイドカーは、リスナーが選択した出力言語に対して WebRTC リアルタイム翻訳セッションを開始します。
- リアルタイム翻訳は、翻訳されたオーディオをリモートオーディオトラックとして返すとともに、oai-events データチャネルを通じてトランスクリプトの差分(デルタ)を送信します。
- リスナーのブラウザは、翻訳されたオーディオを再生し、キャプションを描画するとともに、元の LiveKit オーディオをローカルで音量を下げるかミックス処理を行います。
このデモでは、翻訳されたオーディオはリスナーのブラウザ内にのみ保持され、LiveKit ルームに公開されることはありません。
リモート参加者のトラックに翻訳を添付する
リスナーが LiveKit ルームに参加したら、各リモート参加者のマイクトラックを見つけ、その基盤となる MediaStreamTrack を翻訳ヘルパーに渡します。
function getParticipantAudioMediaStreamTrack(participant: Participant) {
const publication = participant.getTrackPublication(Track.Source.Microphone);
return publication?.audioTrack?.mediaStreamTrack ?? null;
}
リモートスピーカーごとに 1 つの翻訳サイドカーを作成する
翻訳された参加者のタイルは、元の LiveKit メディアパスをそのまま維持しつつ、その横に翻訳出力を追加できます。タイルは依然として参加者のビデオとオリジナルオーディオを描画しますが、翻訳が有効になっている場合、参加者のマイクトラックに対してリアルタイム翻訳サイドカーを開始します。
function TranslatedParticipantTile({
participant,
language,
translationEnabled,
}: {
participant: Participant;
language: string;
translationEnabled: boolean;
}) {
const sourceTrack = getParticipantAudioMediaStreamTrack(participant);
const translation = useRemoteTranslation({
enabled: translationEnabled && Boolean(sourceTrack),
sourceTrack,
language,
});
return (
<MeetingTile
participant={participant}
sourceVolume={translation.hasOutputAudio ? 0.15 : 1}
translatedSubtitle={translation.translatedSubtitle}
sourceSubtitle={translation.sourceSubtitle}
/>
);
}
Open the translation sidecar
このヘルパーは、サーバー上で短寿命のリアルタイム翻訳クライアントシークレットを作成し、ブラウザから WebRTC サイドカーを開き、リモートの LiveKit マイクメディアストリームトラックを RTCPeerConnection にアタッチし、返されたリモートトラックから翻訳されたオーディオを再生します。
async function startTranslationSidecar({ sourceTrack, clientSecret }) {
const pc = new RTCPeerConnection();
pc.addTrack(sourceTrack, new MediaStream([sourceTrack]));
const translatedAudio = new Audio();
translatedAudio.autoplay = true;
pc.ontrack = ({ streams }) => {
translatedAudio.srcObject = streams[0];
};
const events = pc.createDataChannel("oai-events");
events.onmessage = ({ data }) => {
const event = JSON.parse(data);
if (event.type === "session.output_transcript.delta") {
subtitles.textContent += event.delta;
}
};
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const response = await fetch(
"https://api.openai.com/v1/realtime/translations/calls",
{
method: "POST",
headers: {
Authorization: Bearer ${clientSecret},
"Content-Type": "application/sdp",
},
body: offer.sdp,
}
);
await pc.setRemoteDescription({
type: "answer",
sdp: await response.text(),
});
return pc;
}
Plan session fanout by listener language
For a two-person room, each participant translates the other participant's microphone track into their own preferred language. For a group room, the number of active translation sessions depends on the number of active remote speakers and the number of distinct target languages listeners need.
Browser-side translation is the simplest architecture: each listener creates translation sidecars for the remote speakers they want translated. For larger rooms in production, move the work into a LiveKit worker or server-side participant that subscribes to room audio, translates each source speaker once per target language, and republishes translated tracks back into the room.
Run the complete demo:
cd examples/voice_solutions/realtime_translation_guide/livekit-translation-demo
pnpm install
pnpm dev
Use the same meeting code in two browser windows to join the same LiveKit room. Enable translation in one window, choose the language that listener wants to hear, and speak from the other window.
Before launching Realtime Translation, test the full experience with the same audio, languages, network conditions, and user flows you expect in production. Translation quality is only one part of the experience: latency, speaker routing, captions, reconnect behavior, and audio controls all impact production readiness.
メディアパスに基づいてアーキテクチャを選択する
マイクロフォン、タブ音声、または LiveKit パーティシパントトラックなどのクライアントサイドメディアにはブラウザの WebRTC を使用し、電話回線、ブロードキャストイングエスト、またはバックエンドのメディアパイプラインにはサーバーサイドの WebSocket を使用してください。
マルチパーティ通話では、翻訳をソーススピーカーとターゲット言語に基づいてルーティングします。可能であればスピーカートラックは分離したままにし、同じターゲット言語を共有するリスナーに対して翻訳された出力をファンアウト(分配)します。すべてのスピーカーを 1 つのストリームにミックスすると、キャプション、スピーカーの識別、および重なる音声の処理が困難になります。
用語と固有名詞は直接テストする
モデルは現在、カスタムプロンプト、グロッサリー、または発音ガイドをサポートしていません。特定の語彙、固有名詞、法的・医療用語、またはその他のドメイン固有言語に依存するユースケースがある場合は、それらの用語を直接テストしてください。翻訳中にモデルが誤った名前やエンティティを置き換えることがあるため、これらのケースはローンチ評価セットに含まれていなければなりません。
混合言語の発話に対応する
リアルタイム翻訳では、選択された出力言語ですでに発話されている場合は翻訳しないように努めています。例えば、出力言語がスペイン語で、スピーカーがスペイン語に切り替えた場合、モデルはそのセグメントに対して翻訳されたオーディオを生成しない可能性があります。
これは混合言語の発話において重要です。スペイン語と英語が混ざった「スパンギッシュ」をドイツ語に翻訳する場合は、英語部分もスペイン語部分も両方をドイツ語に変換する必要があるので、期待通りに動作するはずです。一方、スパンギッシュを英語に翻訳する場合、モデルはスペイン語部分を翻訳しつつ、英語部分はそのまま保持して沈黙するため、全体的にぎこちなく感じられることがあります。
この挙動は通常は有益ですが、アプリが元の音声を完全にミュートしてしまうと混乱を招く可能性があります。話者が複数の言語を混ぜて話すことを想定している場合は、元の音声も利用可能にしておくべきです。良いパターンとしては、翻訳された音声が再生されている間に元の音声を完全に消すのではなく、音量を下げて(ダッキング)再生し、必要に応じてソース言語の字幕や、元音声と翻訳音声を切り替えるコントロール機能を提供することです。
サポートされる言語
リアルタイム翻訳では現在、13 のターゲット出力言語をサポートしています:スペイン語、ポルトガル語、フランス語、日本語、ロシア語、中国語、ドイツ語、韓国語、ヒンディー語、インドネシア語、ベトナム語、イタリア語、英語。
現在、このモデルは70以上の入力言語をサポートしています。アラビア語、アフリカーンス語、アゼルバイジャン語、ベラルーシ語、ベンガル語、ボスニア語、ブルガリア語、カタルーニャ語、中国語、クロアチア語、チェコ語、デンマーク語、オランダ語、ゾンカ語、英語、エスペラント語、エストニア語、バスク語、ペルシャ語/ファールス語、フィンランド語、フィリピン語、フランス語、ガリシア語、ドイツ語、ギリシャ語、グジャラート語、ハイチ・クレオール語、ハワイ語、ヘブライ語、ヒンディー語、ハンガリー語、アルメニア語、インドネシア語、イタリア語、日本語、ジャワ語、グルジア語、カザフ語、韓国語、クルド語、ラテン語、ラトビア語、リトアニア語、マケドニア語、マレー語、マラヤーラム語、マオリ語、モンゴル語、ビルマ語/ミャンマー語、ネパール語、ノルウェー語、ニーノシュク語、ポーランド語、ポルトガル語、パンジャブ語、ルーマニア語、ロシア語、セルビア語、ショナ語、スロバキア語、スロベニア語、アルバニア語、スペイン語、スワヒリ語、スウェーデン語、タガログ語、テルグ語、タイ語、トルコ語、ウクライナ語、ウズベク語、ベトナム語、ウェールズ語、ヨルバ語からの動的な検出と翻訳が可能です。
意味とレイテンシを別々に評価する
評価においては、各ランごとにソースオーディオ、生成された翻訳オーディオ、生成された文字起こし、および参照テキストをセットとして保持してください。後で以下の3つの質問に答えられるようにする必要があります:
- モデルは何を聞いたのか?
- 何と言ったのか?
- 何を言うべきだったのか?
可能な限り最良の人間による参照を使用してください。具体的には、人間が編集した字幕、専門家の通訳者による文字起こし、バイリンガルスピーカーがレビューした通話記録、またはソース素材に対する人間の吹き替えなどです。自動キャプションや文字起こしは迅速なスモークテストには有用ですが、真実の源泉としては弱いです。
参照データにタイムスタンプが含まれている場合は、それを利用してください。時間同期された字幕や書き起こしを使用すれば、翻訳の質だけでなく、翻訳された音声とキャプションがいつ届いたかも評価できます。
訳文は正確な語句ではなく意味で評価してください。良い翻訳では異なる単語が使われることもあるため、重要な事実、ニュアンス、エンティティ(実体)、数値、トーンが保持されているかを評価しましょう。平均スコアだけでなく、誤りの分布全体を追跡することが重要です。なぜなら、ライブ翻訳においては少数の重大なエラーが大きな影響を及ぼす可能性があるからです。
BLEU などの従来のテキスト指標は迅速な比較に役立ちますが、意味的類似性を捉えられないため、音声から音声への品質に対する弱い代理指標となります。
遅延(レイテンシ)と質は別々に測定してください。ソース音声から翻訳された音声へ、およびソース音声から表示されるキャプションまでの時間を追跡します。遅延を計算する際は、意味的に適切に同期されているセグメントのみを使用してください。そうでないと、誤ったマッチングがタイミングデータを誤解させる恐れがあります。
最後に、低スコアの例を手動でレビューしてください。元のソース、生成された翻訳、参照セグメントを並べて聴取します。ここで初めて、集計スコアでは見逃される問題、特に固有名詞、数値、部分的な翻訳、トーン、モデルが内容をスキップまたは遅延させたケースなどを発見できます。
リアルタイム評価の詳細については、Realtime eval guide を参照してください。
リアルタイム翻訳は、多言語ユーザー向けアプリケーションを構築する意味そのものを変えます。これにより、ライブ通訳が製品体験のネイティブな一部となり、多言語での会話が翻訳ツールの利用という感覚から、リアルタイムで互いに理解し合う自然な行為へと変わります。専用翻訳セッションを通じて、音声はブラウザ、電話、ビデオルームを体験の一部として流れるようになります。
言語をより小さな障壁にすることで、これらのアプリケーションは、より多くの人々が参加し、協力し、つながることを可能にします。
原文を表示
gpt-realtime-translate is a live speech-to-speech translation model for building multilingual audio experiences across broadcasts, streams, calls, and video conversations. It accepts spoken input, automatically detects the source language, and returns translated speech plus text transcripts. Developers only need to specify the target output language.
This model has two new features that make it uniquely capable:
- Unlike general-purpose voice models, gpt-realtime-translate is optimized for interpretation. It was trained on thousands of hours of professional interpreter audio, which helps it remain translation-only and wait for enough context before producing speech. This is especially important across languages with different sentence structures.
- It can process input audio while simultaneously streaming translated audio back. This allows for truly low latency over continuous speech.
We built gpt-realtime-translate because live interpretation has different requirements than existing AI voice interactions. General-purpose models can be prompted to translate, but they may still answer questions or follow instructions rather than translate them. They also rely on turn-based interaction, requiring speakers to pause while the model generates the translated audio, which does not work well for fluent interpretation.
These have been the main blockers to the high accuracy and low latency required for natural live interpretation, and what we’re solving for with gpt-realtime-translate.
This model is unique in that it is primarily about empowering humans to be multilingual as opposed to building AI voice agents. If you’re building voice agents, use the new gpt-realtime-2 model.
We see two main patterns for gpt-realtime-translate. The first is broadcast-style translation: livestreams, webinars, lectures, earnings calls, conference keynotes, and other cases where many listeners need translated audio from one primary source to another. The second is conversational translation, where two or more participants speak with each other across languages: call centers, video chat, or other phone-based workflows.
This cookbook focuses on these patterns: We’ll start by covering the basics, then build a web app for one-way live translation from any browser tab audio, use Twilio to build translation into phone calls, and create a multilingual group video chat room with LiveKit. Lastly, we’ll cover production best practices, model limitations, and evals.
You will build three ways to add live translation to existing audio paths:
- Browser tab translation: Capture tab audio with getDisplayMedia(), send it to Realtime Translation over WebRTC, and play translated speech plus captions in the browser.
- Phone-call translation: Use Twilio Media Streams to receive phone audio over WebSockets, bridge it into Realtime Translation, and send translated audio back to the other caller.
- Video-call translation: Subscribe to remote LiveKit microphone tracks, translate each remote speaker for the listener, and render translated audio and captions locally.
The complete demo apps live in the accompanying folders:
- Browser tab translation
- Twilio phone translation
- LiveKit video translation
You need:
- An OpenAI API key.
- Node.js for the browser and Twilio demos.
- A Twilio phone number if you want to run the phone-call demo.
- A LiveKit project or self-hosted LiveKit server if you want to run the video-room demo.
Keep your OpenAI API key on a server. Browser examples should use short-lived client secrets rather than exposing the API key to client code.
See our Live Translation docs for full details on setting up WebRTC and WebSocket sessions, client and server events, and configuration options.
Key differences
Realtime Translation sessions are configured around the target output language. Set the target language with session.audio.output.language. The model currently supports over 70 input languages and 13 output languages. This model does not currently support custom prompting or voice selection parameters.
If you want source-language transcripts alongside translated audio, configure input transcription with gpt-realtime-whisper.
Realtime Translation uses dynamic voice adaptation. Instead of selecting a fixed output voice, translated speech follows the source speaker’s general tone, pitch, and speaking style. In a multi-speaker session, the translated voice will change as new speaker audio comes in.
Session lifecycle
The session lifecycle is also different from a standard Realtime voice session:
- Dedicated endpoint: Connect to /v1/realtime/translations.
- Continuous audio in: Stream 24 kHz PCM16 audio with session.input_audio_buffer.append, including silence between phrases.
- Continuous translation out: The model emits translated audio in 200 ms PCM16 chunks, plus target-language transcript deltas.
- No turn lifecycle: Translation starts from the incoming audio stream itself. There is no response.create, assistant turn, tool call, or conversation state to manage.
Protocols
For browser-based apps, use WebRTC. The browser sends microphone, tab, or remote participant audio as a media track and receives translated speech as a remote audio track. Use the oai-events data channel for session updates, transcript deltas, and errors. See the Browser Tab Translation or LiveKit sections for implementation examples.
For backend media pipelines, use WebSockets. This is the right fit when your server already receives raw audio, such as Twilio Media Streams, SIP, broadcast ingest, or a media worker. Send base64 24 kHz PCM16 audio with session.input_audio_buffer.append, including silence between spoken phrases. See the Phone Calls with Twilio section for an example.
Let’s start with a small browser app for one-way live translation. The app captures audio from a browser tab, starts a Realtime Translation session over WebRTC, and plays translated speech with subtitles as the model emits them.
This pattern is useful when the original experience is already happening in the browser: a public meeting, livestream, conference talk, online class, or video without built-in live dubbing. Instead of rebuilding the player or publishing separate language feeds, the app sits alongside the page and gives listeners translated audio and subtitles in real time.

How it works
- Your server creates a short-lived translation client secret.
- The browser captures tab audio with getDisplayMedia().
- The browser creates an RTCPeerConnection, adds the captured audio track, and opens an oai-events data channel.
- The browser posts its SDP offer to the Realtime Translation call endpoint with the client secret.
- The model returns translated audio on the remote WebRTC audio track and sends transcript deltas on the data channel.
Create the translation client secret
Create the client secret on your server so your standard OpenAI API key never reaches the browser. The model and output language live in the client-secret request.
const TRANSLATION_CLIENT_SECRET_URL =
"https://api.openai.com/v1/realtime/translations/client_secrets";
app.post("/session", async (req, res) => {
const language = req.body.targetLanguage ?? "es";
const response = await fetch(TRANSLATION_CLIENT_SECRET_URL, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
session: {
model: "gpt-realtime-translate",
audio: {
input: {
transcription: { model: "gpt-realtime-whisper" },
noise_reduction: { type: "near_field" },
},
output: { language },
},
},
}),
});
res.status(response.status).json(await response.json());
});The complete browser demo validates target language codes before making the OpenAI request and returns only the short-lived client secret to the browser.
Capture tab audio
Use getDisplayMedia() so the user explicitly picks the source tab. When supported, request suppressLocalAudioPlayback so the listener does not hear the original and translated audio at the same time.
async function captureTabAudio() {
const audio = {
echoCancellation: false,
noiseSuppression: false,
autoGainControl: false,
};
if (navigator.mediaDevices.getSupportedConstraints?.().suppressLocalAudioPlayback) {
audio.suppressLocalAudioPlayback = true;
}
const stream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio,
});
if (!stream.getAudioTracks().length) {
stream.getTracks().forEach((track) => track.stop());
throw new Error("Choose a browser tab and enable tab audio.");
}
return stream;
}Open the WebRTC translation session
Use the short-lived client secret to post the browser’s SDP offer to the Realtime Translation call endpoint. Audio output arrives as a remote track. Translation and input transcript deltas arrive on the data channel.
const sessionResponse = await fetch("/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ targetLanguage }),
});
const session = await sessionResponse.json();
const pc = new RTCPeerConnection();
const events = pc.createDataChannel("oai-events");
for (const track of sourceStream.getAudioTracks()) {
pc.addTrack(track, sourceStream);
}
pc.ontrack = ({ streams }) => {
translatedAudio.srcObject = streams[0];
};
events.onmessage = ({ data }) => {
const event = JSON.parse(data);
if (event.type === "session.output_transcript.delta") {
translatedSubtitles.textContent += event.delta;
}
if (event.type === "session.input_transcript.delta") {
sourceTranscript.textContent += event.delta;
}
};
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const sdpResponse = await fetch(
"https://api.openai.com/v1/realtime/translations/calls",
{
method: "POST",
headers: {
Authorization: `Bearer ${session.client_secret}`,
"Content-Type": "application/sdp",
},
body: offer.sdp,
}
);
await pc.setRemoteDescription({
type: "answer",
sdp: await sdpResponse.text(),
});Run the complete demo:
cd examples/voice_solutions/realtime_translation_guide/browser-translation-demo
npm install
npm run devThen open the local URL, choose a tab with audio, pick the target language, and start translation.
Next, let’s put gpt-realtime-translate into a Twilio call path. Conversational translation works best when each participant has a distinct audio stream. Twilio Media Streams gives your backend a server-side WebSocket for phone audio, and your server handles the format boundary: receiving caller audio, converting it for Realtime Translation, then converting translated audio back into Twilio media messages.

How it works
- A caller joins and says their preferred output language.
- Twilio streams that caller’s audio to your backend.
- Your backend converts Twilio audio into the audio format expected by Realtime Translation.
- For each translation direction, your backend opens a Realtime Translation session with the listener’s target language.
- As translated audio comes back from OpenAI, your backend converts it back into Twilio media messages.
- Twilio plays the translated audio to the other participant.
For a two-person call, this usually means two translation sessions: A-to-B and B-to-A. For larger calls, create translation sessions based on who needs to hear which source speaker in which language rather than mixing all participants into one shared stream.
Production note: gpt-realtime-translate may not translate audio that is already in the listener’s selected output language. Because this demo does not pass original Twilio audio through to the other participant, same-language speech may lead to silence. Production phone bridges should add original-audio passthrough or mixing. This demo pairs callers one-to-one; additional callers wait for another caller and form a separate pair.
Configure the Twilio webhook
Create a public endpoint for your server, then set the Twilio phone number’s Voice webhook to route inbound calls to your application. For local development, expose the server with a tunnel or deploy it somewhere Twilio can reach over port 443. The same host must serve the HTTP webhook routes and the WebSocket Media Stream route.
Ask the caller for a target language
When a caller dials in, return TwiML that asks which language they want for the translation.
<Response>
<Gather input="speech" timeout="10" speechTimeout="auto" action="/choose-language" method="POST">
<Say>What language do you want to hear?</Say>
</Gather>
<Redirect method="POST">/choose-language</Redirect>
</Response>Start the Twilio Media Stream
After the caller chooses a supported language, return a bidirectional Media Stream. Pass the selected language as a custom parameter so the WebSocket handler can register the caller with their preferred output language.
<Response>
<Say>You chose Spanish. Wait for the other caller, then begin speaking.</Say>
<Connect>
<Stream url="wss://YOUR_PUBLIC_HOST/media-stream">
<Parameter name="callSid" value="CALL_SID" />
<Parameter name="language" value="es" />
<Parameter name="languageLabel" value="Spanish" />
</Stream>
</Connect>
</Response>Open a server-side translation session
Because this integration runs on your backend, you do not need browser client secrets. Open the Translation WebSocket directly from the server with your OpenAI API key and select the model in the URL.
import WebSocket from "ws";
function openTranslationSession({ targetLanguage }) {
const ws = new WebSocket(
"wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate",
{
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
},
}
);
ws.on("open", () => {
ws.send(JSON.stringify({
type: "session.update",
session: {
audio: {
input: {
transcription: { model: "gpt-realtime-whisper" },
noise_reduction: { type: "near_field" },
},
output: { language: targetLanguage },
},
},
}));
});
return ws;
}Bridge Twilio audio into Realtime Translation
Twilio sends base64 audio/x-mulaw at 8 kHz. Realtime Translation expects base64 little-endian PCM16 at 24 kHz, so the bridge decodes u-law, resamples to 24 kHz, and appends the audio buffer. Keep sending audio continuously, including silence, since translation sessions are not turn-based and do not wait for response.create.
function sendTwilioAudioToTranslation(realtimeWs, twilioMessage) {
if (twilioMessage.event !== "media") return;
const realtimeAudio = twilioMediaToRealtimeAudio(
twilioMessage.media.payload
);
realtimeWs.send(JSON.stringify({
type: "session.input_audio_buffer.append",
audio: realtimeAudio,
}));
}Bridge translated audio back to Twilio
Realtime Translation emits translated audio as base64 24 kHz PCM16 in session.output_audio.delta. Before sending it to Twilio, convert it back to 8 kHz u-law and wrap it in a Twilio media message.
function sendTranslationToTwilio(twilioWs, streamSid, realtimeEvent) {
if (realtimeEvent.type !== "session.output_audio.delta") return;
const twilioPayload = realtimeAudioToTwilioMedia(realtimeEvent.delta);
twilioWs.send(JSON.stringify({
event: "media",
streamSid,
media: {
payload: twilioPayload,
},
}));
}Pair callers and create one session per direction
Once two callers are waiting, pair them and open two Realtime Translation sessions. Each session’s output language is the language selected by the listener, not the speaker.
function pairCallers(a, b) {
const aToB = openTranslationSession({ targetLanguage: b.language });
const bToA = openTranslationSession({ targetLanguage: a.language });
a.onAudio = (message) => sendTwilioAudioToTranslation(aToB, message);
b.onAudio = (message) => sendTwilioAudioToTranslation(bToA, message);
aToB.on("message", (data) => {
sendTranslationToTwilio(b.ws, b.streamSid, JSON.parse(data));
});
bToA.on("message", (data) => {
sendTranslationToTwilio(a.ws, a.streamSid, JSON.parse(data));
});
}Run the complete demo:
cd examples/voice_solutions/realtime_translation_guide/twilio-translation-demo
npm install
npm run devConfigure your Twilio phone number’s Voice webhook to call POST https://YOUR_PUBLIC_HOST/incoming-call.
Finally, let’s integrate gpt-realtime-translate into a group video conference. Use this pattern when you already have a video room and want to add live interpretation to the conversation. LiveKit handles rooms, participants, microphone tracks, camera tracks, device selection, and reconnect behavior. Realtime Translation acts as an interpreter layer attached to the audio tracks that each listener receives.

How it works
- A participant publishes microphone and camera tracks into the LiveKit room.
- A listener subscribes to the remote participant’s microphone track through LiveKit.
- The listener’s browser passes that remote MediaStreamTrack into a Realtime Translation sidecar.
- The sidecar opens a WebRTC Realtime Translation session for the listener’s selected output language.
- Realtime Translation returns translated audio as a remote audio track and transcript deltas over the oai-events data channel.
- The listener’s browser plays the translated audio, renders captions, and ducks or mixes the original LiveKit audio locally.
In this demo, translated audio stays local to the listener’s browser; it is not published back into the LiveKit room.
Attach translation to a remote participant track
Once the listener joins a LiveKit room, find each remote participant’s microphone track and pass the underlying MediaStreamTrack into a translation helper.
function getParticipantAudioMediaStreamTrack(participant: Participant) {
const publication = participant.getTrackPublication(Track.Source.Microphone);
return publication?.audioTrack?.mediaStreamTrack ?? null;
}Create one translation sidecar per remote speaker
A translated participant tile can keep the original LiveKit media path intact while adding translation output beside it. The tile still renders the participant’s video and original audio, but it also starts a Realtime Translation sidecar for the participant’s microphone track when translation is enabled.
function TranslatedParticipantTile({
participant,
language,
translationEnabled,
}: {
participant: Participant;
language: string;
translationEnabled: boolean;
}) {
const sourceTrack = getParticipantAudioMediaStreamTrack(participant);
const translation = useRemoteTranslation({
enabled: translationEnabled && Boolean(sourceTrack),
sourceTrack,
language,
});
return (
<MeetingTile
participant={participant}
sourceVolume={translation.hasOutputAudio ? 0.15 : 1}
translatedSubtitle={translation.translatedSubtitle}
sourceSubtitle={translation.sourceSubtitle}
/>
);
}Open the translation sidecar
The helper creates a short-lived Realtime Translation client secret on your server, opens a WebRTC sidecar from the browser, attaches the remote LiveKit microphone MediaStreamTrack to an RTCPeerConnection, and plays translated audio from the returned remote track.
async function startTranslationSidecar({ sourceTrack, clientSecret }) {
const pc = new RTCPeerConnection();
pc.addTrack(sourceTrack, new MediaStream([sourceTrack]));
const translatedAudio = new Audio();
translatedAudio.autoplay = true;
pc.ontrack = ({ streams }) => {
translatedAudio.srcObject = streams[0];
};
const events = pc.createDataChannel("oai-events");
events.onmessage = ({ data }) => {
const event = JSON.parse(data);
if (event.type === "session.output_transcript.delta") {
subtitles.textContent += event.delta;
}
};
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const response = await fetch(
"https://api.openai.com/v1/realtime/translations/calls",
{
method: "POST",
headers: {
Authorization: `Bearer ${clientSecret}`,
"Content-Type": "application/sdp",
},
body: offer.sdp,
}
);
await pc.setRemoteDescription({
type: "answer",
sdp: await response.text(),
});
return pc;
}Plan session fanout by listener language
For a two-person room, each participant translates the other participant’s microphone track into their own preferred language. For a group room, the number of active translation sessions depends on the number of active remote speakers and the number of distinct target languages listeners need.
Browser-side translation is the simplest architecture: each listener creates translation sidecars for the remote speakers they want translated. For larger rooms in production, move the work into a LiveKit worker or server-side participant that subscribes to room audio, translates each source speaker once per target language, and republishes translated tracks back into the room.
Run the complete demo:
cd examples/voice_solutions/realtime_translation_guide/livekit-translation-demo
pnpm install
pnpm devUse the same meeting code in two browser windows to join the same LiveKit room. Enable translation in one window, choose the language that listener wants to hear, and speak from the other window.
Before launching Realtime Translation, test the full experience with the same audio, languages, network conditions, and user flows you expect in production. Translation quality is only one part of the experience: latency, speaker routing, captions, reconnect behavior, and audio controls all impact production readiness.
Choose the architecture based on the media path
Use browser WebRTC for client-side media like microphones, tab audio, or LiveKit participant tracks. Use server-side WebSockets for telephony, broadcast ingest, or backend media pipelines.
For multi-party calls, route translation by source speaker and target language. Keep speaker tracks separate when possible, then fan out the translated output to listeners who share the same target language. Mixing all speakers into one stream makes captions, speaker identity, and overlapping speech harder to handle.
Test terminology and names directly
The model does not currently support custom prompts, glossaries, or pronunciation guides. If your use case depends on specific vocabulary, names, legal or medical terms, or other domain language, test those terms directly. The model can sometimes substitute incorrect names or entities while translating, so include these cases in your launch evaluation set.
Account for mixed-language speech
Realtime Translation tries not to translate speech that is already in the selected output language. For example, if the output language is Spanish and the speaker switches into Spanish, the model may not produce translated audio for that segment.
This matters for mixed-language speech. Spanglish to German should work as expected because both the English and Spanish parts need to be translated into German. Spanglish to English can feel choppier because the model may translate the Spanish parts but stay quiet during the English parts.
This behavior is usually helpful, but it can be confusing if your app fully mutes the original audio. If you expect speakers to mix languages, keep the original audio available. A good pattern is to duck the original audio while translated audio is playing rather than fully muting it. You can also offer source-language captions or an original/translated audio mix control.
Supported languages
Realtime Translation currently supports 13 target output languages: Spanish, Portuguese, French, Japanese, Russian, Chinese, German, Korean, Hindi, Indonesian, Vietnamese, Italian, and English.
The model currently supports over 70 input languages. It can dynamically detect and translate from Arabic, Afrikaans, Azerbaijani, Belarusian, Bengali, Bosnian, Bulgarian, Catalan, Chinese, Croatian, Czech, Danish, Dutch, Dzongkha, English, Esperanto, Estonian, Basque, Persian / Farsi, Finnish, Filipino, French, Galician, German, Greek, Gujarati, Haitian Creole, Hawaiian, Hebrew, Hindi, Hungarian, Armenian, Indonesian, Italian, Japanese, Javanese, Georgian, Kazakh, Korean, Kurdish, Latin, Latvian, Lithuanian, Macedonian, Malay, Malayalam, Maori, Mongolian, Burmese / Myanmar, Nepali, Norwegian, Nynorsk, Polish, Portuguese, Punjabi, Romanian, Russian, Serbian, Shona, Slovak, Slovenian, Albanian, Spanish, Swahili, Swedish, Tagalog, Telugu, Thai, Turkish, Ukrainian, Uzbek, Vietnamese, Welsh, and Yoruba.
Evaluate meaning and latency separately
For evaluations, keep the source audio, generated translated audio, generated transcript, and reference text together for each run. You want to be able to answer three questions later:
- What did the model hear?
- What did it say?
- What should it have said?
Use the best human reference you can get, such as human-edited subtitles, a professional interpreter transcript, a call transcript reviewed by a bilingual speaker, or a human dub of the source material. Automatic captions and transcripts are useful for quick smoke tests, but they are weaker as the source of truth.
If your reference has timestamps, use them. Time-aligned subtitles or transcripts let you evaluate not just translation quality, but also when the translated audio and captions arrived.
Score translations by meaning, not exact wording. A good translation may use different words, so evaluate whether the important facts, nuance, entities, numbers, and tone are preserved. Track the full distribution of misses, not just the average score, because a few bad errors can matter a lot in live translation.
Traditional text metrics like BLEU can help with quick comparisons, but they are a weak proxy for speech-to-speech quality because they miss semantic similarity.
Measure latency separately from quality. Track source speech to translated audio and source speech to displayed captions. Only use segments where the translation is meaningfully aligned when calculating delay; otherwise, bad matches can make timing data misleading.
Finally, review low-scoring examples manually. Listen to the original source, the generated translation, and the reference segment side by side. This is where you catch the issues aggregate scores miss, especially names, numbers, partial translations, tone, and cases where the model skipped or delayed content.
For a deeper treatment of Realtime evaluation, see the Realtime eval guide.
Realtime Translation changes what it means to build applications for multilingual users. It turns live interpretation into a native part of the product experience, so multilingual conversations can feel less like using a translation tool and more like simply understanding each other in real time. With a dedicated translation session, audio can move through browsers, phone calls, and video rooms as part of the experience itself.
By making language a smaller barrier, these applications can help more people participate, collaborate, and connect.
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み