ASRService 测试台与 API 文档

同一端口测试一句话识别、实时 WebSocket、长录音和词库,并查看完整请求与返回格式。

检查服务中…

测试音频

一句话音频约 4.571 秒;长录音为医患对话,约 196.996 秒。两者均为 16 kHz 单声道 PCM WAV,下载后可直接用于下面三个测试。

词库管理

每行一个词;强制替换词也可写成 原词[TAB]目标词。创建后点击词库标签即可填入识别请求。

热词

敏感词

强制替换

一句话识别

调用 POST /api/v1,建议使用 60 秒以内的 WAV。

长录音任务

调用 POST /request,自动轮询 /getResult。

实时 WebSocket

选择 WAV 后,浏览器会提取 PCM16 数据并分块发送到 /ws/v1;这不依赖麦克风权限,适合远程 HTTP 页面。

在线 API 文档

以下内容与当前 ASRService 实现同步,示例中的 $BASE 表示本页 HTTP 地址。

返回功能测试 ↑

接口总览

统一语言为 zh-cmn-Hans-CN,模型采样率为 16 kHz。HTTP 错误会同时使用对应的 HTTP 状态码和 JSON status 业务状态码。
通用业务状态码含义
00000成功
20001词库请求或词条格式错误
20114音频请求体为空
20191请求参数无效、音频超过限制或词库 ID 不存在
20193识别或服务处理失败
20302长录音任务正在排队或处理中
20326任务 ID 不存在
GET/health 与 /ready

/health 返回模型、设备和预热状态;/ready 仅在本地模型完整且预热完成后返回 HTTP 200。

curl "$BASE/health"
curl "$BASE/ready"

/health 返回示例

{
  "status": "ok",
  "version": "0.1.0",
  "offline": true,
  "device": "cpu",
  "models_dir": "/opt/asrservice/models",
  "missing_models": [],
  "preload_enabled": true,
  "models_loaded": ["offline+vad+punc+speaker", "streaming", "streaming-punctuation"],
  "models_warmed_up": true
}

/ready 返回示例

{"status":"ready","offline":true}

预热尚未完成时返回 HTTP 503:{"status":"warming_up", ...};模型缺失时返回 HTTP 503:{"status":"not_ready", ...}。

POST/api/v1 一句话识别(≤ 60 秒)

音频放在原始 HTTP body 中,Content-Type 为 application/octet-stream。整个请求等待识别完成后返回。

Query 参数类型/默认值说明
lang_typestring / zh-cmn-Hans-CN当前只支持普通话
formatstring / pcmpcm、pcm_16000 或 WAV/FLAC 等可解码格式
sample_rateint / 16000当前必须为 16000
bit_depthint / 16当前必须为 16
hotwords_idstring / 空已创建的热词库 ID
hotwords_liststring / 空本次请求热词,以 | 或逗号分隔
hotwords_weightfloat / 0.4范围 0.1~1.0;临时热词优先与词库词合并
correction_words_idstring / 空强制替换词库 ID,多个 ID 用 | 分隔,all 表示全部
forbidden_words_idstring / 空敏感词库 ID,支持多个 ID 或 all
clustersint / 00 关闭说话人分离;1 开启自动说话人分离;不接受其他值

WAV 请求示例

curl -X POST \
  "$BASE/api/v1?lang_type=zh-cmn-Hans-CN&format=wav&clusters=1" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @audio.wav

成功返回

{
  "task_id": "5bf51482cdd64c1c9b31b07920a184d8",
  "result": "对方正在通话中,请尝试其他方式。",
  "status": "00000",
  "message": "SUCCESS",
  "segments": [{
    "lang_type": "zh-cmn-Hans-CN",
    "paragraph": 1,
    "begin": "00:00:00,120",
    "end": "00:00:04,400",
    "begin_time": 120,
    "end_time": 4400,
    "seg_num": 1,
    "transcript": "对方正在通话中,请尝试其他方式。",
    "confidence": 1.0,
    "cluster_id": 1
  }]
}
只有开启说话人分离时才返回 segments。confidence 缺失时当前实现会填 1.0,不能视作经过校准的真实置信度。

