> ## Documentation Index
> Fetch the complete documentation index at: https://quwan-b8010aef.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 火山引擎流式语音识别

> 在 ModelHub 中使用火山引擎 ASR 实时识别语音

# 火山引擎流式语音识别

通过 WebSocket 接口 `/v1/stream_asr` 持续发送 PCM 音频，并实时接收识别结果。

## 可用模型

| 模型 | 说明 |
| - | - |
| `volcengine_bigmodel` | 火山引擎大模型流式语音识别 |
| `volcengine_normal` | 火山引擎流式语音识别 |

## 音频要求

发送的音频必须满足以下要求：

| 项目 | 要求 |
| - | - |
| 编码 | PCM signed 16-bit little-endian |
| 采样率 | 16000 Hz |
| 声道 | 单声道 |
| 容器 | 裸 PCM，不包含 WAV 文件头 |

如果源文件不是该格式，可先使用 FFmpeg 转换：

```bash theme={null}
ffmpeg -i input.mp3 -f s16le -acodec pcm_s16le -ac 1 -ar 16000 input.pcm
```

## Python 示例

安装 WebSocket 客户端：

```bash theme={null}
pip install websockets
```

以下示例读取 `input.pcm`，按 100 毫秒分片发送，并在音频末尾补充静音以触发完整识别结果：

```python theme={null}
import asyncio
import base64
import json
import os

import websockets

API_KEY = os.environ["MODELHUB_API_KEY"]
MODEL = "volcengine_normal"
WS_URL = f"wss://model-api.skyengine.com.cn/v1/stream_asr?model={MODEL}"


async def recognize(path: str) -> None:
    headers = {"Authorization": f"Bearer {API_KEY}"}

    async with websockets.connect(WS_URL, additional_headers=headers) as ws:
        with open(path, "rb") as audio_file:
            while chunk := audio_file.read(3200):
                await ws.send(json.dumps({
                    "type": "input_audio_buffer.append",
                    "audio": base64.b64encode(chunk).decode(),
                }))
                await asyncio.sleep(0.1)

        # 1 秒 16 kHz、16-bit、单声道静音
        await ws.send(json.dumps({
            "type": "input_audio_buffer.append",
            "audio": base64.b64encode(bytes(32000)).decode(),
        }))

        completed = []
        while True:
            try:
                message = await asyncio.wait_for(ws.recv(), timeout=3)
            except asyncio.TimeoutError:
                break
            event = json.loads(message)
            if event.get("type") == "error":
                raise RuntimeError(event["error"]["message"])
            if event.get("type") == "conversation.item.input_audio_transcription.delta":
                print("实时结果：", event["transcript"])
            if event.get("type") == "conversation.item.input_audio_transcription.completed":
                completed.append(event["transcript"])

        print("最终结果：", "".join(completed))


asyncio.run(recognize("input.pcm"))
```

将 `MODEL` 改为 `volcengine_bigmodel` 即可调用大模型流式识别。

## 请求格式

ASR 使用 WebSocket 协议，因此建连请求没有 HTTP JSON Body。连接成功后，客户端通过 WebSocket 文本消息发送 JSON Body。

建连地址：

```text theme={null}
wss://model-api.skyengine.com.cn/v1/stream_asr?model=volcengine_normal
```

建连 Header：

```text theme={null}
Authorization: Bearer <API-KEY>
```

WebSocket 连接建立后，可以直接发送音频 Body：

```json theme={null}
{
  "type": "input_audio_buffer.append",
  "audio": "<BASE64_PCM_AUDIO>"
}
```

如果需要设置识别语言，可以先发送会话配置 Body：

```json theme={null}
{
  "type": "session.config",
  "config": {
    "language": "zh-CN"
  }
}
```

发送了 `session.config` 时，请等待平台返回 `session.ready`，然后再发送音频 Body。不需要设置会话参数时，无需发送 `session.config`，也无需等待 `session.ready`。

音频 Body：

```json theme={null}
{
  "type": "input_audio_buffer.append",
  "audio": "<BASE64_PCM_AUDIO>"
}
```

## 连接参数

| 参数 | 位置 | 必填 | 说明 |
| - | - | - | - |
| `model` | URL Query | 是 | 使用的 ASR 模型名称。 |
| `Authorization` | Header | 是 | `Bearer <API-KEY>`。 |

