首页
/ VibeVoice-ASR 实战指南:统一模型如何一次完成 60 分钟长音频的转写、说话人分离与时间戳标注

VibeVoice-ASR 实战指南:统一模型如何一次完成 60 分钟长音频的转写、说话人分离与时间戳标注

2026-09-05 15:48:39作者:董斯意

本文以 docs/vibevoice-asr.md 为主线,讲解 VibeVoice 仓库中 VibeVoice-ASR 这一统一语音识别(ASR)模型的核心能力、模型架构与安装使用方法,并结合仓库源码剖析其长音频分块编码、热词上下文注入与结构化 JSON 输出的实现细节。读完本文,你将掌握在 GPU 环境部署 VibeVoice-ASR-7B 的完整流程、两条官方推理路径(Gradio 交互 Demo 与文件批处理推理)的全部关键参数,以及如何准备数据、用 LoRA 微调模型并加载推理。

VibeVoice ASR 模型架构

一、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)。

四大核心特性

官方文档列出的核心特性,逐条对应仓库中的具体实现:

  1. 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 预算依据。

  2. 自定义热词(Customized Hotwords) 用户可传入专有名词、人名、术语或背景信息来引导识别,显著提升领域内容准确率。在 Gradio Demo 中这对应 transcribe()context_info 参数;在批量推理脚本中则通过 processor 的 context_info 字段注入,具体拼接方式见下文“热词如何进入提示词”一节。

  3. 富转写(Rich Transcription:Who / When / What) 模型联合执行 ASR、说话人分离与时间戳,直接产出结构化输出。模型输出为 JSON,每个片段包含 Start timeEnd timeSpeaker IDContent 四个键,由 post_process_transcription 解析为统一字段。

  4. 多语言与代码切换(Code-Switching) 支持 50 种以上语言,不需要显式语言设置,并在语料层面覆盖了多语言分布(见原文档中的 Language Distribution 图)。官方还配套了 vLLM 加速推理文档流式识别文档,分别解决高并发服务与“边听边转写”两类场景。

二、模型架构与内部数据流

上图为 VibeVoice-ASR 的架构图:语音经声学/语义两条 token 化通路变成嵌入,与文本 token 一起送入基于 Qwen2.5 的语言模型,以自回归方式生成 JSON 转写。结合 modeling_vibevoice_asr.py 可以确认几个关键结构:

  • 语言模型(decoder)VibeVoiceASRModelAutoModel.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_embedsinputs_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_ffmpegffprobe 探测采样率并转单声道 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_pdo_samplerepetition_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 小时的长音频用于演示(需另装 datasetstorchcodec,仅演示用途,不用于评测)
--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
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)。

延伸阅读建议(均在当前仓库内):

再次强调适用前提:长音频(60 分钟级)单次转写建议放在 GPU 上以 bfloat16 运行并优先使用 flash-attention;CPU/MPS 环境脚本会自动切换 float32 + sdpa,但显存与耗时预算会显著变化,请据此规划数据量与 max_new_tokens 设置。

登录后查看全文
热门项目推荐
相关项目推荐