MiniInfer API OpenAI 兼容 · 自研 CUDA 推理引擎
▶ 在线体验 Demo(麦克风实时转写 / 文件转写 / 语音合成)
鉴权
除 /health 与本页外,所有接口都要求 Bearer 令牌(服务端启动时以
MINI_API_KEY 环境变量配置;未配置则服务只应绑定内网):
Authorization: Bearer <MINI_API_KEY>
令牌缺失或错误一律返回 401:{"error":"invalid api key"}。
请勿把令牌放在 URL 或日志中。
并发上限与局域网 HTTPS(M147)
并发上限:MINI_MAX_CONNS(默认 24)以内的并发请求正常服务,超过即回
429 Too Many Requests + Retry-After: 2(连接关闭,带退避重试);
/health 与本页、/demo 豁免(探活与静态页不被业务挤死)。
推理引擎本身互斥串行,上限保护的是连接线程与内存,不是 GPU 队列。
局域网 HTTPS(M148 单端口双协议):MINI_TLS_CERT/MINI_TLS_KEY 提供即
在同一端口同时服务 HTTPS 与 HTTP——accept 后按首字节自动分流(0x16=TLS
ClientHello,否则明文),客户端无需任何配置区分,两个 scheme 都打同一端口
(部署脚本无证书时自动生成自签 10 年证,SAN 覆盖 localhost 与 LAN IP,浏览器首次访问需
"继续前往";curl 加 -k)。SSE 流式在 TLS 下行为一致。
如需把 HTTPS 挪到独立端口(例如防火墙策略),显式设 MINI_TLS_PORT 即可。
curl -k https://<LAN-IP>:8950/health # 与 http:// 同端口 curl http://<LAN-IP>:8950/health
端点一览
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET | /health | 公开 | 存活探针(负载均衡/监控用) |
| GET | /docs | 公开 | 本页 |
| GET | /v1/models | 令牌 | 模型列表(OpenAI 格式) |
| GET | /metrics | 令牌 | 内部计数器(JSON) |
| POST | /v1/chat/completions | 令牌 | 对话补全(支持 stream SSE) |
| POST | /v1/completions | 令牌 | 文本补全(支持 stream SSE) |
| POST | /v1/audio/transcriptions | 令牌 | 语音转文字(ASR,需服务端启用) |
| POST | /v1/audio/stream/… | 令牌 | 准实时流式 ASR 会话(分片上传,partial/final) |
| POST | /v1/audio/speech | 令牌 | 文字转语音(TTS,需服务端启用) |
| POST | /v1/agent/stream | 令牌 | 语音代理编排(M123:LLM+TTS 同进程,text/audio 事件流) |
| POST | /train /learn /loss /save /rl_apply /rl_rollout | 令牌 | 训练/RL 内部接口 |
POST /v1/audio/transcriptions — 语音转文字
multipart 表单(file=@录音.mp3)或直接把音频字节作为请求体。
支持 wav 直传;mp3/m4a/flac 等由服务端调用 ffmpeg 自动转 16 kHz 单声道。
长录音自动按能量切分解码,不会在长段上退化。
curl -X POST https://<host>/v1/audio/transcriptions \ -H "Authorization: Bearer $KEY" \ -F "file=@visit.mp3" \ -F "response_format=verbose_json"
参数:file(音频文件);response_format:
json(默认)或 verbose_json(带分段时间戳);
model(sensevoice 或 fireredasr2,默认
fireredasr2,可被服务端 MINI_ASR_BACKEND 改写)。
SenseVoice 为 CTC 引擎:纯内存解码、无临时文件,单次解码约快 19×。
// json
{"text":"……"}
// verbose_json
{"text":"……","duration":301.23,
"segments":[{"start":0.00,"end":12.40,"text":"……"}, …]}
可选说话人区分(diarization):URL 加 ?diarize=1(或 multipart 字段
diarize=1),segments 每段多一个 speaker 字段(0 起),
顶层多 speakers(人数)。流式会话在创建时加
?diarize=1,final 响应带全局一致的段级 speaker。
实现:能量 VAD 分段 → CAM++ 说话人嵌入(192 维)→ AHC 余弦聚类;
阈值 MINI_DIAR_THRESHOLD(默认 0.12,余弦距离,越低越严)。
已知边界:轮次间隔 >1s 的对话可靠;句间停顿 <1s 的连续朗读/合成音频
受段内内容主导影响,可能过分裂。
POST /v1/chat/completions — 对话补全
curl -X POST https://<host>/v1/chat/completions \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"你好"}],"max_tokens":300,"temperature":0}'
参数:messages(必需,OpenAI 消息数组);max_tokens;
temperature(0=贪心);top_p;frequency_penalty /
presence_penalty / repeat_penalty;stop(停止串);
stream(true 时返回 text/event-stream,逐块
data: {...},以 data: [DONE] 结束)。
// 非流式响应
{"id":"…","object":"chat.completion","model":"mininfer","choices":[
{"index":0,"message":{"role":"assistant","content":"……"},"finish_reason":"stop"}],
"usage":{"prompt_tokens":…,"completion_tokens":…,"total_tokens":…}}
POST /v1/completions — 文本补全
curl -X POST https://<host>/v1/completions \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"prompt":"哥白尼提出的","max_tokens":64,"temperature":0}'
参数与 chat 相同,把 messages 换成 prompt(字符串)。
POST /v1/audio/stream/… — 准实时流式转写(会话制)
客户端边录边传(16 kHz 单声道 s16le 裸 PCM 分片),服务端滚动解码当前话轮: partial 随新音频刷新(每 ≥0.5 s 新音频最多一次,延迟 ~1-2 s), 检测到 ≥0.7 s 停顿即定稿该话轮并累计进 text/segments; 话轮上限 30 s。定稿精度与整段转写一致(同一模型、同一 AGC/防退化路径)。 会话闲置 10 分钟自动回收。
model 选):fireredasr2(默认)
定稿精度逐字级(对齐相似度 1.000),partial 解码成本随文本增长(分片 RTT
28→171 ms);sensevoice 非自回归单次前向,分片 RTT 平坦 12-58 ms、
自动加标点,精度 0.957(同音字级错误)。低延迟 partial 场景选 sensevoice,
定稿/精度场景用默认。两后端皆为滚动重解码(非逐帧在线),机制见上。# 1) 建会话
SID=$(curl -s -X POST -H "Authorization: Bearer $KEY" \
".../v1/audio/stream/sessions?model=sensevoice" \
| python3 -c "import json,sys;print(json.load(sys.stdin)['sid'])") # 默认 fireredasr2
# 2) 循环:每录 0.5~1 s 就 POST 一片裸 PCM(s16le, 16kHz, mono)
curl -X POST .../v1/audio/stream/sessions/$SID \
-H "Authorization: Bearer $KEY" --data-binary @chunk.pcm
# → {"text":"已定稿…","partial":"正在说…","buffer_s":3.2,
# "utterance_final":false,"final":false,"segments":[…]}
# 3) 结束(定稿残留话轮并销毁会话)
curl -X POST ".../v1/audio/stream/sessions/$SID?finish=1" -H "Authorization: Bearer $KEY"
# 弃用:curl -X DELETE .../v1/audio/stream/sessions/$SID -H "Authorization: Bearer $KEY"
# 运维:GET .../v1/audio/stream/sessions → {"live":N,"sessions":[{"sid":..,"buffer_s":..}]}
# 错误状态码:401 令牌 / 404 未知会话或路由 / 429 会话满 / 400 参数或音频不可解码
客户端采音示例(ffmpeg 从麦克风推 PCM 分片):
ffmpeg -f alsa -i default -ac 1 -ar 16000 -f s16le - | 按 16KB 切片 POST;
Python 见仓库 tools/asr_stream_test.py。
POST /v1/agent/stream — 语音代理编排(M123)
LLM 边生成边按句边界切出,每句立即送 Qwen3-TTS 句级流式合成——TTS(句N) 与
LLM 生成(句N+1) 重叠。SSE 事件流:{"type":"meta",…} 开路、
{"type":"text","text":"…"}(完句文本)、
{"type":"audio","delta":"<base64 s16le/24kHz>"}(逐 2s 音频块,
首块 0.67s)、data: [DONE] 终。请求:
{"input":"用户一句话","voice":"mumei(可选)","system":"可选","max_tokens":1024}。
需 MODULE=agent(LLM+MINI_TTS_GGUF 同进程)。
POST /v1/audio/speech — 文字转语音(可选)
curl -X POST https://<host>/v1/audio/speech \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"input":"要合成的文本"}' --output out.wav
参数:input(必需,≤200 字,MINI_TTS_MAX_CHARS 可调);
response_format 仅支持 wav;
stream(true = SSE 流式合成:逐块返回 base64 s16le/24kHz PCM
(data: {"delta":"…"},data: [DONE] 结束),首块音频 ~0.5s)。
需服务端以 MINI_TTS_GGUF 启用,否则返回 400
{"error":"TTS disabled …"}。首次合成包含模型加载,之后为热延迟。
加载失败(显存不足等)返回 503,服务不会中断。多音色:
"voice":"名字" 选 MINI_QTTS_VOICES="名:bundle前缀;..." 注册项
(bundle=tools/qtts_voice_bundle.sh 按参考音频产出;缺省=预置 g3)。
M100 引擎 cosyvoice3(服务端 MINI_COSY3_GGUF 启用):请求加
"model":"cosyvoice3",可选 "mode":"zero_shot"(默认,音色克隆)|"cross_lingual";
参考音色 = 服务端 MINI_COSY3_VOICE_WAV + MINI_COSY3_REF_TEXT;
多音色:"voice":"名字" 选 MINI_COSY3_VOICES="名:wav[:转写];..."
注册项(转写空=cross_lingual 专用;参考音频须长——裁窗参考会退化生成)。
stream:true 时走窗式流式(M141 起默认档):非对称首窗
24:96:64:100(首窗 24 帧≈0.5s 音频早出、稳态窗 96 帧、64 帧左上下文、
100 帧 prompt 尾),逐窗吐 base64 delta(事件格式同上,首窗 ~0.5s、
稳态窗 ~1.9s 音频);AR 解码与 flow/hift 进程池重叠,首音频 ~0.38s、
RTF ~0.21(280W+MPS 暖态实测)。ar/flow/hift 仍为三个独立常驻进程池
(同进程串联会触发 GPU 掉卡,已实测);建议启用 CUDA MPS
(nvidia-cuda-mps-control -d)让 AR∥flow 真并发。
回退句级串行:COSY3_STREAM_WIN="96:64:100" COSY3_P2B_SERIAL=1。
首句另含一次性音色 prep(CPU 前向 ~40s,按音色缓存于
MINI_COSY3_CACHE,之后命中缓存)。仅设 MINI_COSY3_GGUF 不设
MINI_TTS_GGUF 时本引擎为默认。
错误格式
所有错误统一 {"error":"…"},常见:401 令牌错误、400 参数缺失、
音频不可解码、ASR/TTS 未启用。