OpenAI Realtime API × Cloudflare Worker で音声→音声のリアルタイム翻訳デモを作ってみた
Cloudflare Workers を使って簡易なリアルタイム翻訳デモを作る(OpenAI RealtimeAPI)🎉
📌 はじめに
これまで、発話した内容を API で翻訳し音声として流すには
3つの工程を順番に処理する必要がありました。
🧱 従来のフロー(3段階)

- STT(Speech-to-Text)
音声 → テキストへ変換 - 翻訳 / LLM
翻訳されたテキストを生成 - TTS(Text-to-Speech)
テキスト → 音声へ変換
リアルタイム性のある自然な会話が難しい 😵
🎙️ Speech-to-Speech(STS)とは?
OpenAI が提供する 音声入力→音声出力 を直接扱える新しい音声API です。
公式ドキュメント:
https://platform.openai.com/docs/guides/speech-to-speech

「Speech-to-Speech(STS)」により…
これまでの「STT → 翻訳 → TTS」という工程を意識せずに扱えるようになりました。
※ 2025年8月に一般提供開始 とのことです。キャッチアップが遅れました💦
🎯 本記事でやりたいこと
本記事では、OpenAI の Speech-to-Speech(STS) を使って
「話しかけるとAIがすぐ翻訳した音声で返してくれるデモ」に挑戦したいと思います!
ただし、ブラウザから直接Realtime APIに接続すると APIキーが外部に漏れる危険性 があるので
👉 Cloudflare Workers を“リレーサーバー”として挟み、APIキーを隠したまま Realtime API を呼び出す方法 🎉 を簡単なデモでご紹介します!

🧰 必要なもの
本記事の手順に必要なのはこれだけです。
-
OpenAI API Key(従量課金)
- Speech-to-Speech(Realtime API)を使うため。
- 「Billing が有効」 なアカウント
- クレジットカード登録が完了しているだけではNGです。
- クレジット残高が0ではないこと!!※これ重要※

- Realtime APIは高めなのでご利用時は、課金状況確認しながらご利用ください!
-
Cloudflare アカウント(無料)
- WebSocketリレーサーバーとして利用
-
任意のブラウザ
- 私はChrome
-
html を開けるローカル環境
- 作業用PCでも大丈夫!(Live Server拡張機能)
🛠 設定概要
- OpenAI API Key を用意
- Cloudflare アカウントを作成
- Worker を作成
- APIキーを Secret として登録
- Worker を WebSocket リレーとして実装
- ブラウザ側から Worker に接続
- AI と音声で会話して確認
📝詳細手順
🛠 Cloudflare Worker の設定手順(サーバー側)
🚀 1. OpenAI APIキーの用意
https://platform.openai.com にアクセスして、APIを作成してください。
作成されたAPIキーはコピーしておきましょう!!
🚀 2. Cloudflare アカウントを作成
Cloudflareのサインアップページ にアクセスして、アカウントを作成してください。
※下は、ログイン後の画面です。

🚀 3. Cloudflare Worker を作成
-
左のメニュー>BUILD>Workers & Pagesを開き
-
一番下の「Start with Hello World!」の Get startedボタンをクリック

-
Workername(なんでもいい)を入れて「Deploy」ボタンをクリック

🚀 4. APIキーを Secret として登録
-
作成した Workerの「Settings」をクリック
-
「Variables & Secrets」を開く
-
「Add variable(追加)」をクリック

-
下記の内容で登録してDeploy
- Type:Secret
- 名前:OPENAI_API_KEY
- Value(値):あなたのOpenAIのAPIキー
🚀 5. Worker を WebSocket リレーとして実装してDeploy
-
作成した WorkerのOverview の右上に「Edit Code」をクリック

-
下のコードを貼り付けて、Deployボタン

Workerの説明
- ブラウザからの WebSocket を受け取る
- OpenAI Realtime API へ WebSocket を張る
- 受け取ったメッセージをそのまま中継する
- APIキーを環境変数で管理し、ブラウザに渡さない
🚀 ブラウザ(HTML/JS)から接続して動作確認する
ここからは ブラウザ側(HTML/JS)のコード です。
ブラウザ側の説明
- マイク音声を録音する(MediaRecorder)
- ボタンを押している間の音声のみ
- 録音データを Cloudflare Worker に WebSocket で送る
- Worker 経由で返ってくる AI の音声を再生する
表示されたHTMLからお試し
- 接続開始ボタン(WebSocket接続開始)
- 話すボタンを押しながら 日本語を話す
- ボタンを離すと、即英語が流れる
🎯 つまづきポイント
ここでは 「つまづいたポイント」だけピックアップして紹介 します。
🎤 押して話す(Push-to-Talk)で必要な3ステップ
Realtime API で「押して話す (Push-to-Talk)」を実現するためには、
次の 3 つを確実に送る必要があります。
-
input_audio_buffer.append— 押している間、音声を送り続ける -
input_audio_buffer.commit— ボタンを離した瞬間、録音ブロックを確定する -
response.create— 翻訳音声を生成してもらう
🔊 自分の声が二重に聞こえる(エコー問題)
最初、Push-to-Talk 後に 録音した自分の声と翻訳音声が同時に聞こえる現象があり、ここはかなりハマりました。
そのため、エコー対策として
録音した音声はスピーカーに流さない処理(silentGain) を入れています。
🔁 多重接続で音声が 2 回流れる
Push-to-Talk が動くようになってくると、
次にハマりやすいのが 「なんか翻訳音声が二重に聞こえる…」問題 です。
原因はシンプルで、
「接続開始ボタンを何度も押してしまい、
WebSocket が 複数本 開いている」
という状態です。
ブラウザから同じ Worker に対して new WebSocket(WORKER_URL) を何回も呼ぶと、
- WebSocket A も OpenAI に中継
- WebSocket B も OpenAI に中継
という形になり、
同じ翻訳結果が 2 回分再生されるように聞こえます。
そのため、すでに 接続中なら「接続開始」を無視する処理 を入れています。
(実際のコードは付録のソースにコメント付きで掲載しています)
🎉 付録
※ブラウザ側(HTML/JS)のコードの完全版です。サンプルですので、ご参考まで。
※const WORKER_URL = "wss://あなたのURLに貼り換えて.workers.dev";だけ書き換えて、動かしてみてください。
Discussion