WhisperX 实战:一条命令把多人混音录音,变成带说话人标签的词级字幕
【免费下载链接】whisperXWhisperX: Automatic Speech Recognition with Word-level Timestamps (& Diarization)项目地址: https://gitcode.com/gh_mirrors/wh/whisperX
上周我帮朋友处理一段 58 分钟的三方访谈录音,他的需求很朴素:"把每个人的话分开,最好字幕能直接看到谁在说"。我原本以为只是转写,结果发现市面上大多数工具只能给出一整段没有断句的文本,时间戳还经常偏出好几秒。直到我把 WhisperX(一个主打词级时间戳 + 说话人分离的开源语音识别项目)跑起来,第一次看到输出文件里每句话前都顶着[SPEAKER_00]、[SPEAKER_01]这样的标签,才意识到:音频处理的正确打开方式,应该是"让声音自己说出是谁在讲"。
这篇文章不打算复述官方文档,而是想用我真实趟过的流程,带你从一条命令出发,看 WhisperX 的说话人识别(Speaker Diarization)和词级时间戳是怎么工作的,以及它在会议、访谈、播客三种场景下分别能帮你省下多少事。
先看效果:58 分钟混音录音,五分钟出结果
在讲任何原理之前,先看这个项目能交付什么。运行下面的命令(注意--diarize就是打开说话人分离的关键开关):
python -m whisperx interview.wav --model medium --diarize --min_speakers 2 --max_speakers 3 --output_format srt工作目录下会多出几个文件,其中interview.srt长这样:
1 00:00:01,120 --> 00:00:04,380 [SPEAKER_00] 大家好,欢迎来到今天的访谈,先请嘉宾做个自我介绍。 2 00:00:04,620 --> 00:00:09,910 [SPEAKER_01] 谢谢主持人,我是做语音交互产品的,今天主要想聊聊…… 3 00:00:10,030 --> 00:00:15,470 [SPEAKER_02] 我这边补充一点,从工程角度讲这个方案的坑主要在……几件事值得注意:每一句都精确到了词级的时间戳(精确到零点几秒),每一句都被自动分配了说话人编号,而且字幕本身就是标准的 SRT 格式,能直接拖进剪辑软件或播放器。下面这张图就是 WhisperX 处理一条音频的完整流水线:从原始波形进去,经过 VAD 语音检测、裁剪合并、批量填充,再到 Whisper 转写和音素级强制对齐,最终输出带词级时间戳的转录结果。
如果你在跑这个命令时被提醒缺少说话人分离模型,只需要把--hf_token参数补上(后面安装章节会专门讲)。
为什么"能转写"和"会说话人分离"差着一个量级
很多人一开始想不通:OpenAI 的 Whisper 不是已经能转写了吗?为什么还要 WhisperX?这里有个关键的认知差:
- Whisper 的时间戳是"句子级"的。它给出的是每个文本块的大致起止时间,块内单词的时间位置并不精确,有时会整体偏移好几秒。拿去做字幕卡点,你会被逼疯。
- Whisper 是单说话人假设。它会老老实实把两三个人交替的对话当成一段连续文本转出来,完全不区分"这句是谁说的"。
- Whisper 原生不支持批量推理。长音频只能一段段串行处理,速度上不去。
WhisperX 做的不是"另一个转写模型",而是在 Whisper 外面套了一条完整的后处理流水线,把上面三个短板一次性补上:
| 痛点 | Whisper 原生 | WhisperX |
|---|---|---|
| 时间戳精度 | 句子级,偏差可达数秒 | 词级,基于 wav2vec2 强制对齐 |
| 多说话人 | 混成一团 | pyannote 说话人分离,输出 SPEAKER_x 标签 |
| 速度 | 串行推理 | faster-whisper 后端 + 批量推理,large-v2 可达约 70 倍实时速度 |
| 幻觉抑制 | 长静音段易编造文本 | VAD 先切掉无声段,从源头减少幻觉 |
其中"70 倍实时"指的是:1 小时的音频,在 GPU 上大约 1 分钟出头能跑完。这个数字的前提是使用 large-v2 模型、beam_size=5、显存低于 8GB,且模型缓存已加载完毕——如果你用的是 CPU 或者小模型,速度会打折,但"快"这个方向没错。
拆开看流水线:一次转写背后发生的四件事
想用好一个工具,最好先知道它在你按下回车后干了什么。WhisperX 的完整流程可以分成四步,对应着源码里四个模块:
第一步:VAD 语音检测(whisperx/vad.py)。先用 VAD(语音活动检测)把音频里"有人说话"和"安静"的区间切出来。这一步有两个作用:跳过无声段避免 Whisper 在长静音上产生幻觉;同时把语音段整理成规整的片段,为下一步的批量推理做准备。如果发现语音没被识别出来,可以调低--vad_onset(默认 0.500)。
第二步:Whisper 批量转写(whisperx/transcribe.py)。把上一步切好的语音片段批量喂给 Whisper 模型做识别。注意这里用的是 faster-whisper 作为后端,并且默认关闭了--condition_on_previous_text(让前文影响后文预测的机制),这是减少错误级联和幻觉的刻意设计。
第三步:强制对齐(whisperx/alignment.py)。Whisper 给出的时间戳不精确,所以 WhisperX 会引入一个音素级模型(如 wav2vec2),把转写文本"硬怼"回音频波形上,通过动态规划在时间轴上找到每个字/词最可能的起止位置。这一步输出的是带词级时间戳的精确结果——这是 SRT 字幕能逐词卡点的根基。对于中英文等空格语言,模型会自动按空格分词;对日文、中文这类不分词的语言,也做了单独处理(源码里有个LANGUAGES_WITHOUT_SPACES列表)。
第四步:说话人分离(whisperx/diarize.py)。pyannote 的说话人分离模型先把整段音频按"声音特征"分成若干片段,然后assign_word_speakers函数把这些片段和上一步的转写结果做"时间重叠度"匹配。核心逻辑不复杂:计算每个说话人片段和每个转录句子的时间交集,谁的累计重叠时长最长,这句话就归谁。如果你发现分配得不准,可以试试fill_nearest=True(源码里预留了这个开关),它会允许在完全没有重叠时也强行找最近的那个说话人。
看到这里你会发现,WhisperX 与其说是一个转写工具,不如说是一条把"转写—对齐—分离"串起来的装配线,每一环都替换掉了 Whisper 原生的弱项。
动手前先把环境备齐:三个必做动作
项目建议在 Python 3.10 + PyTorch 2.0 的环境下运行。推荐用 conda 隔离环境,避免污染系统 Python:
git clone https://gitcode.com/gh_mirrors/wh/whisperX cd whisperX conda create --name whisperx python=3.10 -y conda activate whisperx conda install pytorch==2.0.0 torchaudio==2.0.0 pytorch-cuda=11.8 -c pytorch -c nvidia pip install -e .如果你是老手,想直接用稳定版本,也可以跳过 clone,直接pip install whisperx,效果一样。
另外还有两件容易踩坑的事,提前说清楚:
- ffmpeg 必须装。音频加载依赖它,少了会在
load_audio那一步直接报错。 - 说话人分离模型需要 Hugging Face Token。pyannote 的
speaker-diarization-3.1是门控模型,需要你先去 HF 官网生成一个 read 权限的 Access Token,并同意模型使用协议,然后通过--hf_token传入,或把它保存到环境变量里。没这个 token,--diarize会加载失败——这是新手最常卡住的地方。
装好后,先用项目自带的一句示例快速验证通不通:python -m whisperx 你的音频.wav(不带--diarize,先把转写链路跑通)。
三个真实场景,三种打开方式
同一套命令行,放在不同业务里,用法完全不同。下面三个场景覆盖了最常见的需求。
场景一:周会录音,一分钟生成"分人会议纪要"
会议录音通常是 2~6 个人来回抢话,最烦的是事后听录音找"到底是谁拍板的"。这时可以给模型一个说话人数量范围,让分离更稳定:
python -m whisperx meeting_20241028.wav --model medium --diarize --min_speakers 3 --max_speakers 5 --output_format srt,txt --highlight_words True--min_speakers 3 --max_speakers 5是告诉分离模型"这屋里大概三到五个人",比让它自己猜准得多;--highlight_words True会让 SRT 字幕逐词高亮,方便视频剪辑时对嘴型。输出的 txt 文件里同样带[SPEAKER_x]前缀,直接丢给 AI 模型让它"按说话人归纳要点",一份会议纪要就出来了。
场景二:访谈音频,精准捞出某位嘉宾的所有发言
做内容运营的朋友最想要的是"某位嘉宾的全部金句"。WhisperX 的 JSON 输出把说话人信息结构化存了下来,你只需要一个 grep:
python -m whisperx interview.wav --model large --diarize --output_format json python -c "import json;d=json.load(open('interview.json'));print('\n'.join(s['text'] for s in d['segments'] if s.get('speaker')=='SPEAKER_01'))"一句话就把 SPEAKER_01 的所有发言捞出来,后面接剪辑脚本就能自动生成"嘉宾金句集锦"视频。注意:这里换成了large模型,因为--model large在非英语和复杂语音场景下的识别准确率更高(访谈多为单人轮流说话,比会议更考验转写质量)。
场景三:播客长音频,把性能榨干
播客动辄一两小时,最关心的是速度。如果你的机器有 N 卡,按这个组合来:
python -m whisperx episode_089.wav --model large-v2 --diarize --device cuda --batch_size 16 --compute_type float16--device cuda:强制走 GPU;--batch_size 16:批量推理的核心参数,显存够就往上加(显存不够就降到 4);--compute_type float16:半精度计算,又快又省显存。
如果只有 CPU(或 Mac),把--device cuda换成--compute_type int8即可,速度和显存都友好,代价是识别精度略有下降。
踩坑记录:四个我替你先趟过的坑
把实践中遇到的典型问题按"症状 → 解法"列出来,能帮你少走弯路:
- 说话人认成一个人,或者来回乱跳→ 多半是没给数量范围。先听一遍音频数人头,然后用
--min_speakers N --max_speakers N锁定(已知确切人数时两个参数传相同值效果最好)。 - 静音段被幻觉填词→ 检查 VAD 是否生效,尝试调低
--vad_onset(比如 0.3),让更多弱语音被保留、更长的静音被切除。 - "2014."、"£13.60"这类文本没有时间戳→ 这是已知限制:wav2vec2 对齐模型只认识字典里的字符,数字和特殊符号无法对齐,源码对此的处置是跳过并保留原时间。遇到这种情况,要么接受,要么在转写前把这类文本规范化。
- GPU 显存爆掉(OOM)→ 按优先级依次尝试:降
--batch_size到 4、换小模型(--model base)、换--compute_type int8。README 里明确给了这三步降显存方案。
另外要提前管理好预期:重叠说话(两个人同时开口)是 Whisper 系模型的通病,WhisperX 也不擅长;说话人分离也远非完美,多说话人快速抢话的场景偶尔会标错人。它解决的是"把 80% 的整理工作自动化",而不是 100% 的绝对正确。
语言支持:它不只是个英文工具
如果你是做多语言内容的,这个细节很加分:WhisperX 会根据检测到的语言自动挑选对应的音素对齐模型,无需手动配置。目前开箱即用地支持英语、法语、德语、西班牙语、意大利语、日语、中文、荷兰语、乌克兰语、葡萄牙语这十种语言的对齐(见 whisperx/alignment.py 里的默认模型表),俄语、韩语、越南语、印地语等更多语言也都能通过指定模型路径用起来。
非英语场景记得用大模型,README 和 EXAMPLES.md 里的官方建议都是"非英语 ASR 请使用--model large"。例如德语:
python -m whisperx --model large-v2 --language de podcast_de.wav --diarize参数列表的完整说明都集中在 whisperx/transcribe.py 的 argparse 部分,想深度定制(比如字幕换行宽度、--segment_resolution按句子还是按块切分)都可以在那里找到出处。
收个尾:从"听录音"到"读录音"
回到开头那位朋友。他最后拿到的不只是一份转写文本,而是一份每句话都标了谁说的、每个字都有精确时间点的结构化数据。他说自己最直观的感受是:"以前整理一次访谈要听三遍,现在一遍都不用听。"这句话或许有点夸张,但方向是对的——WhisperX 真正改变的是工作方式:你不必再被动地"听"录音,而是可以主动地"检索"它。
现在就把那条 58 分钟的访谈录音找出来,跑一遍第一条命令。五分钟之后你会看到,混音录音里每个人说的话,终于各自找到了自己的名字。
【免费下载链接】whisperXWhisperX: Automatic Speech Recognition with Word-level Timestamps (& Diarization)项目地址: https://gitcode.com/gh_mirrors/wh/whisperX
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考