自部署会议转写:从音频到说话人字幕
教程使用 Nemotron 3.5 Transcribe,通过 vLLM 和兼容 OpenAI 的客户端生成带说话人标记的笔记及 SRT 字幕,并介绍音频预处理。作者验证了预处理、模拟服务调用和输出格式,GPU 部署命令引用自模型卡,未实际验证。
AI 深度解读
一段会议录音,往往要经过转写、区分说话人、翻译、时间对齐,才能变成可用的纪要或字幕。Nvidia 的 Nemotron 3.5 Transcribe 试图把这些能力放进同一个开放权重模型,用提示词切换任务,减少多套工具之间的衔接。
这篇教程的价值在于把部署条件和验证边界讲得比较清楚:作者跑通了音频预处理、客户端和输出转换,但没有 GPU,模型服务与识别效果并未实测。对准备自建会议转写服务的开发者,它是一份接入路线,尚不能充当选型结论。
一个模型接多种任务,省掉了哪些麻烦
按原文介绍,Nvidia 于 2026 年 10 月 28 日发布 Nemotron 3.5 Transcribe。它用音频编码器连接混合 Mamba-Transformer 的混合专家模型(MoE),总参数 34B,每个 token 约激活 4.3B 参数,上下文为 65,536 token,支持最长一小时录音。
同一段音频,可以按指令生成逐字稿、去除口头语的可读稿、带说话人标签的文本,也可以用于翻译和音频问答。原文给出的范围是:转写覆盖 40 种语言,英语与另外 31 种语言之间支持翻译,单段录音最多标记八位说话人;权重采用允许商用的 OpenMDW-1.1 许可证。
整合的好处容易理解:过去几个模型分别处理文字、说话人和时间,输出边界可能对不上。放进同一条服务路径后,应用层需要协调的结果更少。
但说话人标签只是区分录音中的声音。spk:0 不代表某个真实身份,分段请求之后也不能直接沿用人物对应关系。
任务指令也有明确约束:转写和翻译保持 system prompt 为空,将要求写在用户消息里;使用 temperature=0,关闭 reasoning。专业词汇可以通过 Context terms: <names and terms> 提供,适合加入产品名和内部术语,但原文没有给出它能改善多少准确率的对照数据。
要说话人和时间轴,部署路线就不能随便选
教程选择 vLLM,因为原文列出的完整功能组合依赖这条路线。SGLang-Omni 虽然安装更简单,但不支持词级时间戳、说话人归属输出、翻译或推测解码;直接使用 Hugging Face Transformers,则缺少这里的服务优化和时间戳中间件。
硬件也有限定:参考配置是 H100 80 GB,支持 BF16 或 FP8;A100 80 GB 对应 BF16,L40S 48 GB 对应 FP8,RTX 5090 对应 NVFP4。不能看到量化版本就默认自己的显卡能跑。
环境采用 Linux 或 WSL2、Python 3.13、uv、vLLM 0.32.0 和 NeMo Speech 的 main 分支。额外安装的 av==19.0.2 用于解码压缩音频,opencv-python-headless==5.0.0.93 补足依赖。默认权重名称是 nvidia/NVIDIA-Nemotron-3.5-Transcribe-30B-A4B,另有 -FP8、-NVFP4 版本;名称中的 30B-A4B 与文中总参数口径不同,原文没有进一步解释。
词级时间戳尤其依赖配置:需要 VLLM_PLUGINS=nemo_speechlm、VLLM_USE_V2_MODEL_RUNNER=0,以及 --trust-request-mm-kwargs 和 CTC 时间戳中间件。录音时长默认上限为 600 秒,教程通过 VLLM_MAX_AUDIO_DECODE_DURATION_S=3600 提高到一小时,文件上限设置为 VLLM_MAX_AUDIO_CLIP_FILESIZE_MB=180。
服务参数中的 --max-model-len 65536 不宜随意缩小,原文提醒,密集的一小时对话可能需要约 20,000 个输出 token。--gpu-memory-utilization 0.94 则允许服务使用 94% 显存。
支持某项能力,不代表换一条部署路线仍然支持。
例如 DFlash2 需要修补 vLLM 0.32.0,并使用 V2 runner,却无法提供词级时间戳。需要时间轴的会议场景,教程建议保留 MTP 路线。
速度同样要看口径。模型卡给出的 H100 英语 ASR 批处理吞吐约为 MTP2 的 410 倍实时、MTP8 的 270 倍实时,排除了启动时间,也不是单请求延迟。另一组 RTX PRO 6000 每秒处理 2,238 秒音频的数据来自优化后的 NIM,开放 vLLM 集成预计慢约两倍,不能混用这些数字估算交付时间。
从录音到字幕,关键是保住标签并检查对齐
先统一音频格式,可以减少输入端的变量。教程将录音转成 16 kHz 单声道,再检查编码和时长:
ffmpeg -y -i meeting_raw.m4a -ar 16000 -ac 1 meeting_16k.wav
ffprobe -v error -show_entries stream=sample_rate,channels,codec_name \
-show_entries format=duration -of default=noprint_wrappers=1 meeting_16k.wav
这里要看的是 -ar 16000 -ac 1。作者使用 ffmpeg 8.1.2,验证了 44.1 kHz 双声道测试音频转成 16,000 Hz 单声道 PCM 后,五秒时长保持不变。超过一小时可以用 -ss、-t 切分,但各段说话人标签会重新编号。
客户端通过 OpenAI 兼容的 chat.completions.create 请求本地 http://127.0.0.1:8000/v1,音频放在 audio_url 的 base64 data URL 中。api_key="not-needed" 是占位值,本地服务仍需限制访问范围。
有两个设置不能漏:skip_special_tokens=False 保留说话人和事件标签;mm_processor_kwargs={"capture_ctc_timestamps": True} 请求时间戳。下面这段代码展示如何同时索取标签和对齐结果,依赖原文前面定义的 ask 函数:
SPEAKER_PROMPT = (
"Transcribe this audio with punctuation and capitalization. "
"Include all spoken words and verbal fillers. "
"Write numbers in their standard written form. "
"Put speaker tags <spk:0> <spk:1> <spk:2> <spk:3> on the transcription."
)
response = ask("meeting_16k.wav", SPEAKER_PROMPT, timestamps=True)
alignment = response.model_dump()["ctc_timestamps"]
if alignment["error"] is not None:
raise RuntimeError(alignment["error"])
for word in alignment["words"]:
print(word["word"], word["start"], word["end"], word["speaker"])
最关键的是先检查 alignment["error"]。时间戳请求还要求单段音频、stream=false、n=1;没有说话人标签的文本会按单个说话人对齐。评估说话人区分效果时,应使用 diarization 活动片段,不能只看词级时间戳。
后处理则比较直接:连续同一说话人的词合并成一段,Markdown 保留开始时间,SRT 使用首词和末词的时间,并保留毫秒。不过,这样生成的是带时间的转写稿,并非提炼过决策与待办的会议摘要;长时间独白也可能产生过长的字幕条目。
我的判断
我认可教程对验证范围的交代。作者于 2026 年 10 月 29 日用 openai 3.41.0 对接 mock server,检查了请求结构、标签解析,并逐字节核对 Markdown、SRT 输出。这能证明客户端和格式转换按预期工作。
mock 验证通过,不能证明真实录音的识别质量。
模型服务命令来自模型卡,作者没有实际启动。中文术语、多人抢话、远场收音和真实处理耗时,都还需要验证。提供的原文也在第八步质量检查处截断,没有完整检查清单。
与多个专用模型串联相比,单模型路线减少了接口协调,却也让功能更依赖特定推理配置。原文没有给出两种方案在准确率、成本和延迟上的对照,暂时只能把整合优势视为架构上的便利。
音频问答也应单独验收:该模式使用 temperature=0.6、top_p=0.95、20,480 token 输出上限和 16,384 token reasoning budget;客户端另设 thinking_token_budget=17408。模型卡主要评估英语音频理解,不能据此认定中文会议问答同样可靠。
能拿来做什么
- 接入前先挑一段熟悉的两分钟录音,核对转写、说话人切换和时间轴,再测试完整会议,记录预热之后的真实耗时。
- 给技术会议维护一份
--context术语表,比较加入产品名、组件名和内部简称前后的结果,用实际样本决定是否保留。 - 做会议回放页面时,用词级时间关联文本与播放器;多人活动展示使用
diarization,并为分段录音维护独立的说话人映射。 - 批处理可以沿用
transcribe.py的--mode speaker|readable|verbatim|translate|qa、--format md|srt|txt和--out。原文循环为 Markdown、SRT 分别发起请求,实际接入时可以复用同一份对齐结果生成两种文件,减少重复推理。