失败返回示例

{
  "task_id": "...",
  "result": "",
  "status": "20191",
  "message": "一句话识别音频不能超过 60 秒"
}
WS/ws/v1 实时语音识别

连接地址为当前页面同主机的 。音频必须是 16 kHz、单声道、16-bit little-endian PCM;建议每个二进制帧 7680 字节。

1. 首条文本消息:启动

{
  "header": {
    "namespace": "SpeechTranscriber",
    "name": "StartTranscription"
  },
  "payload": {
    "lang_type": "zh-cmn-Hans-CN",
    "format": "pcm",
    "sample_rate": 16000,
    "enable_intermediate_result": true,
    "enable_punctuation_prediction": true,
    "enable_speaker_label": false,
    "hotwords_id": "HW12345678",
    "hotwords_list": ["魔搭", "FunASR"],
    "hotwords_weight": 0.4,
    "correction_words_id": "CW12345678",
    "forbidden_words_id": "FW12345678",
    "user_id": "conversation_001"
  }
}
模式namespace启动/停止消息约束
一句话流式SpeechRecognizerStartRecognition / StopRecognition最长 60 秒
实时长连接SpeechTranscriberStartTranscription / StopTranscription客户端主动结束

2. 循环发送二进制 PCM 数据

// JavaScript 示例
socket.send(pcm16Chunk); // ArrayBuffer/Uint8Array,建议 7680 bytes

3. 停止消息

{"header":{"namespace":"SpeechTranscriber","name":"StopTranscription"}}

服务端事件

事件说明
TranscriptionStarted / RecognitionStarted会话建立成功
SentenceBegin实时长连接检测到首个非空结果
TranscriptionResultChanged / RecognitionResultChanged中间识别结果,是否返回由 enable_intermediate_result 控制
SentenceEnd实时长连接最终句子结果
TranscriptionCompleted / RecognitionCompleted最终结果,随后连接关闭
Pong响应 Ping 或 Heartbeat 控制消息
TaskFailed参数或识别失败,header.status 为 20193

事件返回示例

{
  "header": {
    "namespace": "SpeechTranscriber",
    "name": "TranscriptionCompleted",
    "status": "00000",
    "status_text": "success",
    "task_id": "...",
    "message_id": "...",
    "user_id": "conversation_001"
  },
  "payload": {
    "index": 1,
    "time": 4571,
    "begin_time": 0,
    "speaker_id": "",
    "result": "对方正在通话中,请尝试其他方式。",
    "confidence": 1,
    "volume": 0,
    "words": null
  }
}
enable_speaker_label=true 时,结束阶段会把整段 PCM 再走一次离线识别与 CAM++ 分离,并在最终 payload 中返回 segments;这不是实时增量说话人分离。
POST/request 长录音异步转写

请求类型为 multipart/form-data。服务接收文件后立即返回任务 ID,客户端使用 /getResult 轮询。上传缓存会在成功或失败后立即删除,结果仍可查询。

Form 字段类型/默认值说明
fileFile / 必填上传录音文件
lang_typestring / zh-cmn-Hans-CN当前只支持普通话
formatstring / wav文件格式
sample_rateint / 16000当前必须为 16000
hotwords_idstring / 空热词库 ID
hotwords_liststring / 空临时热词,以 | 或逗号分隔
hotwords_weightfloat / 0.4范围 0.1~1.0
correction_words_idstring / 空强制替换词库 ID
forbidden_words_idstring / 空敏感词库 ID
clustersint / 00 关闭说话人分离;1 开启自动说话人分离;不接受其他值
curl -X POST "$BASE/request" \
  -F "file=@meeting.wav" \
  -F "lang_type=zh-cmn-Hans-CN" \
  -F "format=wav" \
  -F "clusters=1"

创建成功

{
  "status": "00000",
  "message": "",
  "data": {"duration": 197, "task_id": "2aad1d7d835d4a68b28a7b74d4946a22"}
}

轮询结果

curl "$BASE/getResult?task_id=2aad1d7d835d4a68b28a7b74d4946a22"

