跳转至

VibeVoice vLLM 流式 ASR 部署

Huggingface

使用 vLLM 将 VibeVoice ASR 流式模型部署为高性能 API 服务。会话在音频尚未说完时持续推送音频,每个分块返回一条转写文本,因此文字会在音频结束前出现。

非流式: vLLM-asr

🔥 Key Features

  • 🎤 真流式转写:从实时麦克风或不断增长的音频流中逐块转写
  • 🚀 前缀缓存会话:每个分块复用之前所有分块的 KV 缓存,因此随着会话增长,成本保持平稳
  • 📡 WebSocket + REST:/v1/stream 用于实时音频,/v1/transcribe 和 /v1/chat/completions 用于完整文件
  • 🔌 插件架构:无需修改 vLLM 源代码——只需安装并运行
  • 🎚️ 由检查点定义的分块:分块和前瞻窗口均从检查点读取,因此模型始终以训练时的几何配置运行

🛠️ 安装

使用官方 vLLM Docker 镜像(推荐)

  1. 克隆仓库

    git clone https://github.com/microsoft/VibeVoice.git
    cd VibeVoice
    

  2. 启动服务器(后台模式)

    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
  1. 查看日志
    docker logs -f vibevoice-vllm-streaming
    

注意: - -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"

对于不进行流式传输的调用方,也可以使用整文件端点:

docker exec -it vibevoice-vllm-streaming python3 vllm_plugin/tests/test_api.py /app/audio.wav

注意: - 音频/视频文件必须位于挂载目录(容器中的 /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"

隧道建立后会打印链接:

docker logs vibevoice-vllm-streaming-demo
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 确实意味着不受限。

📊 性能提示

  1. GPU 内存:如果你有专用 GPU,使用 --gpu-memory-utilization 0.9 可获得最大吞吐量
  2. 会话长度:--max-model-len 决定单个会话可运行多长时间;处理长达一小时的流时请调高它
  3. 并发会话:在提高并发之前先调大 --mm-processor-cache-gb——它必须容纳所有进行中会话的音频窗口

🚨 故障排除

常见问题

  1. "CUDA out of memory"
  2. 调低 --gpu-memory-utilization
  3. 调低 --mm-processor-cache-gb
  4. 使用更小的 --max-model-len

  5. "is not a streaming checkpoint"

  6. 检查点的 preprocessor_config.json 中没有 chunk_frames
  7. 改用 start_server.py 来提供服务

  8. "tokenizer layout mismatch"

  9. <|text_chunk_end|> 缺失或位于另一个 id,导致永远无法结束一个分块。服务器会拒绝启动,而不是先服务第一个分块之后又返回空分块
  10. 重新生成:python3 -m vllm_plugin.tools.generate_tokenizer_files --output MODEL_PATH --streaming

  11. "Cache miss" 或会话在多个分块之后停滞

  12. 调高 --mm-processor-cache-gb,或降低并发会话数量

  13. "Plugin not loaded"

  14. 验证安装:pip show vibevoice
  15. 检查入口点:pip show -f vibevoice | grep entry

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vib/VibeVoice