VibeVoice vLLM 流式 ASR 部署¶
使用 vLLM 将 VibeVoice ASR 流式模型部署为高性能 API 服务。会话在音频尚未说完时持续推送音频,每个分块返回一条转写文本,因此文字会在音频结束前出现。
非流式: vLLM-asr
🔥 Key Features¶
- 🎤 真流式转写:从实时麦克风或不断增长的音频流中逐块转写
- 🚀 前缀缓存会话:每个分块复用之前所有分块的 KV 缓存,因此随着会话增长,成本保持平稳
- 📡 WebSocket + REST:
/v1/stream用于实时音频,/v1/transcribe和/v1/chat/completions用于完整文件 - 🔌 插件架构:无需修改 vLLM 源代码——只需安装并运行
- 🎚️ 由检查点定义的分块:分块和前瞻窗口均从检查点读取,因此模型始终以训练时的几何配置运行
🛠️ 安装¶
使用官方 vLLM Docker 镜像(推荐)
-
克隆仓库
-
启动服务器(后台模式)
docker run -d --gpus all --name vibevoice-vllm-streaming \ --ipc=host \ -p 8000:8000 \ -e VIBEVOICE_FFMPEG_MAX_CONCURRENCY=64 \ -e PYTORCH_ALLOC_CONF=expandable_segments:True \ -v $(pwd):/app \ -w /app \ --entrypoint bash \ vllm/vllm-openai:v0.14.1 \ -c "python3 /app/vllm_plugin/scripts/start_streaming_server.py"
⚡ 多 GPU 部署¶
Tensor Parallel¶
将单个模型拆分到 2 块 GPU 上(适合 GPU 显存有限的情况):
docker run -d --gpus '"device=0,1"' --name vibevoice-vllm-streaming \
--ipc=host \
-p 8000:8000 \
-e VIBEVOICE_FFMPEG_MAX_CONCURRENCY=64 \
-e PYTORCH_ALLOC_CONF=expandable_segments:True \
-v $(pwd):/app \
-w /app \
--entrypoint bash \
vllm/vllm-openai:v0.14.1 \
-c "python3 /app/vllm_plugin/scripts/start_streaming_server.py --tp 2"
Data Parallel¶
此处不提供 --dp。一个会话的音频只存在于某一个副本的前缀缓存中,而轮询调度会将该会话后续的分块发送到从未见过先前分块的副本。若要用 N 块 GPU 提升吞吐,请在每块 GPU 上各运行一个服务器,使用各自端口,并按整个会话路由,而不是按单个分块路由:
for i in 0 1 2 3; do
docker run -d --gpus "\"device=$i\"" --name vibevoice-vllm-streaming-$i \
--ipc=host \
-p $((8000 + i)):8000 \
-e PYTORCH_ALLOC_CONF=expandable_segments:True \
-v $(pwd):/app \
-w /app \
--entrypoint bash \
vllm/vllm-openai:v0.14.1 \
-c "python3 /app/vllm_plugin/scripts/start_streaming_server.py"
done
- 查看日志
注意: -
-d参数表示在后台运行容器(分离模式) - 使用docker stop vibevoice-vllm-streaming停止服务 - 模型将下载到容器内的 HuggingFace 缓存(~/.cache/huggingface)中
🚀 用法¶
用法 1:测试 API¶
流式服务器运行后,使用提供的脚本进行测试:
# 基本流式转写
docker exec -it vibevoice-vllm-streaming python3 vllm_plugin/tests/test_api_streaming.py /app/audio.wav
# 使用热词提高特定术语的识别效果
docker exec -it vibevoice-vllm-streaming python3 vllm_plugin/tests/test_api_streaming.py /app/audio.wav --hotwords "Microsoft,VibeVoice"
对于不进行流式传输的调用方,也可以使用整文件端点:
注意: - 音频/视频文件必须位于挂载目录(容器中的
/app)内。测试前,请将文件复制到 VibeVoice 文件夹中。 - 热词有助于提高对特定领域术语(如专有名词、技术术语和说话人姓名)的识别效果。
用法 2:启动演示页面¶
在主机网络上的第二个容器中启动演示,以便 --api_url 能访问已在主机网络运行的服务器:
docker run -d --network host --name vibevoice-vllm-streaming-demo \
-v $(pwd):/app \
-w /app \
--entrypoint bash \
vllm/vllm-openai:v0.14.1 \
-c "python3 /app/vllm_plugin/scripts/fastapi_asr_streaming_demo_api.py --api_url http://localhost:8000"
打开 http://localhost:7860,然后从麦克风录制或选择一个文件。页面会在整个录制过程中保持一个 WebSocket 连接,因此您还在说话时文字就会实时出现。
无需额外安装:演示只需要 fastapi、uvicorn、httpx 和 websockets,这些都已包含在 vLLM 镜像中。
用法 3:公开分享演示页面¶
添加 --cloudflared 参数即可获得公共链接。该参数会在首次使用时将 cloudflared 二进制文件下载到 ~/.local/bin,因此容器需要可访问外网:
docker run -d --network host --name vibevoice-vllm-streaming-demo \
-v $(pwd):/app \
-w /app \
--entrypoint bash \
vllm/vllm-openai:v0.14.1 \
-c "python3 /app/vllm_plugin/scripts/fastapi_asr_streaming_demo_api.py --api_url http://localhost:8000 --cloudflared"
隧道建立后会打印链接:
relaying to http://localhost:8000, open http://localhost:7860
public URL: https://xxxx-xxxx-xxxx.trycloudflare.com
注意:当页面不在
localhost上时,请使用https链接而非普通http地址——浏览器只会在安全上下文中授予麦克风访问权限。
演示选项¶
| 标志 | 描述 | 默认值 |
|---|---|---|
--api_url URL |
流式服务器 URL | http://localhost:8000 |
--port PORT |
本地演示端口 | 7860 |
--host HOST |
绑定地址 | 0.0.0.0 |
--cloudflared |
使用 cloudflared 隧道创建公共链接 | 关闭 |
--max_new_tokens N |
每个分块默认的最大新 token 数 | 256 |
端点¶
| 端点 | 描述 |
|---|---|
WS /v1/stream |
实时会话:先发送 JSON 配置,然后发送 float32 PCM 帧,最后发送 "end" |
POST /v1/transcribe |
上传整个文件,内部自动分块,回复中返回完整转写文本 |
POST /v1/transcribe_batch |
一次请求中包含多个文件 |
POST /v1/chat/completions |
兼容 OpenAI,适用于现有客户端 |
GET /v1/config |
已加载检查点的采样率与分块几何信息 |
环境变量¶
| 变量 | 描述 | 默认值 |
|---|---|---|
VIBEVOICE_FFMPEG_MAX_CONCURRENCY |
同时进行的 FFmpeg 解码上限 | 未设置——不设上限;上面的 docker run 命令设置为 64 |
PYTORCH_ALLOC_CONF |
PyTorch 内存分配器配置 | 未设置;上面的 docker run 命令设置为 expandable_segments:True |
与 start_server.py 不同,流式启动器本身不施加 FFmpeg 限制,因此未设置 VIBEVOICE_FFMPEG_MAX_CONCURRENCY 确实意味着不受限。
📊 性能提示¶
- GPU 内存:如果你有专用 GPU,使用
--gpu-memory-utilization 0.9可获得最大吞吐量 - 会话长度:
--max-model-len决定单个会话可运行多长时间;处理长达一小时的流时请调高它 - 并发会话:在提高并发之前先调大
--mm-processor-cache-gb——它必须容纳所有进行中会话的音频窗口
🚨 故障排除¶
常见问题¶
- "CUDA out of memory"
- 调低
--gpu-memory-utilization - 调低
--mm-processor-cache-gb -
使用更小的
--max-model-len -
"is not a streaming checkpoint"
- 检查点的
preprocessor_config.json中没有chunk_frames -
改用
start_server.py来提供服务 -
"tokenizer layout mismatch"
<|text_chunk_end|>缺失或位于另一个 id,导致永远无法结束一个分块。服务器会拒绝启动,而不是先服务第一个分块之后又返回空分块-
重新生成:
python3 -m vllm_plugin.tools.generate_tokenizer_files --output MODEL_PATH --streaming -
"Cache miss" 或会话在多个分块之后停滞
-
调高
--mm-processor-cache-gb,或降低并发会话数量 -
"Plugin not loaded"
- 验证安装:
pip show vibevoice - 检查入口点:
pip show -f vibevoice | grep entry
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vib/VibeVoice