Files
AI-VideoAssistant/docs/content/api-reference.md

307 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API 参考
本节提供 AI Video Assistant 的 API 接口文档,包括 WebSocket 实时通信协议和后端 REST API。
---
## WebSocket 实时通信
WebSocket 端点提供双向实时语音对话能力,支持音频流输入输出和文本消息交互。
### 连接地址
```
ws://<host>/ws
```
### 传输规则
- **文本帧**JSON 格式控制消息
- **二进制帧**PCM 音频数据(`pcm_s16le`, 16kHz, 单声道)
- 帧长度必须是 640 字节的整数倍20ms 音频 = 640 bytes
---
### 消息流程
```
Client -> hello
Server <- hello.ack
Client -> session.start
Server <- session.started
Server <- config.resolved
Client -> (binary pcm frames...)
Server <- input.speech_started / transcript.delta / transcript.final
Server <- assistant.response.delta / assistant.response.final
Server <- output.audio.start
Server <- (binary pcm frames...)
Server <- output.audio.end
Client -> session.stop
Server <- session.stopped
```
---
### 客户端 -> 服务端消息
#### 1. Handshake: `hello`
客户端连接后发送的第一个消息,用于协议版本协商和认证。
```json
{
"type": "hello",
"version": "v1",
"auth": {
"apiKey": "optional-api-key",
"jwt": "optional-jwt"
}
}
```
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `type` | string | 是 | 固定为 `"hello"` |
| `version` | string | 是 | 协议版本,固定为 `"v1"` |
| `auth` | object | 否 | 认证信息 |
**认证规则**
- 若配置了 `WS_API_KEY`,必须提供匹配的 `apiKey`
-`WS_REQUIRE_AUTH=true`,至少需要提供 `apiKey``jwt` 之一
---
#### 2. Session Start: `session.start`
握手成功后发送的第二个消息,用于启动对话会话。
```json
{
"type": "session.start",
"audio": {
"encoding": "pcm_s16le",
"sample_rate_hz": 16000,
"channels": 1
},
"metadata": {
"appId": "assistant_123",
"channel": "web",
"configVersionId": "cfg_20260217_01",
"systemPrompt": "你是简洁助手",
"greeting": "你好,我能帮你什么?",
"output": {
"mode": "audio"
},
"dynamicVariables": {
"customer_name": "Alice",
"plan_tier": "Pro"
}
}
}
```
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `type` | string | 是 | 固定为 `"session.start"` |
| `audio` | object | 否 | 音频格式描述 |
| `audio.encoding` | string | 否 | 固定为 `"pcm_s16le"` |
| `audio.sample_rate_hz` | number | 否 | 固定为 `16000` |
| `audio.channels` | number | 否 | 固定为 `1` |
| `metadata` | object | 否 | 运行时配置 |
**metadata 支持的字段**
- `appId` / `app_id` - 应用 ID
- `channel` - 渠道标识
- `configVersionId` / `config_version_id` - 配置版本
- `systemPrompt` - 系统提示词
- `greeting` - 开场白
- `output.mode` - 输出模式 (`audio` / `text`)
- `dynamicVariables` - 动态变量(支持 `{{variable}}` 占位符)
---
#### 3. Text Input: `input.text`
发送文本输入,跳过 ASR 识别,直接触发 LLM 回复。
```json
{
"type": "input.text",
"text": "你能做什么?"
}
```
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `type` | string | 是 | 固定为 `"input.text"` |
| `text` | string | 是 | 用户文本内容 |
---
#### 4. Response Cancel: `response.cancel`
请求中断当前回答。
```json
{
"type": "response.cancel",
"graceful": false
}
```
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| `type` | string | 是 | - | 固定为 `"response.cancel"` |
| `graceful` | boolean | 否 | `false` | `false` 立即打断 |
---
#### 5. Tool Call Results: `tool_call.results`
回传客户端执行的工具结果。
```json
{
"type": "tool_call.results",
"results": [
{
"tool_call_id": "call_abc123",
"name": "weather",
"output": { "temp_c": 21, "condition": "sunny" },
"status": { "code": 200, "message": "ok" }
}
]
}
```
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `type` | string | 是 | 固定为 `"tool_call.results"` |
| `results` | array | 否 | 工具结果列表 |
| `results[].tool_call_id` | string | 是 | 工具调用 ID |
| `results[].name` | string | 是 | 工具名称 |
| `results[].output` | any | 否 | 工具输出 |
| `results[].status` | object | 是 | 执行状态 |
---
#### 6. Session Stop: `session.stop`
结束对话会话。
```json
{
"type": "session.stop",
"reason": "client_disconnect"
}
```
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `type` | string | 是 | 固定为 `"session.stop"` |
| `reason` | string | 否 | 结束原因 |
---
#### 7. Binary Audio
`session.started` 之后可持续发送二进制 PCM 音频。
- **格式**`pcm_s16le`
- **采样率**16000 Hz
- **声道**1单声道
- **帧长**20ms = 640 bytes
---
### 服务端 -> 客户端事件
#### 事件包络
所有 JSON 事件都包含统一包络字段:
```json
{
"type": "event.name",
"timestamp": 1730000000000,
"sessionId": "sess_xxx",
"seq": 42,
"source": "asr",
"trackId": "audio_in",
"data": {}
}
```
| 字段 | 类型 | 说明 |
|---|---|---|
| `type` | string | 事件类型 |
| `timestamp` | number | 事件时间戳(毫秒) |
| `sessionId` | string | 会话 ID |
| `seq` | number | 递增序号 |
| `source` | string | 事件来源 (`asr`/`llm`/`tts`/`tool`) |
| `trackId` | string | 事件轨道 (`audio_in`/`audio_out`/`control`) |
| `data` | object | 业务数据 |
---
#### 会话控制类事件
| 事件 | 说明 |
|---|---|
| `hello.ack` | 握手成功响应 |
| `session.started` | 会话启动成功 |
| `config.resolved` | 服务端最终配置快照 |
| `heartbeat` | 保活心跳(默认 50 秒间隔) |
| `session.stopped` | 会话结束确认 |
| `error` | 统一错误事件 |
---
#### ASR 识别事件
| 事件 | 字段 | 说明 |
|---|---|---|
| `input.speech_started` | `probability` | 检测到语音开始 |
| `input.speech_stopped` | `probability` | 检测到语音结束 |
| `transcript.delta` | `text` | ASR 增量识别文本 |
| `transcript.final` | `text` | ASR 最终识别文本 |
---
#### LLM/TTS 输出事件
| 事件 | 字段 | 说明 |
|---|---|---|
| `assistant.response.delta` | `text` | 助手增量文本输出 |
| `assistant.response.final` | `text` | 助手完整文本输出 |
| `assistant.tool_call` | `tool_call_id`, `tool_name`, `arguments` | 工具调用通知 |
| `assistant.tool_result` | `tool_call_id`, `ok`, `result` | 工具执行结果 |
| `output.audio.start` | - | TTS 音频开始 |
| `output.audio.end` | - | TTS 音频结束 |
| `response.interrupted` | - | 回答被打断 |
| `metrics.ttfb` | `latencyMs` | 首包音频时延 |
---
### 错误码
| 错误码 | 说明 |
|---|---|
| `protocol.invalid_json` | JSON 格式错误 |
| `protocol.invalid_message` | 消息格式错误 |
| `protocol.order` | 消息顺序错误 |
| `protocol.version_unsupported` | 协议版本不支持 |
| `auth.invalid_api_key` | API Key 无效 |
| `auth.required` | 需要认证 |
| `audio.invalid_pcm` | PCM 数据无效 |
| `audio.frame_size_mismatch` | 音频帧大小不匹配 |
| `server.internal` | 服务端内部错误 |
---
### 心跳与超时
- **心跳间隔**:默认 50 秒(`heartbeat_interval_sec`
- **空闲超时**:默认 60 秒(`inactivity_timeout_sec`
- 客户端应持续发送音频或轻量消息避免被判定闲置