次の方法で共有


SIP 経由で GPT Realtime API を使用する (クラシック)

現在表示中:Foundry (クラシック) ポータルのバージョン - 新しい Foundry ポータルのバージョンに切り替える

Azure OpenAI GPT Realtime API for speech and audio は GPT-4o モデル ファミリの一部であり、低待機時間の"音声入力、音声出力" の会話操作をサポートします。

WebRTC、SIP、または WebSocket を介してリアルタイム API を使用して、オーディオ入力をモデルに送信し、リアルタイムでオーディオ応答を受信できます。 SIP 経由で Realtime API をget startedするには、この記事の手順に従います。

セッション開始プロトコル (SIP) は、音声通話などの IP ネットワーク経由のリアルタイム通信セッションを確立、変更、および終了するために使用されるシグナリング プロトコルです。 リアルタイム API での SIP サポートにより、受信 VoIP 呼び出しを AI を利用したセッションに直接ルーティングして処理できます。

サポートされているモデル

GPT リアルタイム モデルは、米国 2 およびスウェーデン中部リージョン でのグローバルデプロイで使用できます。

  • gpt-4o-mini-realtime-preview (2024-12-17)
  • gpt-4o-realtime-preview (2024-12-172025-06-03)
  • gpt-realtime (2025-08-28)
  • gpt-realtime-mini (2025-10-06)
  • gpt-realtime-mini (2025-12-15)
  • gpt-realtime-1.5 (2026-02-23)

[前提条件]

GPT リアルタイム オーディオを使うには、次のものが必要です。

  • Azure サブスクリプション - 無料で作成

  • サポートされているリージョンで作成されたAzure OpenAIリソース。 詳細については、「リソースを作成し、Azure OpenAIを使用してモデルをデプロイする」を参照してください。

  • この記事の「サポートされているモデル」セクションで説明されているように、サポートされているリージョンでの GPT リアルタイム モデル のデプロイ。 モデルは、Foundry モデル カタログまたは Microsoft Foundry ポータルのprojectからデプロイできます。

  • Azure ロールの割り当て: リソースに対する Cognitive Services ユーザー、または Cognitive Services 共同作成者 。 この記事のコード サンプルでは、次のものが必要です。

  • Python 3.8 以降。

  • 次の Python パッケージがインストールされています。

    • openai>=1.0.0 (webhook のサポートを含む)
    • flask>=2.0.0
    • websockets>=10.0
    • requests
  • SIP トランキング プロバイダー (Twilio、Vonage、Bandwidth など) を持つアカウント。

  • SIP プロバイダーから購入した電話番号。

SIP に接続する

電話番号を Realtime API に接続するには、SIP トランキング プロバイダー (Twilio など) を使用します。 トランキング プロバイダーは、電話呼び出しを IP トラフィックに変換するサービスです。

  1. SIP トランキング プロバイダーから電話番号を購入します。
  2. Azure OpenAI Webhook Service REST API を使用して、着信呼び出し用の Webhook を作成します。
  3. Azure OpenAI リソースの内部 ID を取得します。
    1. Azure portalで、リソースに移動します。
    2. JSON ビューを選択して内部 ID を検索します。
  4. proj_<internalId> 形式 (例: proj_88c4a88817034471a0ba0fcae24ceb1b) を使用して、project ID を構築します。
  5. SIP トランクを構成して呼び出しをルートします: sip:proj_<internalId>@<region>.sip.ai.azure.com;transport=tls

SIP で現在サポートされているリージョンは、 swedencentraleastus2です。

着信呼び出しの処理

Azure OpenAI がprojectに関連付けられている SIP トラフィックを受信すると、Webhook エンドポイントは受信イベント メッセージを受信します。 SIP 呼び出しで発生したイベントは、次に示す例のように type = realtime.call.incoming です。

