先把当时的情况摆出来。用 faster-whisper 1.0.3 的 large-v3 转写 40 分钟双人访谈,输入是 16k 单声道 wav,输出只有一整段文本加时间戳,谁说的分不出来,客户要求按发言人标注。

排查方向其实有限,先把可能性排一排。Whisper 本身只做语音识别,说话人分离要另接 diarization 模型。另一种情况是VAD 默认把短于 500ms 的静音并掉,两人抢话的边界直接消失。

不容易想到的是,没有开 word_timestamps,识别结果无法和说话人时间轴对齐。还有一种情况,长时间音频一次性送进去,模型内部的 30 秒窗口切在句中。

上来先确认识别输出里到底有哪些字段

python -c "from faster_whisper import WhisperModel;m=WhisperModel('large-v3',device='cuda',compute_type='float16');s,_=m.transcribe('meeting.wav',word_timestamps=True);print(next(iter(s))._asdict().keys())"

随后跑说话人分离拿到带时间轴的 rttm

python -c "from pyannote.audio import Pipeline;p=Pipeline.from_pretrained('pyannote/speaker-diarization-3.1');print(p)"

然后把两份时间轴合并成带发言人标签的字幕

python merge_speaker.py --asr asr.json --diar diar.rttm --out labeled.srt

等前面都确认过,再抽一段人工试听核对标签

ffmpeg -ss 00:12:30 -t 20 -i meeting.wav clip.wav

别只看报错消失,验证要多做一步。labeled.srt 里每句都带 SPEAKER_00 或 SPEAKER_01,抽查三段切换点与人工试听一致,句子总数不少于识别段数。

补一句。分离模型要 HF token 且同样吃显存,40 分钟音频按十分钟切段跑,别让它和 ASR 同时抢同一张卡。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189