处理中返回:

{
  "status": "20302",
  "message": "",
  "data": {
    "task_id": "...", "desc": "音频转写中", "file_name": "meeting.wav",
    "insert_time": "2026-09-07 10:00:00", "process_time": "2026-09-07 10:00:01",
    "finish_time": "", "progress": 1, "duration": 0, "statistics": null
  }
}

完成后返回:

{
  "status": "00000",
  "message": "",
  "data": [{
    "lang_type": "zh-cmn-Hans-CN", "paragraph": 1,
    "begin": "00:00:00,150", "end": "00:00:00,950",
    "begin_time": 150, "end_time": 950, "seg_num": 1,
    "transcript": "医生您好。", "confidence": 1.0, "cluster_id": 1
  }],
  "statistics": {
    "keywords": [], "speed": 276, "word_count": 906,
    "insert_time": "...", "process_time": "...", "finish_time": "...", "duration": 197
  }
}
GET/getTasks 与 /deleteTask
/getTasks Query说明
time只查询最近 N 小时,省略表示不限
type0 失败、1 完成、2 处理中、3 排队中
count最多返回多少条
curl "$BASE/getTasks?time=24&type=1&count=20"
curl -X POST "$BASE/deleteTask?task_id=<task_id>"

/deleteTask 只能删除已完成或失败的任务元数据;排队或处理中返回 HTTP 409、业务状态 20193。

{"status":"00000","message":"success","data":null}
CRUD热词、敏感词与强制替换词库
词库根地址ID 前缀词条格式
热词/hotwordsHW普通字符串,单条最多 20 字符
敏感词/forbidden_wordsFW普通字符串,单条最多 10 字符
强制替换/correction_wordsCW原词[TAB]目标词,单条最多 100 字符
方法与地址请求作用
POST /{kind}JSON 或 form-data 文件创建词库,返回词库 ID
GET /{kind}无列出词库
GET /{kind}/{id}无获取详情和 words
PUT /{kind}/{id}JSON 或 form-data修改名称或覆盖词条
DELETE /{kind}/{id}通常无 body删除整个词库
POST /hotwords/{id}JSON words追加热词;其他两类不支持追加
DELETE /hotwords/{id}可带 JSON words有 body 时仅删除指定热词,无 body 删除词库

JSON 创建热词

curl -X POST "$BASE/hotwords" \
  -H "Content-Type: application/json" \
  -d '{"name":"医疗术语","lang_type":"zh-cmn-Hans-CN","words":["房颤","射频消融"]}'

JSON 创建敏感词

curl -X POST "$BASE/forbidden_words" \
  -H "Content-Type: application/json" \
  -d '{"name":"敏感词","lang_type":"zh-cmn-Hans-CN","words":["秘密","机密"]}'

JSON 创建强制替换

curl -X POST "$BASE/correction_words" \
  -H "Content-Type: application/json" \
  -d '{"name":"纠错词","lang_type":"zh-cmn-Hans-CN","words":["无忌\t5G"]}'

UTF-8 文件上传

curl -X POST "$BASE/forbidden_words" \
  -F "name=敏感词" -F "lang_type=zh-cmn-Hans-CN" -F "file=@forbidden.txt"

curl -X POST "$BASE/correction_words" \
  -F "name=纠错词" -F "lang_type=zh-cmn-Hans-CN" -F "file=@corrections.txt"

通用返回

{"status":"00000","message":"success","data":"HW50D67839"}

详情中的 data 包含 id、name、lang_type、status、sample_rate、update_time、amount 和 words。

文本处理顺序固定为:模型热词增强 → 强制替换 → 敏感词遮罩。一个类型最多 200 个词库,每个词库最多 10000 条。
GET测试页面与演示音频
地址说明
/当前测试台和在线接口文档
/docsFastAPI 自动生成的 OpenAPI/Swagger 文档
/openapi.jsonOpenAPI JSON 描述
/demo-audio/sentence.wav4.571 秒、16 kHz 单声道 PCM WAV
/demo-audio/long_demo.wav196.996 秒、16 kHz 单声道 PCM WAV