Laravel 12|OpenAI Realtime API 超低遅延なAI音声対話の検証

Laravel 12|OpenAI Realtime API 超低遅延なAI音声対話の検証

OpenAIのRealtime APIを使って、AIとのリアルタイム会話を検証してみました。
WebRTCを活用することで、従来の「録音 → 送信 → 処理 → 返信」というステップを排除し、「話しながら同時に処理する」という圧倒的な低遅延体験が可能です。

今回作るものの構成

  • サーバー側 (Laravel): APIキーを隠蔽し、安全な「一時的なトークン(Ephemeral Token)」を発行する。
    ※苦肉の策です。実運用となるとセキュリティを検討する必要があります。
  • フロント側 (WebRTC): ブラウザのマイク音声をOpenAIにストリーミング送信し、返ってきた音声データを再生する。

1. サーバー側の準備:セッション・トークンの発行

APIキーを直接フロントエンドに書くのは非常に危険です。OpenAI Realtime APIには、1分間だけ有効なクライアント用トークンを発行するエンドポイントがあります。

Controllerの作成

app/Http/Controllers/RealtimeController.php
namespace App\Http\Controllers;

use Illuminate\Support\Facades\Http;

class RealtimeController extends Controller
{
    public function index() {
        return view('realtime.index');
    }

    public function token() {
        $apiKey = env('OPENAI_API_KEY');

        // OpenAIにセッション開始をリクエスト
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $apiKey,
            'Content-Type' => 'application/json',
        ])->post('https://api.openai.com/v1/realtime/sessions', [
            'model' => 'gpt-4o-mini-realtime-preview-2024-12-17',
            'voice' => 'alloy', // 声のタイプ
            'instructions' => 'あなたは親切なAIアシスタントです。日本語で自然に会話してください。',
        ]);

        return $response->json();
    }
}

2. フロントエンドの実装:WebRTCによるリアルタイム接続

ブラウザのRTCPeerConnectionを使ってOpenAIと直接つながります。

Viewの作成(抜粋)

resources/views/realtime/index.blade.php JavaScriptの主要な処理フローは以下の通りです:
async function startConversation() {
    // 1. 自前サーバーから一時トークンを取得
    const response = await fetch('/realtime/token');
    const data = await response.json();
    const EPHEMERAL_KEY = data.client_secret.value;

    // 2. WebRTCの準備
    const pc = new RTCPeerConnection();

    // AIからの音声が届いたら再生する設定
    const audioEl = document.createElement('audio');
    audioEl.autoplay = true;
    pc.ontrack = (e) => audioEl.srcObject = e.streams[0];

    // 自分のマイクを追加
    const localStream = await navigator.mediaDevices.getUserMedia({ audio: true });
    pc.addTrack(localStream.getTracks()[0]);

    // 3. OpenAIとSDP(接続情報)を交換
    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);

    const sdpResponse = await fetch("https://api.openai.com/v1/realtime?model=gpt-4o-mini-realtime-preview-2024-12-17", {
        method: 'POST',
        body: offer.sdp,
        headers: {
            Authorization: `Bearer ${EPHEMERAL_KEY}`,
            'Content-Type': 'application/sdp'
        }
    });

    const answer = { type: 'answer', sdp: await sdpResponse.text() };
    await pc.setRemoteDescription(answer);
}

3. 検証

リアルタイム音声会話

結論:AIとの会話が「ツール」から「対話」へ

相槌を打つタイミングや、言葉の詰まり方まで人間らしく感じられます。
まぁ、ChatGPTの音声モードの利用と同じ感覚です。

Laravelなら、ここに「会話履歴の保存」や「ユーザー情報の紐付け」を組み合わせるのも簡単です。
実装によっては大きな可能性を感じます!

感じたこと

STTとTTSの組み合わせより会話はスムーズに行えリアルタイム感があるけど、1分くらいの会話で約10円消費し、なかなかマネタイズが難しそう。。。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です