---
title: "搭配 OpenAI Realtime 用戶端使用 ThunderPhone"
description: "使用已儲存的智慧體或內嵌工作階段設定，將相容於 OpenAI Realtime 的伺服器用戶端指向 ThunderPhone。"
---

ThunderPhone 實作了 OpenAI Realtime 事件模型中專注的一部分。
既有的伺服器端用戶端可在使用 ThunderPhone 語音智慧體時，保留其 WebSocket、音訊、工作階段與回應事件流程。

## 連線前

你需要 ThunderPhone 組織的私密 API 金鑰，以及可開啟 WebSocket 的伺服器執行環境。請勿從瀏覽器程式碼連線，或將金鑰暴露給瀏覽器。若要使用已儲存的智慧體，請先部署並複製其數字智慧體 ID。

連線至：

```text
wss://api.thunderphone.com/v1/realtime
```

從你的伺服器驗證 WebSocket 升級：

```http
Authorization: Bearer sk_live_YOUR_API_KEY
```

無法設定交握標頭的用戶端可使用查詢字串驗證，但 URL 更容易洩漏至日誌中。

## 選擇由誰管理設定

| 模式 | 連線方式 | 設定來源 |
| --- | --- | --- |
| 已儲存的智慧體 | `?agent_id=12` | 已部署的提示、語音、產品、語言、知識，以及相容的伺服器端執行工具 |
| 內嵌 | 無 `agent_id` | 用戶端第一個被接受的 `session.update` |

### 已儲存的智慧體

使用已部署的智慧體 ID 連線：

```text
wss://api.thunderphone.com/v1/realtime?agent_id=12
```

智慧體會在 Socket 連線期間啟動。其問候語仍可使用，
但 Realtime 會停用其語音靜默確認，並省略 `transfer_call`
與 `send_keypad_input`。其他相容工具會在 ThunderPhone 上執行。請勿為此模式
傳送內嵌指示或由用戶端執行的工具。

在智慧體啟動前，使用 `input_audio_format`、
`output_audio_format`、`input_rate` 與 `output_rate` 查詢參數設定傳輸音訊。你
無法在連線後變更已儲存的設定或音訊格式。

### 內嵌工作階段

不使用 `agent_id` 時，請等待 `session.created`，然後傳送 `session.update`：

```json
{
  "type": "session.update",
  "session": {
    "type": "realtime",
    "instructions": "Answer questions clearly and keep responses brief.",
    "audio": {
      "input": {
        "format": { "type": "audio/pcm", "rate": 24000 }
      },
      "output": {
        "format": { "type": "audio/pcm", "rate": 24000 },
        "voice": "olivia"
      }
    },
    "config": {
      "product": "bolt"
    }
  }
}
```

第一個被接受的更新會佈建通話。`session.updated` 表示
工作階段已啟用。在此之後，指示、語音、產品、工具與音訊格式均無法
變更。

內嵌工作階段沒有自動問候語或語音靜默確認。若要讓智慧體先說話，請附加一則系統或使用者訊息，並傳送
`response.create`。完全閒置的工作階段仍會在平台的靜默通話限制時結束，預設為 600 秒。

## 使用官方 OpenAI SDK

傳入以 `/v1` 結尾的 WebSocket 基礎 URL；SDK 會附加 `/realtime`。`model` 值是相容性名稱，不會選取 ThunderPhone 產品。請在工作階段設定或已儲存的智慧體中選擇產品。

這項連線檢查會建立內嵌 Bolt 工作階段、列印事件直到第一個 `session.updated`，然後關閉。請使用[最精簡 Python 用戶端](/api-reference/realtime#minimal-python-client)串流音訊。

```python
import asyncio
import os

from openai import AsyncOpenAI


async def main():
    client = AsyncOpenAI(
        api_key=os.environ["THUNDERPHONE_API_KEY"],
        websocket_base_url="wss://api.thunderphone.com/v1",
    )

    async with client.realtime.connect(
        model="thunderphone-realtime"
    ) as connection:
        await connection.session.update(session={
            "type": "realtime",
            "instructions": "Listen to the caller and help them complete the call.",
            "config": {"product": "bolt"},
        })
        async for event in connection:
            print(event.type)
            if event.type == "session.updated":
                break


if __name__ == "__main__":
    asyncio.run(main())
```

保留你現有的輸入音訊附加、回應音訊增量、中斷、函式呼叫、錯誤處理，以及正常關閉 Socket 的邏輯。內嵌自訂函式會在你的用戶端中執行；請透過 Realtime 通訊協定回傳其結果。已儲存智慧體的工具會在 ThunderPhone 上執行。

## 工作階段生命週期與失敗情況

一個 WebSocket 代表一通通話。無效的智慧體 ID 或遭拒絕的內嵌設定會產生 `error` 事件。在將工作階段視為已啟用前，請先等待 `session.updated`。請宣告實際的輸入與輸出格式及取樣率：PCM 取樣率不符會使音訊播放過快或過慢，而不會產生驗證錯誤。

工作階段開始後，當你的應用程式完成作業時，請正常關閉 Socket。內嵌工作階段可使用由用戶端執行的函式。已儲存智慧體工作階段使用相容且由 ThunderPhone 執行的工具，且不提供轉接或按鍵輸入。

## 測試整合

先使用[最精簡 Python WAV 用戶端](/api-reference/realtime#minimal-python-client)，以及符合其宣告取樣率的單聲道 PCM16 WAV。請確認：

1. 伺服器接受設定並傳送 `session.updated`。
2. 輸入會以預期速度產生逐字稿與回應音訊事件。
3. 中斷與取消回應會停止剩餘的輸出音訊。
4. 內嵌函式結果或已儲存智慧體工具結果會回傳給模型。
5. 無效輸入會產生你的用戶端能處理的 `error` 事件。
6. 你的用戶端會關閉 Socket，且該通話會顯示在[通話紀錄](/zh-Hant/guides/review-calls)中。

[Realtime WebSocket 參考文件](/api-reference/realtime)列出可接受的事件、音訊格式、工作階段欄位與完整範例。

## 費用

Realtime 通話採用所選產品的一般每分鐘費率。啟用即時逐字稿增量會為整個工作階段加收每分鐘附加費；費率請參閱[即時逐字稿](/api-reference/realtime#live-transcripts)，產品費率請參閱[定價](/zh-Hant/guides/pricing)。

`POST /v1/realtime/sessions` 是獨立的受管理 LiveKit 路徑。它會建立房間與具範圍限制的參與者權杖；直接 WebSocket 連線不需要使用它。

如需框架整合，請參閱[從 Pipecat 使用 ThunderPhone](/zh-Hant/guides/use-with-pipecat)與[從 LiveKit Agents 使用 ThunderPhone](/zh-Hant/guides/use-with-livekit)。
