VibeVoice-ASR 实战指南:统一模型如何一次完成 60 分钟长音频的转写、说话人分离与时间戳标注
本文以 docs/vibevoice-asr.md 为主线,讲解 VibeVoice 仓库中 VibeVoice-ASR 这一统一语音识别(ASR)模型的核心能力、模型架构与安装使用方法,并结合仓库源码剖析其长音频分块编码、热词上下文注入与结构化 JSON 输出的实现细节。读完本文,你将掌握在 GPU 环境部署 VibeVoice-ASR-7B 的完整流程、两条官方推理路径(Gradio 交互 Demo 与文件批处理推理)的全部关键参数,以及如何准备数据、用 LoRA 微调模型并加载推理。
一、VibeVoice-ASR 是什么
VibeVoice-ASR 是 VibeVoice 开源语音 AI 家族中的自动语音识别模型,官方提供的权重为 VibeVoice-ASR-7B(Hugging Face 上的 microsoft/VibeVoice-ASR,本文命令中使用的 --model_path 即指向它)。与传统 ASR 不同,它把三件通常分离的工作合并到一次前向生成里完成:
- ASR(What):语音转文字;
- 说话人分离(Who):为每段语音标注说话人 ID;
- 时间戳(When):给出每段语音的起止时间。
最终输出是一份结构化转写,说明“谁在什么时候说了什么”,并原生支持自定义热词(Customized Hotwords)与 50 种以上语言,无需显式指定语言,也能处理句内与句间的双语混说(code-switching)。
四大核心特性
官方文档列出的核心特性,逐条对应仓库中的具体实现:
-
60 分钟单次处理(60-minute Single-Pass Processing) 常规 ASR 往往把长音频切成短块分别识别,容易丢失全局上下文。VibeVoice-ASR 在 64K token 长度内接受最长 60 分钟的连续音频输入,保证整个一小时内说话人追踪与语义连贯。从源码看,音频以 24 kHz 采样、语音 token 压缩比为 3200(见 VibeVoiceASRProcessor),即 1 秒音频约 7.5 个语音 token,60 分钟约 27,000 个 token,正好落在 64K 上下文窗口内——这就是“60 分钟一次过”的 token 预算依据。
-
自定义热词(Customized Hotwords) 用户可传入专有名词、人名、术语或背景信息来引导识别,显著提升领域内容准确率。在 Gradio Demo 中这对应
transcribe()的context_info参数;在批量推理脚本中则通过 processor 的context_info字段注入,具体拼接方式见下文“热词如何进入提示词”一节。 -
富转写(Rich Transcription:Who / When / What) 模型联合执行 ASR、说话人分离与时间戳,直接产出结构化输出。模型输出为 JSON,每个片段包含
Start time、End time、Speaker ID、Content四个键,由 post_process_transcription 解析为统一字段。 -
多语言与代码切换(Code-Switching) 支持 50 种以上语言,不需要显式语言设置,并在语料层面覆盖了多语言分布(见原文档中的 Language Distribution 图)。官方还配套了 vLLM 加速推理文档 与 流式识别文档,分别解决高并发服务与“边听边转写”两类场景。
二、模型架构与内部数据流
上图为 VibeVoice-ASR 的架构图:语音经声学/语义两条 token 化通路变成嵌入,与文本 token 一起送入基于 Qwen2.5 的语言模型,以自回归方式生成 JSON 转写。结合 modeling_vibevoice_asr.py 可以确认几个关键结构:
- 语言模型(decoder):
VibeVoiceASRModel用AutoModel.from_config加载语言模型主干,并挂接acoustic_tokenizer(声学 VAE 编码器)、semantic_tokenizer(语义编码器)以及两个SpeechConnector(把 speech 特征投影到语言模型 hidden size); - 语音编码入口
encode_speech():输入[batch, samples]的 24 kHz 波形。对短音频,直接走acoustic_tokenizer.encode()采样出 token 再经 connector 投影;当音频长度超过分段时长(默认 60 秒)时,从源码结构看会启用流式分段编码——按 60 秒切片,借助VibeVoiceTokenizerStreamingCache维护跨块卷积缓存,逐段编码后拼接,从而避免超长波形一次性过卷积带来的内存与数值问题(见 encode_speech); - 特征回填:模型 forward 时,processor 生成的
acoustic_input_mask标出输入序列中<|speech_pad|>占位 token 的位置,编码出的语音特征直接覆写进inputs_embeds(inputs_embeds[acoustic_input_mask] = speech_features),随后与系统/用户文本 token 一起进入语言模型做自回归生成。
这条“占位 token + 掩码回填”的设计,让语音特征在 token 序列里拥有与文本相同的位置语义,也为长音频提供了在提示词中精确表达时长信息的基础。
三、输入是如何被处理的:采样率、压缩比与热词提示词
安装和使用前,理解输入侧约定能帮你正确准备音频。VibeVoiceASRProcessor 的关键约定:
| 约定 | 取值 | 说明 |
|---|---|---|
目标采样率 target_sample_rate |
24000 Hz | 非 24 kHz 音频会被 resample 到 24 kHz |
语音 token 压缩比 speech_tok_compress_ratio |
3200 | 1 秒音频 ≈ 7.5 个语音 token;占位 token 数按 ceil(samples / 3200) 计算 |
音频归一化 normalize_audio |
True,目标响度 -25 dBFS | AudioNormalizer 先按 RMS 调整到目标 dBFS,再防削波 |
| 音频解码 | ffmpeg 优先,soundfile 兜底 | load_audio_use_ffmpeg 用 ffprobe 探测采样率并转单声道 PCM;COMMON_AUDIO_EXTS 定义了支持的格式(mp3/m4a/mp4/wav/m4v/aac/ogg/mov/opus/m4b/flac/wma/rm/3gp/mpeg/flv/webm/mp2/aif/aiff/oga/ogv/mpga/m3u8/amr 等) |
提示词构造同样值得注意(_process_single_audio):
- 系统提示固定为
You are a helpful assistant that transcribes audio input into text output in JSON format.; - 用户输入形如
<|speech_start|><|speech_pad|>×N<|speech_end|>\n+ 一段说明文本,其中 N 为语音 token 数,说明文本为This is a {时长:.2f} seconds audio, please transcribe it with these keys: Start time, End time, Speaker ID, Content; - 热词注入点:当传入
context_info时,说明文本变为This is a {时长:.2f} seconds audio, with extra info: {context_info}\n\nPlease transcribe it with these keys: ...——即热词/背景信息以自然语言形式拼进用户提示词,而不是走声学前端,这解释了为什么任意专有名词都能“即插即用”。
四、安装:Docker + pip
官方推荐用 NVIDIA Deep Learning Container 管理 CUDA 环境(文档验证范围:PyTorch 容器 24.07 ~ 25.12,更早版本也兼容):
# 1. 启动 NVIDIA PyTorch 容器
sudo docker run --privileged --net=host --ipc=host --ulimit memlock=-1:-1 --ulimit stack=-1:-1 --gpus all --rm -it nvcr.io/nvidia/pytorch:25.12-py3
# 若容器内没有 flash attention,需要手动安装:
# pip install flash-attn --no-build-isolation
# 2. 从 GitHub 克隆并安装
git clone https://github.com/microsoft/VibeVoice.git
cd VibeVoice
pip install -e .
从两份推理脚本的依赖行为看,运行环境还需注意:
- 批量推理脚本对音频解码依赖 ffmpeg(Gradio Demo 文档也明确要求
apt install ffmpeg); - 注意力实现按设备自动选择:CUDA 且装有
flash_attn时用flash_attention_2,否则回退sdpa;MPS/CPU/XPU 一律sdpa,且权重精度用float32(CUDA 用bfloat16),见 device 检测逻辑。
五、使用方法
用法 1:启动 Gradio 交互 Demo
apt update && apt install ffmpeg -y # demo 需要 ffmpeg
python demo/vibevoice_asr_gradio_demo.py --model_path microsoft/VibeVoice-ASR --share
Gradio Demo(demo/vibevoice_asr_gradio_demo.py)适合快速验证与体验,源码中可以看到它提供的完整交互能力:
- 输入:上传音频文件、填入音频路径,或直接用麦克风录制;支持
start_time/end_time参数按秒或hh:mm:ss截取片段; - 热词:
context_info输入框支持填入人名、术语、主题句等,透传给transcribe(context_info=...); - 生成参数:
max_new_tokens(Demo 默认 8192)、temperature(0 即贪心解码)、top_p、do_sample、repetition_penalty; - 流式输出:通过
TextIteratorStreamer在后台线程生成、主协程逐 token 增量展示,并支持“停止”按钮(自定义StopOnFlag停止条件); - 结果展示:原始 JSON 输出 + 解析后的分段列表(时间区间、说话人、文本),并按段时间戳切出每段可播放的小音频(16 kHz 单声道、约 32 kbps MP3,依赖
pydub,缺失时退回 WAV)。
输入 token 统计(speech/text/padding 三类占比)也会随结果打印,方便核对 60 分钟音频的 token 占用。
用法 2:对文件直接做批量推理
python demo/vibevoice_asr_inference_from_file.py \
--model_path microsoft/VibeVoice-ASR \
--audio_files /path/to/audio1.mp3 /path/to/audio2.wav
批量推理脚本 面向批处理场景,除文档给出的两条基础命令外,完整参数(默认值来自源码 argparse)如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
--model_path |
空(必填其一) | 模型检查点路径或 Hugging Face 名称 |
--audio_files |
无 | 一个或多个音频文件路径 |
--audio_dir |
无 | 目录批量转写,按 COMMON_AUDIO_EXTS 过滤支持的格式 |
--dataset / --split |
无 / test |
从 Hugging Face 数据集(如 openslr/librispeech_asr)流式拉取短音频并拼接成约 1 小时的长音频用于演示(需另装 datasets、torchcodec,仅演示用途,不用于评测) |
--max_duration |
3600.0 | 拼接长音频的目标时长(秒) |
--batch_size |
2 | 批量处理大小,transcribe_with_batching 按该大小分块送入模型 |
--device |
自动(cuda/xpu/mps/cpu 探测) | 也支持 auto 多卡自动分配 |
--max_new_tokens |
32768 | 60 分钟音频的长转写需要较大的生成上限 |
--temperature |
0.0 | 为 0 时强制贪心解码(do_sample = temperature > 0) |
--top_p |
1.0 | 核采样阈值(仅采样时生效) |
--num_beams |
1 | >1 时切到束搜索并自动关闭采样 |
--attn_implementation |
auto |
可选 flash_attention_2 / sdpa / eager / auto,auto 下 CUDA 且装了 flash_attn 时优先 flash_attention_2 |
每个样本的输出包含三部分:raw_text(模型原始 JSON 文本)、segments(经 post_process_transcription 解析出的结构化片段:start_time / end_time / speaker_id / text)与 generation_time。解析逻辑支持 ```json 代码块包裹或直接数组/对象两种形态,并做键名归一化(Start/End/Speaker 等别名统一映射),解析失败时安全降级为空列表而不抛错(post_process_transcription)。
六、基准测试与多语言结果
官方文档给出三项指标的对比图(说话人分离 DER、带说话人错误 cpWER、带说话人+时间戳错误 tcpWER):
| DER(说话人分离) | cpWER | tcpWER |
|---|---|---|
![]() |
![]() |
![]() |
多语言基准(MLC-Challenge,11 语种)与会议场景基准(DER / cpWER / tcpWER / WER,数值越低越好):
| 数据集 | 语言 | DER | cpWER | tcpWER | WER |
|---|---|---|---|---|---|
| MLC-Challenge | English | 4.28 | 11.48 | 13.02 | 7.99 |
| MLC-Challenge | French | 3.80 | 18.80 | 19.64 | 15.21 |
| MLC-Challenge | German | 1.04 | 17.10 | 17.26 | 16.30 |
| MLC-Challenge | Italian | 2.08 | 15.76 | 15.91 | 13.91 |
| MLC-Challenge | Japanese | 0.82 | 15.33 | 15.41 | 14.69 |
| MLC-Challenge | Korean | 4.52 | 15.35 | 16.07 | 9.65 |
| MLC-Challenge | Portuguese | 7.98 | 29.91 | 31.65 | 21.54 |
| MLC-Challenge | Russian | 0.90 | 12.94 | 12.98 | 12.40 |
| MLC-Challenge | Spanish | 2.67 | 10.51 | 11.71 | 8.04 |
| MLC-Challenge | Thai | 4.09 | 14.91 | 15.57 | 13.61 |
| MLC-Challenge | Vietnamese | 0.16 | 14.57 | 14.57 | 14.43 |
| 数据集 | 语言 | DER | cpWER | tcpWER | WER |
|---|---|---|---|---|---|
| AISHELL-4 | Chinese | 6.77 | 24.99 | 25.35 | 21.40 |
| AMI-IHM | English | 11.92 | 20.41 | 20.82 | 18.81 |
| AMI-SDM | English | 13.43 | 28.82 | 29.80 | 24.65 |
| AliMeeting | Chinese | 10.92 | 29.33 | 29.51 | 27.40 |
| MLC-Challenge | Average | 3.42 | 14.81 | 15.66 | 12.07 |
语种覆盖方面,原文档附有一张 50+ 语言的训练分布图 language_distribution_horizontal.png,可据此查看各语言语料占比。
七、LoRA 微调:领域适配与热词增强
原文档指出 VibeVoice-ASR 支持 LoRA(Low-Rank Adaptation)微调,详细指引见 finetuning-asr/README.md。结合该目录与仓库结构,要点如下:
数据格式:音频文件与同名 JSON 标注放在同一目录(如 0.mp3 + 0.json)。JSON 结构与推理输出的“Who/When/What”一一对应:
{
"audio_duration": 351.73,
"audio_path": "0.mp3",
"segments": [
{ "speaker": 0, "text": "Hey everyone, welcome back...", "start": 0.0, "end": 38.68 },
{ "speaker": 1, "text": "Thanks for having me...", "start": 38.75, "end": 77.88 }
],
"customized_context": ["Tea Brew", "Aiden Host", "The property is near Meter Street."]
}
其中 customized_context 为可选字段,即领域术语或背景句,训练时通过 --use_customized_context(默认 True)拼入上下文——与推理端 context_info 热词机制形成训练/推理闭环。注意仓库自带的 toy_dataset/ 是由 VibeVoice TTS 生成的合成音频,仅作格式演示,正式微调应准备真实录音与准确转写。
训练命令(1 卡与多卡两种写法):
# 1 GPU
torchrun --nproc_per_node=1 lora_finetune.py \
--model_path microsoft/VibeVoice-ASR \
--data_dir ./toy_dataset \
--output_dir ./output \
--num_train_epochs 3 \
--per_device_train_batch_size 1 \
--learning_rate 1e-4 \
--bf16 \
--report_to none
# 指定 GPU 0,1,2,3
CUDA_VISIBLE_DEVICES=0,1,2,3 torchrun --nproc_per_node=4 lora_finetune.py \
--model_path microsoft/VibeVoice-ASR \
--data_dir ./toy_dataset \
--output_dir ./output \
--num_train_epochs 3 \
--per_device_train_batch_size 1 \
--learning_rate 1e-4 \
--bf16 \
--report_to none
关键 LoRA 参数(脚本基于 HuggingFace TrainingArguments,其余标准参数均可用):
| 参数 | 默认值 | 说明 |
|---|---|---|
--lora_r |
16 | LoRA 秩,越小参数越少,越大表达力越强 |
--lora_alpha |
32 | LoRA 缩放因子(通常取秩的 2 倍) |
--lora_dropout |
0.05 | LoRA 层 dropout |
--per_device_train_batch_size |
8 | 单卡批大小(长音频场景常需调小到 1) |
--gradient_accumulation_steps |
1 | 有效批大小 = 批大小 × 累积步数 |
--learning_rate |
5e-5 | LoRA 常用 1e-4 ~ 2e-4 |
--gradient_checkpointing |
False | 开启以降低显存占用 |
--use_customized_context |
True | 是否把 JSON 中的 customized_context 作为额外上下文 |
--max_audio_length |
None | 超过该时长(秒)的音频跳过训练 |
依赖方面,先 pip install -e . 再 pip install peft。微调后用 inference_lora.py 验证:
python inference_lora.py \
--base_model microsoft/VibeVoice-ASR \
--lora_path ./output \
--audio_file ./toy_dataset/0.mp3 \
--context_info "Tea Brew, Aiden Host"
如需合并权重获得更快的推理,可按 README 给出的方式用 PeftModel.from_pretrained 加载后调用 merge_and_unload() 并 save_pretrained 保存为独立模型目录。
八、许可与相关资源
项目整体采用 MIT License 授权(见 LICENSE)。
延伸阅读建议(均在当前仓库内):
- 部署加速:docs/vibevoice-vllm-asr.md 介绍 vLLM 服务化推理;vllm_plugin/ 下有配套插件与 API 测试脚本;
- 流式识别:docs/vibevoice-asr-streaming.md 描述“边听边转写”的流式 ASR 变体;
- Gradio 部署细节:docs/setup_gradio_demo.md。
再次强调适用前提:长音频(60 分钟级)单次转写建议放在 GPU 上以 bfloat16 运行并优先使用 flash-attention;CPU/MPS 环境脚本会自动切换 float32 + sdpa,但显存与耗时预算会显著变化,请据此规划数据量与 max_new_tokens 设置。
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 StartedRust0623
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



