VibeVoice-ASR 实战指南:统一模型如何一次完成 60 分钟长音频的转写、说话人分离与时间戳标注
【免费下载链接】VibeVoiceOpen-Source Frontier Voice AI项目地址: https://gitcode.com/GitHub_Trending/vib/VibeVoice
本文以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 --shareGradio 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 参数(脚本基于 HuggingFaceTrainingArguments,其余标准参数均可用):
| 参数 | 默认值 | 说明 |
|---|---|---|
--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设置。
【免费下载链接】VibeVoiceOpen-Source Frontier Voice AI项目地址: https://gitcode.com/GitHub_Trending/vib/VibeVoice
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考