> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 语音识别 (ASR)

> 使用完全运行在 Qualcomm NPU 上的设备端 ASR 模型将音频转写为文本。

ASR 服务使用完全运行在 Qualcomm NPU 上的设备端模型将音频转写为文本。它同时支持基于
文件的批量转写以及通过 WebSocket 的实时流式转写。

## 前置条件

请先部署并运行 Audio Analytics 容器。设置说明参见
[运行 Audio Analytics 容器](/zh/AI-Developer-Workflow-Ubuntu/topic/audio-analytics-overview)。

## 音频格式要求

| 属性     | 要求                                               |
| ------ | ------------------------------------------------ |
| 格式     | 仅支持 WAV                                          |
| 采样率    | 要求 16 kHz。如果您的音频采样率不同,请通过创建请求中的 `parameters` 声明。 |
| 声道     | 单声道(自动转换)                                        |
| 文件大小上限 | 25 MB                                            |

## 可用模型

查询 models 端点以获取可用 ASR 模型列表:

```bash theme={null}
curl http://localhost:8085/audio-analytics/v1/api/transcriptions/models
```

**响应:**

```json theme={null}
[
  {
    "name": "whisper-small-quantized",
    "display_name": "Whisper Small (Quantized)",
    "description": "OpenAI whisper-small-quantized model for general transcription"
  }
]
```

在转写请求中使用该响应中的 `name` 值。

## 端点

| 方法     | 端点                       | 描述              |
| ------ | ------------------------ | --------------- |
| `GET`  | `/transcriptions/models` | 列出可用的 ASR 模型    |
| `POST` | `/transcriptions/create` | 转写一个文件或启动一个流式会话 |
| `POST` | `/transcriptions/close`  | 关闭一个活动的流式会话     |
| `POST` | `/transcriptions/flush`  | 立即处理已缓冲的音频      |

## 文件转写

上传一个 WAV 文件,并在单次响应中接收完整的转写结果:

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/create \
  -F "file=@recording.wav" \
  -F "model=whisper-small-quantized" \
  -F "language=en" \
  -F "stream=false"
```

**响应:**

```json theme={null}
{
  "text": "The transcribed text from your audio file.",
  "language": "en",
  "language_name": "English",
  "type": "transcript.text.done"
}
```

将 `language` 设置为模型支持的语言代码,或省略以进行自动检测。

## 文件转写并流式返回结果

上传完整的 WAV 文件,在文件处理过程中通过 WebSocket 实时接收转写结果:

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/create \
  -F "file=@recording.wav" \
  -F "model=whisper-small-quantized" \
  -F "language=en" \
  -F "stream=true"
```

服务器确认上传后开始处理。连接到 WebSocket 以接收结果。

**WebSocket 结果:**

```json theme={null}
{ "state": "connection_established" }
{ "type": "transcript.text.done", "text": "The transcribed text.", "language": "en", "language_name": "English", "state": "transcription" }
```

## 实时音频流

实时流式发送原始音频块,并在说话过程中接收转写结果。

### 第 1 步 —— 创建会话

如果您的音频不是 16 kHz 单声道 PCM,请通过 `parameters` 声明音频格式:

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/create \
  -H "Content-Type: application/json" \
  -d '{
    "model": "whisper-small-quantized",
    "language": "en",
    "stream": true,
    "vad": 1200,
    "parameters": [
      {"key": "sampling_rate", "value": "44100"},
      {"key": "channels", "value": "1"},
      {"key": "format", "value": "pcm_s16le"}
    ]
  }'
```

**响应:**

```json theme={null}
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "state": "asr_initialized",
  "text": "Successfully started Transcription Engine. Please connect to the WebSocket to send audio data & receive transcription output.",
  "language": "en",
  "type": "transcript.event"
}
```

`vad` 参数设置在判定语音结束之前的静音等待毫秒数。省略该参数将禁用 VAD,并需要通过
`/transcriptions/flush` 或 `/transcriptions/close` 手动管理话语结束。

### 第 2 步 —— 连接 WebSocket 并发送音频

连接到 `ws://localhost:8085/stream`。服务器会在任何转写消息到达之前先发送一条
`connection_established` 消息:

