VibeVoice 的 Gradio demo 起不来:按仓库文档的前置条件逐条核

2026-08-18

「Gradio demo 起不来」这句话在 VibeVoice 这条链路上至少对应四种完全不同的故障。因为 docs/setup_gradio_demo.md 给的不是一条命令,而是三段:先用 Docker 起一个 vLLM 的 ASR server,再验证这个 server,最后才在同一个容器里把 Gradio 脚本拉起来。中间任何一段没走完,你看到的都是同一个现象——浏览器打不开,或者日志是空的。

所以排查的第一件事不是重启,是先确定断在哪一段。

现象:四种「起不来」

按仓库文档 Troubleshooting 一节列出的说法,常见表现有这么几类:Gradio 的日志文件是空的;share 链接打开显示 “No interface”;tmux: command not found;以及 Port already in use。另外还有一类文档没归到这张表里但同样常见——Gradio 页面出来了,但顶部状态是警告而不是绿勾。

这几种表现分属不同层。日志为空和 tmux 找不到是启动脚本层面的;“No interface” 按文档的说法是还在加载;而状态行的警告说明 Gradio 进程本身活着,是它连不上后端。

怎么确认断在哪一段:三个可执行的判定动作

第一步,看 ASR server 的启动日志。

docker logs -f vibevoice-asr-demo

文档写明要一直等到出现 Application startup complete.,这句话出现才代表 server 就绪。没出现,那就不是 Gradio 的事。

vllm_plugin/scripts/start_server.py 的模块 docstring 把它做的事列成了五件:装系统依赖、装 VibeVoice 包、从 Hugging Face 下模型、生成 tokenizer 文件、启动 vLLM 服务。对应到代码里是 install_system_deps()apt-get install -y ffmpeg libsndfile1)、install_vibevoice()pip install -e /app[vllm])、download_model()(走 huggingface_hubsnapshot_download)、generate_tokenizer()、最后 start_vllm_server()os.execvp 把自己替换成 vllm serve。每一步在 run_command() 里都会打印一条带等号分隔线的标题,所以日志停在哪一行,就是卡在哪一步——这是这个脚本最好用的地方。

顺带记一个源里的不一致:install_vibevoice() 装的是 /app[vllm] 这个 extra,而 pyproject.toml[project.optional-dependencies] 里我们只找到 streamingtts,没有 vllm 这一项。两处摆在一起就是对不上的,具体影响以仓库最新内容为准。

第二步,验证 server 而不是验证 demo。

curl http://localhost:6001/v1/models

文档给出的预期输出是 {"data": [{ "id": "vibevoice", ... }]}。这个 vibevoice 不是随便起的名字——_build_vllm_cmd() 里写死了 --served-model-name vibevoice

第三步,看 Gradio 自己打印的状态行。

docker exec vibevoice-asr-demo cat /tmp/gradio.log

vllm_plugin/scripts/gradio_asr_demo_api_video.pycreate_gradio_interface() 在启动时会走一遍 api_client.check_health_sync(),然后按结果打印三种字符串之一:连上且拿到模型列表是 ✅ Connected to API: ... | Model: ...;连上但模型列表为空是 ⚠️ Connected but no models found at: ...;健康检查没过是 ⚠️ API not available: ...。这三行的区分度很高,看到哪一行基本就定位了。

这里有个容易踩的细节:文档 Step 2 让你 curl 的是 /v1/models,而 demo 启动时先打的是 /healthcheck_health_sync() 里写明),拿到模型列表用的才是 /v1/modelsget_available_models_sync())。两个端点不是一回事,只 curl 通了 /v1/models 并不构成 demo 那一侧也能连上的证据。VibeVoiceAPIClient.__init__ 里还会把 api_url 做一次 rstrip("/"),并拼出 {api_url}/v1/chat/completions 作为转写端点。

前置条件与参数:逐条核

文档 Prerequisites 一节只列了三条:支持 CUDA 的 GPU、带 GPU 支持的 Docker(nvidia-docker)、以及本地已经 clone 好仓库。但真正容易出事的是命令里的参数配对。

端口。 三个默认值互相不一致,这是本文最想让你记住的一点:start_server.py--port 默认 8000;Gradio 脚本的 --api_url 默认 http://localhost:8000--port 默认 7860;而文档全程用的是 6001。所以文档里的 docker run 既写了 -p 6001:6001,又在 -c 后面显式带了 --port 6001,Gradio 那条命令也显式带了 --api_url http://localhost:6001。这三处必须同时改,漏掉任何一处,Gradio 会去连 8000,然后给你一行 ⚠️ API not available。(以上默认值是仓库当前代码里的取值,随版本可能变动。)

还有一点值得摆出来:文档的 docker run 只发布了 6001,Gradio 默认监听的 7860 并没有映射出去,而文档给的启动命令带了 --share。如果你不想开公网链接,仓库文档里我们没有找到对应的本地访问说明。

挂载与工作目录。 -v $(pwd):/app -w /app 把仓库挂进容器,所以后面所有路径都写成 /app/vllm_plugin/scripts/...docs/vibevoice-vllm-asr.md 特别提示过:待测的音频或视频文件必须放在挂载目录里面。顺便说一个对不上的地方——文档 Step 2 的快速测试命令引用的是 /app/en-Alice_woman.wav,但仓库里我们没有找到这个文件,能找到的是 demo/asr_demo/demo3-hotwords.wav。文件不存在导致的报错跟服务起没起来没有关系,别往那个方向查。