POST https://my_website.com/webhook_endpoint
user-agent: OpenAI/1.0 (+https://platform.openai.com/docs/webhooks)
content-type: application/json
webhook-id: wh_685342e6c53c8190a1be43f081506c52 # unique ID for idempotency
webhook-timestamp: 1750287078 # timestamp of delivery attempt
webhook-signature: v1,Signature # signature to verify authenticity from OpenAI

{
  "object": "event",
  "id": "evt_685343a1381c819085d44c354e1b330e",
  "type": "realtime.call.incoming",
  "created_at": 1750287018, // Unix timestamp
  "data": {
    "call_id": "some_unique_id",
    "sip_headers": [
      { "name": "From", "value": "sip:+142555512112@sip.example.com" },
      { "name": "To", "value": "sip:+18005551212@sip.example.com" },
      { "name": "Call-ID", "value": "rtc_xyz"}
    ]
  }
}

Webhook エンドポイントから、webhook イベントのcall_id値を使用して、この呼び出しを受け入れる、拒否する、または参照することができます。 呼び出しを受け入れるときは、Realtime API セッションに必要な構成 (命令、音声など) を指定します。 確立されたら、WebSocket を設定し、通常どおりセッションを監視できます。 呼び出しの受け入れ、拒否、監視、参照、および切断を行う API については、次のセクションで説明します。

呼び出しを受け入れてセッションを構成する

着信呼び出しを承認し、応答するリアルタイム セッションを構成するには、呼び出しの受け入れエンドポイントを使用します。 クライアント シークレットの作成に送信するのと同じパラメーターを送信します。 session.update メッセージに使用する任意の値を含めることができますが、typemodelinstructionsが必要です。

承認には、次に示すように、 api-key ヘッダーまたはベアラー トークンを使用できます。 モデル名は、実際にはデプロイの名前であることに注意してください。

curl -X POST "https://<your azure resource name>.openai.azure.com/openai/v1/realtime/calls/$CALL_ID/accept" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "type": "realtime",
        "model": "gpt-realtime",
        "instructions": "You are Alex, a friendly concierge for Example Corp."
      }'

要求パスには次のものが含まれている必要があります。

  • call_id Webhook イベントからの realtime.call.incoming
  • Authorization (または api-key)ヘッダー

エンドポイントは、SIP レッグが呼び出され、リアルタイム セッションが確立されると、 200 OK を返します。

ヒント

確認: 成功した受け入れによって HTTP 200 が返されます。 Webhook サーバーのログで応答の状態を確認します。

不要な呼び出しを拒否する

着信通話を処理しない場合 (たとえば、サポートされていない国/地域コードから) 招待を拒否するには、拒否呼び出しエンドポイントを使用します。 キャリアに送り返される応答を制御するには、必要な call_id パス パラメーターと共にオプションの SIP ステータス コードを指定します。 次の例は 486を送信する要求を示しています。これは、システムがビジー状態のため、呼び出しを受け取るのが難しいことを示しています。

curl -X POST "https://<your azure resource name>.openai.azure.com/openai/v1/realtime/calls/$CALL_ID/reject" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status_code": 486}'

状態コードが指定されていない場合、SIP サーバーは 603 (拒否) の状態コードを通信事業者に送信します。 成功した要求は、SIP 応答が配信された後、 200 OK で応答します。

別のエンドポイントへの呼び出しを転送 (参照) する

Refer 呼び出しエンドポイントを使用してアクティブな呼び出しを転送します。 SIP call_id ヘッダーに配置する必要があるtarget_uriRefer-To (tel:+14155550123sip:agent@example.comなど) を指定します。

curl -X POST "https://<your azure resource name>.openai.azure.com/openai/v1/realtime/calls/$CALL_ID/refer" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target_uri": "tel:+14155550123"}'

REFER が SIP プロバイダーに中継されると、API は 200 OK を返します。 ダウンストリーム システムは、呼び出し元の残りのコール フローを処理します。

通話イベントを監視し、セッション コマンドを発行する

呼び出しを受け入れた後、同じセッションへの WebSocket 接続を開いてイベントをストリーミングし、リアルタイム API コマンドを発行します。 既存の呼び出しに対して WebSocket を作成するには、 call_id パラメーターを使用する必要があります。 モデル引数は、呼び出しを受け入れるときに JSON の一部として構成されるため、使用されません。 次の例は、一般的なシナリオを示しています。 response.create メッセージを発行して、電話に応答して Hello と言うよう Realtime API システムに指示します。

特定の SIP 呼び出しに対する WebSocket 要求のサンプルを次に示します。

GET wss://<your azure resource name>.openai.azure.com/openai/v1/realtime?call_id={call_id}

クエリ パラメーター

パラメーター タイプ [説明]
call_id 文字列 realtime.call.incoming webhook からの識別子。

Headers

Authorization: Bearer $TOKEN (または api-key: <your API key>)

WebSocket は、他のリアルタイム API 接続とまったく同じように動作します。 response.createsession.updateなどのメッセージを送信して通話を制御したり、サーバー イベントをリッスンして進行状況を追跡したりできます。

次のコード スニペットは、WebSocket 接続の作成方法を示しています。

import WebSocket from "ws";

