VibeVoice ASR 部署实战:从 Docker + vLLM 推理服务到 Gradio 网络 Demo 的完整搭建
本篇基于仓库内的部署指南 setup_gradio_demo.md,讲清楚 VibeVoice ASR(语音识别)模型在 GPU 环境下的端到端部署流程:如何用一条 docker run 命令拉起基于 vLLM 的高性能推理服务(支持单卡与多卡数据并行),验证 OpenAI 兼容 API,再叠加 Gradio Web Demo 生成可公开访问的试听/转录页面。读完本文,你可以独立完成 ASR 服务的容器化部署、多 GPU 扩容与故障排查,并深入理解启动脚本 start_server.py 与服务端插件的实现细节。
一、整体架构:两个组件,一条链路
整个 Demo 由两个独立进程组成,均运行在同一个 Docker 容器内:
- ASR 服务:
vllm/vllm-openai:v0.14.1官方镜像中运行 start_server.py,它负责装依赖、拉模型、生成 tokenizer 文件,最终启动vllm serve,对外提供 OpenAI 兼容的/v1/chat/completions接口(模型名注册为vibevoice); - Gradio 前端:gradio_asr_demo_api_video.py 通过 HTTP 调用上面的 API,提供音频/视频上传、流式转写、分段试听与字幕生成界面,可用
--share生成gradio.live公网链接。
从 pyproject.toml 可以看到,vibevoice 包通过 vllm.general_plugins 入口点注册 vllm_plugin:register_vibevoice,这意味着 vLLM 无需修改源码即可识别并加载 VibeVoice 模型——安装即插即用。
二、前置条件
- 具备 CUDA 的 GPU(多卡部署需更多显存设备);
- 支持 GPU 的 Docker(
nvidia-docker); - 本地已克隆 VibeVoice 仓库(容器会把当前目录挂载为
/app):
git clone https://github.com/microsoft/VibeVoice.git
cd VibeVoice
三、Step 1 — 启动 ASR 服务
启动脚本 start_server.py 会自动完成五件事:安装系统依赖(FFmpeg、libsndfile1)、以 vLLM 插件方式安装 VibeVoice、从 Hugging Face 下载模型(默认 microsoft/VibeVoice-ASR)、通过 generate_tokenizer_files.py 生成 tokenizer 文件、最后 exec 启动 vllm serve。
3.1 单 GPU(默认)
docker run -d --gpus '"device=0"' --name vibevoice-asr-demo \
--ipc=host \
-p 6001:6001 \
-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_server.py --port 6001"
两个环境变量的作用:
VIBEVOICE_FFMPEG_MAX_CONCURRENCY=64:控制音频解码(FFmpeg)的并发上限,DP 模式下启动脚本还会自动为每个 worker 单独注入该值;PYTORCH_ALLOC_CONF=expandable_segments:True:开启 PyTorch 可扩展显存分段分配,缓解显存碎片导致的 OOM。
3.2 多 GPU 数据并行(负载均衡)
docker run -d --gpus '"device=0,1,2,3"' --name vibevoice-asr-demo \
--ipc=host \
-p 6001:6001 \
-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_server.py --port 6001 --dp 4"
--dp 4 表示在 4 张 GPU 上各跑 1 个独立副本。从源码 start_dp_server 可以看到其实现细节:
- 为每个副本分配独立 GPU(通过
CUDA_VISIBLE_DEVICES)与内部端口(前端端口 + 100、+101……); - 自动安装并启动 nginx 反向代理,采用
least_conn(最少连接)调度,worker 数默认为2 × 副本数,对外只暴露一个端口; - 设计注释说明:这样做是为了规避 vLLM 内置 DP 协调器在大音频载荷下的单进程 HTTP 瓶颈;
- 每个后端最多等待 10 分钟就绪,任何一个 worker 退出都会触发整体优雅关闭。
Tip:
--dp N用于 N 路数据并行(吞吐扩容,推荐);--tp N用于张量并行(单卡放不下大模型时切分)。两者默认均为 1,详细原理见 vibevoice-vllm-asr.md。
3.3 检查日志
docker logs -f vibevoice-asr-demo
等待出现 Application startup complete. 即表示服务就绪(含模型下载,首次约 2 分钟以上)。
3.4 启动脚本暴露的全部参数
对照 start_server.py 的 argparse 定义,除 --port 和 --dp/--tp 外还可调节:
| 参数 | 说明 | 默认值 |
|---|---|---|
--model, -m |
Hugging Face 模型 ID | microsoft/VibeVoice-ASR |
--port, -p |
服务端口 | 8000 |
--max-num-seqs |
单批次最大并发序列数 | 64 |
--max-model-len |
最大模型上下文长度(支撑长音频) | 65536 |
--gpu-memory-utilization |
显存占用比例 | 0.8 |
--skip-deps |
跳过系统依赖安装 | off |
--skip-tokenizer |
跳过 tokenizer 文件生成 | off |
这些值最终会传入由 _build_vllm_cmd 拼出的 vllm serve 命令,其中固定携带 --dtype bfloat16、--no-enable-prefix-caching、--enable-chunked-prefill、--allowed-local-media-path /app 等 ASR 场景针对性配置。
四、Step 2 — 验证服务
# Check the model is loaded
curl http://localhost:6001/v1/models
预期输出:
{
"data": [{ "id": "vibevoice", ... }]
}
4.1 用真实音频快速测试
仓库自带的 test_api.py 是最小验证客户端:
docker exec -it vibevoice-asr-demo \
python3 /app/vllm_plugin/tests/test_api.py /app/en-Alice_woman.wav \
--url http://localhost:6001
从源码看,该脚本会把音频 base64 编码后以 audio_url 形式放入 /v1/chat/completions 请求,prompt 中要求模型按 Start time / End time / Speaker ID / Content 四个键输出 JSON,并以流式方式接收增量结果;结束后打印总耗时与 RTF(实时因子)= 处理时长 / 音频时长,可用于直观评估服务吞吐。它还支持 --hotwords 参数,把热词以 "with extra info" 形式嵌入 prompt,提升专有名词、人名识别准确率:
python3 /app/vllm_plugin/tests/test_api.py /app/en-Alice_woman.wav --hotwords "Microsoft,Azure,VibeVoice"
(测试音频路径可按需替换为挂载目录中的任意 wav/mp3 文件。)
五、Step 3 — 启动 Gradio Demo
Gradio 进程与 ASR 服务分离,便于单独重启前端而不动推理服务。这里用 tmux 让进程在容器内后台常驻。
5.1 安装 tmux
docker exec vibevoice-asr-demo apt-get install -y tmux
5.2 在 tmux 中启动 Gradio
docker exec vibevoice-asr-demo bash -c \
"PYTHONUNBUFFERED=1 tmux new-session -d -s gradio \
'PYTHONUNBUFFERED=1 python3 /app/vllm_plugin/scripts/gradio_asr_demo_api_video.py \
--api_url http://localhost:6001 --share \
2>&1 | tee /tmp/gradio.log'"
PYTHONUNBUFFERED=1 保证 Python 输出不缓冲,日志能实时写入 /tmp/gradio.log(这也是排查"日志为空"的关键)。
5.3 获取 Share 链接
等待约 20 秒后:
docker exec vibevoice-asr-demo cat /tmp/gradio.log
预期看到:
✅ Connected to API: http://localhost:6001 | Model: vibevoice
🚀 Starting VibeVoice ASR Demo
* Running on local URL: http://0.0.0.0:7860
* Running on public URL: https://xxxxxx.gradio.live
gradio.live 链接为公网可访问的临时分享(有效期约 1 周)。
5.4 Gradio 启动参数
| Flag | 说明 | 默认值 |
|---|---|---|
--api_url URL |
vLLM 服务地址 | http://localhost:8000 |
--share |
创建 Gradio 公网链接 | off |
--port PORT |
本地 Gradio 端口 | 7860 |
--cloudflared |
用 Cloudflare 隧道代替 Gradio share | off |
--max_video_size MB |
允许上传的视频大小上限 | 50 |
补充源码中同样存在但文档未强调的两个参数(见 gradio_asr_demo_api_video.py):--model_name(不指定时自动从 /v1/models 探测)与 --max_new_tokens(默认 4096)。启动时 demo 会调用 demo.queue(default_concurrency_limit=10),即队列模式下最多 10 个请求并发处理,天然支持多人同时使用。
5.5 Demo 前端的实现要点
从 gradio_asr_demo_api_video.py 的源码结构看,它不只是简单的转写页面:
- 多格式兼容:识别
.wav/.mp3/.flac/.ogg/.opus/.m4a等音频与.mp4/.webm/.mov/.mkv等视频扩展名;视频会先用 ffmpeg 抽取 16kHz 单声道 MP3 音轨再提交识别; - 流式输出:
VibeVoiceAPIClient.transcribe_streaming以stream: True请求 API,边收边向页面推送增量文本,并解析usage字段展示 token 统计; - 截断容错:
_parse_segments与_parse_truncated_segments会在响应被截断时尽力抢救出完整的分段(Start/End/Speaker/Content),避免长音频"全军覆没"; - 分段试听与字幕:转写完成后可按说话人分段并行切片(
ThreadPoolExecutor),并生成 SRT / WebVTT 字幕文件; - 热词上下文:界面支持填入 context info,拼入 prompt 后同样走热词增强识别路径。
六、服务管理
6.1 只停 Gradio(保留 ASR 服务)
docker exec vibevoice-asr-demo tmux kill-session -t gradio
重启 Gradio:重跑 Step 3 中的 tmux 命令即可。
6.2 全部停止
docker stop vibevoice-asr-demo
docker rm vibevoice-asr-demo
七、一键完整示例(GPU 0 + 端口 6001)
# 1. Start server
docker run -d --gpus '"device=0"' --name vibevoice-asr-demo \
--ipc=host -p 6001:6001 \
-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_server.py --port 6001"
# 2. Wait for startup (~2 min), then verify
docker logs -f vibevoice-asr-demo # wait for "Application startup complete."
curl http://localhost:6001/v1/models
# 3. Install tmux and launch Gradio
docker exec vibevoice-asr-demo apt-get install -y tmux
docker exec vibevoice-asr-demo bash -c \
"PYTHONUNBUFFERED=1 tmux new-session -d -s gradio \
'PYTHONUNBUFFERED=1 python3 /app/vllm_plugin/scripts/gradio_asr_demo_api_video.py \
--api_url http://localhost:6001 --share \
2>&1 | tee /tmp/gradio.log'"
# 4. Get the public link
sleep 20 && docker exec vibevoice-asr-demo cat /tmp/gradio.log
八、故障排查
| 问题 | 处理办法 |
|---|---|
CUDA out of memory |
换用其他 GPU(device=X),或在 start_server.py 中把 --gpu-memory-utilization 调低(如 0.7) |
| Gradio 日志为空 | 多等一会(约 30s);Gradio 会缓冲输出,务必加 PYTHONUNBUFFERED=1 |
Port already in use |
换端口,或停掉占用容器:docker stop <name> && docker rm <name> |
| Share 链接显示 "No interface" | Gradio 仍在加载,等待日志出现 Application startup complete |
tmux: command not found |
先执行 docker exec <container> apt-get install -y tmux |
补充两条从源码可确认的排查线索:DP 模式下每个后端就绪判定依赖其内部端口的 /v1/models(最长等待 10 分钟),若日志停在 "Waiting for all backends to be ready" 应检查 --gpus 提供的卡数是否 ≥ --dp × --tp;--dp N 启动前脚本会显式断言 GPU 数量充足,数量不足会直接给出 Need X GPUs ... but only Y available 的明确报错。
九、延伸阅读
- 部署指南原文:docs/setup_gradio_demo.md
- vLLM ASR 服务完整说明(TP/DP 原理、流式 API、热词):docs/vibevoice-vllm-asr.md
- 一键启动脚本:vllm_plugin/scripts/start_server.py
- Gradio 前端实现:vllm_plugin/scripts/gradio_asr_demo_api_video.py
- API 测试客户端:vllm_plugin/tests/test_api.py
- 流式 Demo 的 FastAPI 服务端(另一条部署路线):vllm_plugin/asr_streaming_server.py
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00