语音(TTS / ASR / 对话闭环)
四个语音端点,全部用 Bearer API key 鉴权:
| 端点 | 方向 | 形态 |
|---|---|---|
POST /v1/tts | 文本 → 语音 | 同步,一次回整段 mp3 |
POST /v1/tts/stream | 文本 → 语音 | 流式,边合成边吐 PCM |
POST /v1/asr | 语音 → 文本 | 同步,音频字节进、文本出 |
POST /v1/voice | 语音 → 语音 | 同步,音频进 → asr→agent→tts → 智能音频出(一趟闭环) |
TTS 同步:POST /v1/tts
curl "$BASE/v1/tts" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"text":"你好喵,今天也要加油哦"}' \
-o hello.mp3请求体:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | 是 | 要合成的文本(空白串 400) |
voice | string | 否 | 音色 id,缺省 female-shaonv(甜美少女音) |
成功响应:200,Content-Type: audio/mpeg,响应体即 mp3 字节(32kHz / 128kbps),存成文件直接可播。
错误:400(体坏 / text 空)、401、429、502「语音合成暂时不可用」(上游或配置问题)。
TTS 流式:POST /v1/tts/stream
请求体与 /v1/tts 完全相同;区别在响应:
200,Content-Type: application/octet-stream;- 响应体是裸 PCM 流:s16le / 32000 Hz / 单声道,响应头
X-Audio-Format: pcm_s16le_32000_mono标明格式; - 边合成边推送,首块约 1.5 秒到达——适合「说半句就开始播」的实时场景。
播放示例(macOS / Linux,ffplay):
curl -sN "$BASE/v1/tts/stream" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"text":"边合成边播放的一段话"}' \
| ffplay -autoexit -nodisp -f s16le -ar 32000 -ch_layout mono -i -已知边界:若流已经以 200 开始、上游中途失败,流会提前结束(无带内错误事件)——请按「收到的字节即有效音频」处理。
ASR:POST /v1/asr
请求体就是原始音频字节(不是 JSON):wav / mp3 / flac / ogg 等常见格式皆可,上限 25MB。
curl "$BASE/v1/asr" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/octet-stream" \
--data-binary @speech.wav成功响应:
{"text":"识别出来的文字"}错误:400「音频为空」、401、413「音频过大(上限 25MB)」、429、502(识别服务不可用 / 失败)。
质量说明(诚实):底层是 Workers AI Whisper,中文内容识别可用,但专有名词可能同音错(如「喵喵」→「妙妙」)、不带标点。拿来「听懂指令喂给 Agent」足够;要出版级转写请自行后处理。
语音对话(一趟闭环):POST /v1/voice
把上面三段(asr → agent → tts)在服务端串成一趟请求:你只发一次音频,直接拿回 Agent 的智能语音应答。客户端零编排、一次往返。对话端完整继承 /v1/agent 的全部能力——工具、知识库(RAG)、人格、多轮记忆、BYO 自带模型、多租户,统统继承。
# 把 speech.wav 编码成 base64,POST /v1/voice,拿回 JSON
AUDIO_B64=$(base64 < speech.wav | tr -d '\n')
curl "$BASE/v1/voice" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d "{\"audio_b64\":\"$AUDIO_B64\",\"session_id\":\"my-voice-session\"}"请求体:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
audio_b64 | string | 是 | base64 编码的音频(格式同 /v1/asr:wav/mp3/flac/ogg 等;解码后 ≤25MB) |
session_id | string | 否 | 会话 id(同 /v1/agent:续多轮记忆;缺省 anon) |
voice | string | 否 | 回复语音音色 id(同 /v1/tts,缺省 female-shaonv) |
kb | bool | 否 | 知识库检索开关(透传 agent;缺省按租户有无文档自动检索) |
persona_id | string | 否 | 人格库引用 id(透传 agent;租户隔离) |
skip_tts | bool | 否 | 跳过 TTS 合成、只回文字(缺省 false)。瘦客户端/MCU 若自走 /v1/tts/stream 取流式音频,置 true 可省一整段 mp3 的合成与传输、端到端更快;此时 audio_b64:null、audio_format:"none" |
成功响应(200):
{
"asr_text": "今天天气怎么样",
"reply_text": "喵~今天天气不错哦,适合出门晒太阳!",
"audio_b64": "SUQzBAAAAAAA...(回复语音的 base64 mp3)",
"audio_format": "mp3"
}把 audio_b64 base64 解码即得 mp3 字节,存文件直接可播:
curl -s "$BASE/v1/voice" -H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d "{\"audio_b64\":\"$(base64 < speech.wav | tr -d '\n')\"}" \
| jq -r '.audio_b64' | base64 -d > reply.mp3降级(分段不全挂):
- ASR 听不清(空/失败)→
502「听不清,请再说一遍喵」; - Agent 出错 →
502,透传喵口吻错误文案; - TTS 失败 → 仍回
200,但audio_b64为null(文字成功、只是没出声)——客户端可只读reply_text; skip_tts:true→ 主动不合成:audio_b64:null、audio_format:"none"(瘦客户端自走/v1/tts/stream取音频,省一次合成 + 传输)。
错误:400(体坏 / audio_b64 非法 base64 / 音频为空)、401、413(解码后 >25MB)、429、502(见上)。
延迟口径(诚实):同步版延迟 = asr + agent + tts 串行之和(可观,适合「一问一答」而非「说半句就抢答」)。要更低延迟的「边说边播」,现阶段请自行用
/v1/asr+/v1/agent(SSE)+/v1/tts/stream三段手动串(全流式 voice 是后续升级路径)。
手动串三段(更低延迟 / 边收边播)
ASR 出文本 → 喂 /v1/agent(SSE 边收边显)→ 回复喂 /v1/tts/stream(边合成边播),三个端点串起来就是一个能听会说、低延迟的语音助手——这正是 NovaMeow 桌面客户端的做法。一趟式 /v1/voice 则适合瘦客户端(ESP32 等)/ 一问一答场景:省去客户端编排。