## 客户端事件

### `session.config`

配置当前识别会话。该事件不是必需步骤；只有需要设置会话参数时才发送。发送后应等待平台返回 `session.ready`，再开始发送音频。

```json theme={null}
{
  "type": "session.config",
  "config": {
    "language": "zh-CN",
    "enable_itn": true,
    "enable_punc": true,
    "enable_ddc": false
  }
}
```

| `config` 参数 | 类型 | 默认值 | 适用模型 | 说明 |
| - | - | - | - | - |
| `language` | string | 未指定 | 两款模型 | 识别语言。是否可用以及具体取值取决于模型服务。 |
| `enable_itn` | boolean | `true` | `volcengine_bigmodel` | 开启数字、日期等内容的文本规整。 |
| `enable_punc` | boolean | `true` | `volcengine_bigmodel` | 在识别结果中添加标点。 |
| `enable_ddc` | boolean | `false` | `volcengine_bigmodel` | 开启语义顺滑。 |

`volcengine_normal` 只读取 `language`；`enable_itn`、`enable_punc` 和 `enable_ddc` 不会传递给该模型。

不发送 `session.config` 时，WebSocket 建连成功后可以直接发送第一条 `input_audio_buffer.append`，平台将使用模型默认配置。

### `input_audio_buffer.append`

发送一段 Base64 编码的 PCM 音频。建议按固定时长连续发送，不要一次发送完整的长音频。

```json theme={null}
{
  "type": "input_audio_buffer.append",
  "audio": "<BASE64_PCM_AUDIO>"
}
```

| 参数 | 类型 | 必填 | 说明 |
| - | - | - | - |
| `type` | string | 是 | 固定为 `input_audio_buffer.append`。 |
| `audio` | string | 是 | Base64 编码的 PCM 音频字节。 |

### `input_audio_buffer.commit`（仅 `volcengine_normal`）

最后一包音频发送完毕后，发送该事件，明确结束当前语音段，无需再补静音。平台会向火山发送协议尾包，并等待最终识别结果。

```json theme={null}
{
  "type": "input_audio_buffer.commit",
  "event_id": "event_xxx"
}
```

`event_id` 必填，长度为 1～128 字节，每一轮使用新的 ID。平台会忽略近期已经接受的同 ID commit 重发。

发送后请等待 `conversation.item.input_audio_transcription.completed`，再开始发送下一轮音频；对外 WebSocket 连接可以继续复用。等待期间发送下一轮音频、提交另一个 commit，或对空音频缓冲区提交 commit，会收到 `invalid_request_error`，其中 `error.event_id` 指向触发错误的客户端事件。

完成事件仍使用现有的 `input_audio_buffer.speech_stopped` 和 `conversation.item.input_audio_transcription.completed`，不额外发送 commit 确认事件。只有静音的音频也可能返回空的最终文本。等待最终结果超过 5 秒，或上游断连、重连失败时，会返回服务端错误并结束连接。

`volcengine_bigmodel` 不支持该事件，会返回 `invalid_request_error`。不发送 commit 的调用方式继续使用原来的 VAD 自动判停。

## 服务端事件

| 事件 | 说明 |
| - | - |
| `session.ready` | 会话配置完成，可以开始发送音频。 |
| `conversation.item.created` | 创建了一段新的语音识别内容。 |
| `input_audio_buffer.speech_started` | 检测到语音开始。 |
| `conversation.item.input_audio_transcription.delta` | 当前语音段的实时累计识别文本。 |
| `input_audio_buffer.speech_stopped` | 检测到语音结束。 |
| `conversation.item.input_audio_transcription.completed` | 当前语音段的最终识别文本；一次连接可能返回多条。 |
| `error` | 请求或识别失败。 |

最终结果事件示例：

```json theme={null}
{
  "event_id": "event_xxx",
  "type": "conversation.item.input_audio_transcription.completed",
  "item_id": "item_xxx",
  "content_index": 0,
  "transcript": "欢迎使用语音识别服务。",
  "audio_duration": 3
}
```

火山引擎模型能力说明可参考[火山引擎语音识别产品文档](https://www.volcengine.com/docs/6561/1354871)。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.