多卡分支。 只有 --dp N(N > 1)才会走 start_dp_server(),那条路径下会先 _install_nginx()、写一份 /tmp/nginx_vllm.conf,然后把后端端口排成 frontend_port + 100 + i。它开头有一句断言,要求可见 GPU 数不少于 dp × tp,不满足会直接抛出来。就绪判定是逐个后端轮询 /v1/models,成功打印 ✅ Backend on port ... is ready,超出重试次数则打印 ❌ Backend on port ... failed to start。另外主循环里任何一个 worker 退出,都会触发 _shutdown 把 nginx 和其余 worker 一起收掉——所以 dp 模式下「整个服务突然没了」,要去日志里找 ❌ Worker ... exited with code。单卡默认路径不走 nginx,怀疑 nginx 之前先确认自己有没有加 --dp

处置:文档与代码给出的做法

  • 日志为空:文档写明 Gradio 会缓冲输出,处置是按文档那样带上 PYTHONUNBUFFERED=1
  • tmux: command not found:先 docker exec <container> apt-get install -y tmux
  • 端口被占:换端口,或者 docker stop <name> && docker rm <name>
  • CUDA out of memory:文档 Troubleshooting 表的写法是换一块卡(device=X)或者在 start_server.py 里降 --gpu-memory-utilization 0.7。这里也有一处对不上——start_server.py 的 argparse 里本来就有 --gpu-memory-utilization 这个参数(仓库当前代码里的默认值是 0.8,随版本可能变动),不必改源码文件;docs/vibevoice-vllm-asr.md 的排障节还提到可以调小 --max-num-seqs--max-model-len
  • --cloudflared 而不是 --sharedownload_cloudflared() 里下载地址写死的是 cloudflared-linux-amd64,落盘路径是 ~/.local/bin/cloudflared,用的是 wget;下载不成它返回 False。上一层的 start_cloudflared_tunnel() 拿到 False 就打印 ❌ Cannot start cloudflared tunnel 并返回 None,而 main() 拿到 None 之后仍然会继续 demo.launch(...)——也就是说隧道失败不会让 demo 退出,你得自己去日志里确认。

另外,main() 里构造 launch_kwargs 时把 themecss 一起传给了 demo.launch(),代码注释写明的理由是 “Gradio 6.0+ moved theme/css to launch()“。这属于仓库自述。

Windows 侧。 仓库文档里的命令是按 Linux/macOS 的 shell 写的:$(pwd)bash -c、以及 --gpus '"device=0"' 这种单双引号嵌套。仓库里我们没有找到 Windows 下的对应写法。通用做法(非该项目官方内容,请自行验证)是把 $(pwd) 换成一个明确的绝对路径再传给 -v,并注意 PowerShell 与 cmd 对引号的处理跟 POSIX shell 不同。

处置后怎么验证

按顺序对三个信号:curl .../v1/models 能拿到 idvibevoice 的条目;docker logs 里出现过 Application startup complete./tmp/gradio.log 里出现 ✅ Connected to API: 开头那一行,以及文档示例里那两行 Running on local URLRunning on public URL。三个都对上了,这条链就算通了。

什么情况说明不是这个原因

  • 状态行已经是 ✅ Connected to API,并且本地 URL 已经打印。 这说明前置条件、端口配对、server 就绪这条链都没问题,再去核 --api_url 是浪费时间,该往浏览器侧、网络侧或上传的文件本身查。
  • 只有上传某个文件时才失败。 脚本里 COMMON_AUDIO_EXTSCOMMON_VIDEO_EXTS 是两个写死的扩展名集合;视频还有大小上限,由 --max_video_size 控制(当前默认 50,单位 MB,随版本可能变动),超了会返回以 ❌ Video file too large 开头的提示。这是单次请求被拒,不是服务起不来。
  • 单卡部署却在查 nginx。 _install_nginx() 与那份 nginx 配置只在 --dp N(N > 1)时才会被执行。
  • 转写结果不合预期。 那跟本文这条启动链无关,属于另一个问题域。

最后提醒一句家族别搞混:这条链路上跑的是 VibeVoice 的 ASR 模型(start_server.py--model 默认值指向 microsoft/VibeVoice-ASR),文档在 docs/vibevoice-vllm-asr.md;实时 TTS 那条线是另外的模型和另外的文档,两边的参数不能互相套用。


本文依据 github.com/microsoft/VibeVoice 仓库与 Hugging Face 模型卡于 2026-08-18 的公开内容整理, 事实来自仓库内的文档与源码。我们没有下载权重、没有跑过推理、也没有做过训练, 因此不涉及显存占用、推理速度、识别准确率与音质的任何描述,也不与其它模型做比较或排名。 该项目持续更新,文中涉及的模块路径、配置字段与接口写法随版本变动,请以仓库最新内容为准。

以上命令与参数组合为按仓库文档中的参数语义组合的示例,未经实测,以仓库最新内容与 --help 的实际输出为准。

文中提到的 TTS 那条线还需补一句状态:仓库 README 记载,2025-09-05 微软因发现有与既定意图不符的使用方式, 基于负责任 AI 原则从该仓库移除了 VibeVoice-TTS 代码;当前 vibevoice/modular/modeling_vibevoice.py 首行注释标明其来自社区 fork,且该模块未被 vibevoice/modular/__init__.py__all__ 导出。 本文只讲本条 ASR 启动链路,不构成 TTS 推理的可用性保证。

仓库 README 的风险与限制一节写明:该模型仅供研究与开发用途, 未经进一步测试与开发不建议用于商业或真实场景,并特别提示了合成语音被用于伪造与虚假信息的风险。 使用合成语音时应遵守所在司法辖区的法律法规,并在分享 AI 生成内容时主动披露。

安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。