长录音为什么会漏掉结尾?

如果团队拿到了长录音的文本,却找不到最后一句,先别急着调大批次。沿着原文件、语音分段和返回结果定位,才能知道哪一步需要处理;有文本并不代表全程完整。

设想一段访谈:原文件里能听到最后一句,文本里却没有。这个现象还不能直接归因于模型。先确认读取包含尾部、分段保留了那句声音,再看客户端有没有保存完整结果。

下面只用一个明确的 SenseVoice 离线分段配置说明排查路径,不是所有漏尾问题的修复。静音、切分、推理和客户端异常需要分别核验。

调参之前,先查三个位置

  1. 输入:核对实际解码的那份文件及其结尾,不是同名的另一份录音。
  2. 边界:检查缺句附近的切分。语音检测负责选区域,不负责判断文字是否正确。
  3. 结果:分清空记录、未读完的响应和最终保存的文本;保留错误,不靠猜测补写原文。

用一个明确的离线配置开始

前提是已经准备好的独立 FunASR 1.4.15 环境,包括 PyTorch、可用的音频解码依赖和模型权重访问。先按安装与环境验证指南准备平台依赖,再核对Python SDK 指南。下方版本检查只检查已安装包的元数据,不是完整安装或声学推理证明。

把你有权处理的本地文件放在 meeting.wav。先用短录音验证环境,再逐步测试业务长录音;首次加载可能联网下载模型。输出包含转写文本,不要把私人内容放进公开日志。代码固定工具包版本,但未锁定全部依赖和模型 revision,正式部署应另行记录并固定它们。

from importlib.metadata import version
from pathlib import Path

installed = version("funasr")
if installed != "1.4.15":
    raise RuntimeError(f"Expected FunASR 1.4.15, found {installed}")

audio = Path("meeting.wav")
if not audio.is_file():
    raise FileNotFoundError(audio)

from funasr import AutoModel

model = AutoModel(
    model="iic/SenseVoiceSmall",
    vad_model="fsmn-vad",
    vad_kwargs={"max_single_segment_time": 30000},
    device="cpu",
)
result = model.generate(
    input=str(audio),
    batch_size_s=300,
)
if not result or not isinstance(result[0], dict):
    raise RuntimeError("No result record; inspect audio and model logs")
text = result[0].get("text", "")
if not isinstance(text, str) or not text.strip():
    raise RuntimeError("Empty transcript; inspect audio, silence and VAD output")
print(text)

这里明确使用 CPU,按 VAD 片段逐个处理;batch_size_s 不是 CPU 并行参数,也不是速度推荐。空结果需要检查:可能是静音、VAD 未选中语音、输入问题或推理异常,不能一律当成成功或模型错误。示例故意停止并要求人工检查,不提供伪造的转写输出。

长文件上线前怎么验收

  1. 先验证输入:检查文件可解码、实际时长、声道和采样率。不要把读取成功或非空文本视为完整处理证明。
  2. 覆盖业务难点:准备短录音、长静音、多人重叠、连续长发言,以及末尾有明确语音的样本。重点复听切分处、关键实体和尾部;时间戳空隙也可能是静音。
  3. 记录资源和时延:固定模型与依赖版本、硬件、设备、音频身份和并发;分开记录初始化与文件调用耗时,说明是否预热,测量 RAM 和 GPU 峰值,保留失败与空结果。
  4. 再扩大负载:逐步增加录音长度和并发,确定服务的准入、超时、队列与重试策略。一次成功不能证明所有时长都可用;客户端超时也不等于后台推理被取消。

更多思路见会议转写验收清单可复现性能评测。前者附带的 MOSS sentence_info 检查器有特定输入契约,不可直接套在任意 SenseVoice 返回值上;结构检查也不证明文字准确率或语音覆盖完整。

附录:窗口、资源与参数单位

一次调用背后的资源路径

这条离线路径会读取完整音频波形到 CPU 内存,再使用 VAD 区域组织 ASR 输入;它不是只从磁盘读取当前片段的有界内存流式处理。分段可以改变某一批推理的工作量,但整段波形、解码缓冲、分段信息、输出和并发请求仍占用资源。

仅按 16 kHz、单声道、float32 波形计算,一小时数据约 230 MB;这只是数据量估算,不是进程 RAM 或 GPU 峰值内存实测,也不包含解码副本和模型。不能据此承诺任意文件都能处理,或一小时与一分钟文件显存相同。可接受的时长需要在所选硬件、模型、音频格式和并发条件下验证。

查看整段加载与分段排序音频解码入口。这些源码能说明数据路径,不能替代峰值内存测量。

两个参数,两个不同的边界

  • max_single_segment_time=30000: FSMN-VAD 的端点阈值,单位毫秒(ms)。它参与帧级语音分段决策。 不是整文件时长限制,不保证严格等长片段或恰好切在一个词、句子的边界。
  • batch_size_s=300: VAD 包装器的批预算,单位秒(s),内部转为毫秒;组批判据涉及最长片段时长乘以片段数量。 不是所有片段时长简单求和,也不是硬内存上限;较长的单段仍可能单独进入推理。

CPU 例外:当前包装器在 device="cpu" 时关闭上述组批预算,按片段逐个处理。因此调整示例中的 batch_size_s 不能当作 CPU 批吞吐优化已经生效。换用经过配置和验证的 GPU 环境时,应重新测量,而不是套用相同内存或速度结论。实现依据:批预算单位CPU 分支与组批判据

模型和服务应分开选择

  • 本文是明确配置外部 FSMN-VAD 的 SenseVoice 离线示例。Paraformer 的配置与输出应另行核对;SenseVoice 富文本标签不是经过验证的情绪准确率。
  • 第三方 MOSS-Transcribe-Diarize 有自己的整录音转写与原生说话人分离路径,不需要照搬本文的外部 VAD 或 CAM++。匿名说话人标签不等于实名身份识别。
  • 需要实时麦克风转写时,按部署矩阵选择明确支持的流式模型与服务;缩小离线批次并不会把它变成流式协议。更多能力差异见模型选型指南

本文依据固定版本源码解释行为,没有新增长录音性能或准确率实测。旧页缺乏完整复现条件的耗时和全程覆盖宣传已撤下;历史版本保留在仓库中,不能作为当前部署承诺。

下一步,按会议转写验收清单挑一份有代表性的录音回听结尾。该文下载的 MOSS 检查器有不同输入契约,不能直接套用本篇 SenseVoice 返回值。