const callId = "rtc_u1_9c6574da8b8a41a18da9308f4ad974ce";
const ws = new WebSocket(`wss://<your azure resource name>.openai.azure.com/openai/v1/realtime?call_id=${callId}`, {
    headers: {
        "api-key": `${process.env.OPENAI_API_KEY}`,
    },
});

ws.on("open", () => {
    ws.send(
        JSON.stringify({
            type: "response.create",
        })
    );
});

ヒント

確認: 接続から数秒以内に WebSocket で session.created イベントを受信する必要があります。

セッションを終了して切断する

アプリケーションが呼び出し元を切断する必要がある場合は、ハングアップエンドポイントを使用してセッションを終了してください。 このエンドポイントを使用して、SIP と WebRTC の両方のリアルタイム セッションを終了できます。

curl -X POST "https://<your azure resource name>.openai.azure.com/openai/v1/realtime/calls/$CALL_ID/hangup" \
  -H "Authorization: Bearer $TOKEN"

API は、呼び出しの破棄を開始すると、 200 OK で応答します。

Webhook エンドポイントのサンプル

次のコードは、 realtime.call.incoming ハンドラーの Python の例です。 呼び出しを受け入れ、Realtime API からのすべてのイベントをログに記録します。

from flask import Flask, request, Response
from openai import OpenAI, InvalidWebhookSignatureError
import asyncio
import json
import os
import requests
import time
import threading
import websockets

app = Flask(__name__)
client = OpenAI(
    webhook_secret=os.environ["OPENAI_WEBHOOK_SECRET"]
)

AUTH_HEADER = {
    "api-key": os.getenv("OPENAI_API_KEY")
}

call_accept = {
    "type": "realtime",
    "instructions": "You are a support agent.",
    "model": "gpt-realtime",
}

response_create = {
    "type": "response.create",
    "response": {
        "instructions": (
            "Say to the user 'Thank you for calling, how can I help you'"
        )
    },
}

async def websocket_task(call_id):
    try:
        async with websockets.connect(
            "wss://<your azure resource>.openai.azure.com/openai/v1/realtime?call_id=" + call_id,
            additional_headers=AUTH_HEADER,
        ) as websocket:
            await websocket.send(json.dumps(response_create))

            while True:
                response = await websocket.recv()
                print(f"Received from WebSocket: {response}")
    except Exception as e:
        print(f"WebSocket error: {e}")

@app.route("/", methods=["POST"])
def webhook():
    try:
        event = client.webhooks.unwrap(request.data, request.headers)

        if event.type == "realtime.call.incoming":
            requests.post(
                "https://<your azure resource name>.openai.azure.com/openai/v1/realtime/calls/"
                + event.data.call_id
                + "/accept",
                headers={**AUTH_HEADER, "Content-Type": "application/json"},
                json=call_accept,
            )
            threading.Thread(
                target=lambda: asyncio.run(
                    websocket_task(event.data.call_id)
                ),
                daemon=True,
            ).start()
            return Response(status=200)
    except InvalidWebhookSignatureError as e:
        print("Invalid signature", e)
        return Response("Invalid signature", status=400)

if __name__ == "__main__":
    app.run(port=8000)

トラブルシューティング

Webhook 署名の検証が失敗する

InvalidWebhookSignatureErrorを受け取った場合:

  • OPENAI_WEBHOOK_SECRET環境変数が webhook 作成のシークレットと一致するかどうかを確認します。
  • 解析された JSON ではなく、生の要求本文のバイトを unwrap()に渡していることを確認します。
  • 検証の前に、ミドルウェアによって要求本文が変更されていないことを確認します。

Webhook に到達しない SIP 呼び出し

  • SIP トランクが <region>.sip.ai.azure.com にルーティングするように構成されていることを確認します。
  • TLS が有効になっていることを確認します (SIP URI でtransport=tls )。
  • project ID 形式が正しいことを確認します:proj_<32-character-hex-id>

WebSocket 接続が失敗する

  • wss://ではなく、ws:// (セキュリティで保護された WebSocket) を使用していることを確認します。
  • call_idが受け入れられた呼び出しと一致するかどうかを確認します。
  • API キーまたはトークンがリソースにaccessされていることを確認します。

一般的な SIP 状態コード

Code 説明 解決策
486 ここではビジー状態 システムがオーバーロードされました。再試行ロジックを実装する
603 拒否 明示的に拒否された呼び出し。受け入れ/拒否ロジックを確認する
408 要求のタイムアウト ネットワークの問題。Azureへの接続を確認する