🎙️

OpenAI Realtime API × Cloudflare Worker で音声→音声のリアルタイム翻訳デモを作ってみた

に公開

Cloudflare Workers を使って簡易なリアルタイム翻訳デモを作る(OpenAI RealtimeAPI)🎉

📌 はじめに

これまで、発話した内容を API で翻訳し音声として流すには
3つの工程を順番に処理する必要がありました。

🧱 従来のフロー(3段階)

  1. STT(Speech-to-Text)
     音声 → テキストへ変換
  2. 翻訳 / LLM
     翻訳されたテキストを生成
  3. 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拡張機能)

🛠 設定概要

  1. OpenAI API Key を用意
  2. Cloudflare アカウントを作成
  3. Worker を作成
  4. APIキーを Secret として登録
  5. Worker を WebSocket リレーとして実装
  6. ブラウザ側から Worker に接続
  7. 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