```json theme={null}
{ "state": "connection_established" }
```

通过 WebSocket 以 8192 字节的分块发送音频:

```javascript theme={null}
const ws = new WebSocket('ws://localhost:8085/stream');

ws.send(JSON.stringify({
  "message_type": "transcriptions_session_audio",
  "message_source": "audio_analytics_api",
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "type": "input_audio",
  "data": "<BASE64_ENCODED_PCM>"
}));
```

### 第 3 步 —— 接收结果

服务器针对每段话语按以下顺序发送消息:

```json theme={null}
{ "type": "transcript.event", "state": "speech_start", "session_id": "..." }
{ "type": "transcript.text.delta", "text": "Partial text...", "language": "en", "session_id": "..." }
{ "type": "transcript.event", "state": "speech_end", "session_id": "..." }
{ "type": "transcript.text.done", "text": "Complete utterance text.", "language": "en", "state": "transcription", "session_id": "..." }
```

在 `transcript.text.done` 之后,引擎会重置并监听下一段话语。会话会一直保持,直到您
调用 `/transcriptions/close`。

### 第 4 步 —— 关闭会话

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/close \
  -H "Content-Type: application/json" \
  -d '{"session_id": "550e8400-e29b-41d4-a716-446655440000"}'
```

**响应:**

```json theme={null}
{
  "text": "",
  "language": null,
  "type": "asr_closed",
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "state": "asr_closed"
}
```

<Note>同一时间只能有一个活动的 ASR 会话。在已有会话活跃时启动第二个会话会返回 HTTP `409 Conflict`。请先关闭现有会话。</Note>

## 语音活动检测 (VAD)

VAD 控制服务器在流式会话期间如何检测话语结束。当检测到的静音达到配置的时长时,服务器
会针对当前话语发送 `speech_end`,然后是 `transcript.text.done`。会话本身保持打开状态
并为下一段话语重置 —— VAD 不会关闭会话。

| 参数    | 描述                                                                                                                             |
| ----- | ------------------------------------------------------------------------------------------------------------------------------ |
| `vad` | 触发 `speech_end` 之前的静音等待毫秒数。例如,`1200` = 1.2 秒静音触发话语结束。省略以禁用 VAD,并通过 `/transcriptions/flush` 或 `/transcriptions/close` 手动管理话语结束。 |

<Note>如果在容器配置中由 `SESSION_TIMEOUT_S` 设定的时长内(默认:30 秒)没有收到任何音频,会话会自动关闭,与 VAD 状态无关。</Note>

## 刷新已缓冲的音频

在不关闭会话的情况下,立即转写已缓冲的音频:

```bash theme={null}
curl -X POST http://localhost:8085/audio-analytics/v1/api/transcriptions/flush \
  -H "Content-Type: application/json" \
  -d '{"session_id": "550e8400-e29b-41d4-a716-446655440000"}'
```

## Python 示例

```python theme={null}
import requests

def transcribe_file(audio_file, language=None):
    url = "http://localhost:8085/audio-analytics/v1/api/transcriptions/create"
    data = {
        "model": "whisper-small-quantized",
        "stream": "false"
    }
    if language:
        data["language"] = language
    with open(audio_file, "rb") as f:
        response = requests.post(url, files={"file": f}, data=data, timeout=60)
    response.raise_for_status()
    return response.json()["text"]

print(transcribe_file("sample.wav"))
```

## 故障排查

**转写质量差:** 请使用 16 kHz 单声道 WAV 文件,并确保音频清晰、背景噪声尽量少。

## 下一步

<CardGroup cols={2}>
  <Card title="文本到语音" icon="volume-high" href="/zh/AI-Developer-Workflow-Ubuntu/topic/tts-container">
    在设备端从文本合成语音
  </Card>

  <Card title="语言翻译" icon="language" href="/zh/AI-Developer-Workflow-Ubuntu/topic/language-translation">
    在设备端在不同语言之间进行文本翻译
  </Card>
</CardGroup>
