Prhub

#24185 [Fix] load_audio: fall back to soundfile when torchcodec fails on WAV with trailing metadata

原始 PR 作者 AgainstEntropy 合并时间 2026-05-14 15:02 文件变更 1 提交数 6 评论 5 代码增减 +17 / -10

执行摘要

修复 torchcodec 解析带尾部元数据 WAV 崩溃

Qwen3-ASR 测试套件中的英文 WAV 样本携带尾部 _PMX(XMP)元数据,torchcodec AudioDecoder 从内存字节流读取时越过 PCM 区域进入元数据并抛出 RuntimeError: 'Tried to read outside of the buffer',导致 ASR 端点返回 500 错误。该问题已向 torchcodec 上报(issue#1378)并被修复(PR#1379),但为防止用户在使用旧版本 torchcodec 时遇到同样问题,在 SGLang 侧增加防御性 fallback。

建议合并。这是一次防御性编程改动,以极低代价提升了系统鲁棒性。可考虑后续补充单元测试,覆盖 torchcodec 抛出异常的场景。

讨论亮点

review 中没有技术讨论。JustinTong0323 在 issue 中询问该问题是否来自 torchcodec 本身的 bug,作者 AgainstEntropy 确认并已向 torchcodec 提交了最小复现脚本和 issue(#1378);issue 关闭时 torchcodec 侧也已修复(PR#1379)。

实现拆解

  1. 异常捕获:在 python/sglang/srt/utils/common.pyload_audio 函数中,将 torchcodec 的 AudioDecoder 调用及后续采样处理包裹在 try/except Exception 块内。
  2. 日志告警:捕获异常后调用 logger.warning 输出 torchcodec 失败原因,提醒用户正在回退。
  3. 回退到 soundfile:由于 torchcodec 分支与后续的 soundfile + torchaudio fallback 路径在代码结构上紧接着,异常抛出后自然落入同一 fallback 块,无需额外逻辑。fallback 路径之前仅用于 ARM / 无 FFmpeg 环境,现在也覆盖 torchcodec 运行时失败。
  4. 注释更新:将 fallback 的注释从 "ARM / no FFmpeg" 更新为 "ARM / no FFmpeg / torchcodec failure",明确其扩展后的用途。
  5. 无测试文件变更:改动仅作用于源代码,未添加单元测试;作者在 PR body 中说明了本地通过 Qwen3-ASR 测试套件验证。
文件 模块 状态 重要度
python/sglang/srt/utils/common.py 音频解码 modified 6.4

关键符号

load_audio

关键源码片段

python/sglang/srt/utils/common.py core-logic

核心修改文件:在 load_audio 函数中为 torchcodec 分支增加 try/except,失败时回退到 soundfile + torchaudio 路径。

# python/sglang/srt/utils/common.py 中 load_audio 函数(关键变更部分)
​
    if _BACKEND == "torchcodec":
        from torchcodec.decoders import AudioDecoder
​
        try:
            # torchcodec 在解析带尾部元数据(如 XMP)的 WAV 时可能崩溃
            decoder = AudioDecoder(
                source,
                sample_rate=sr,
                num_channels=1 if mono else None,
            )
            samples = decoder.get_all_samples()
            if mono:
                return samples.data.squeeze(0).numpy()
            return samples.data.T.numpy()
        except Exception as e:
            # torchcodec's bytes-buffer IO can fail on WAV files that carry
            # large trailing metadata chunks. Fall back to soundfile, which
            # reads the PCM payload directly.
            logger.warning(
                f"torchcodec AudioDecoder failed ({e}); "
                f"falling back to soundfile + torchaudio."
            )
            # 不 return,继续往下走到 fallback 路径
​
    # Fallback: soundfile + torchaudio (ARM / no FFmpeg / torchcodec failure)
    import soundfile as sf
    import torch
    import torchaudio
​
    if isinstance(source, bytes):
        audio, original_sr = sf.read(BytesIO(source))
    else:
        audio, original_sr = sf.read(source)
    # ... 后续 mono 处理和重采样逻辑不变 ...

评论区精华

bug 归属:torchcodec 自身 bug other

JustinTong0323 在 issue 评论中询问该问题是否是 torchcodec 的 bug,是否应向上游报告。

结论:作者 AgainstEntropy 确认是 torchcodec bug,并已创建上游 issue(meta-pytorch/torchcodec#1378),之后上游也已修复(PR#1379)。SGLang 的防御性 fallback 作为临时缓解措施。 · 已解决

风险与影响

低风险。变更仅在 torchcodec 解码异常时触发回退,对正常流程无影响。回退路径 soundfile + torchaudio 是早已存在的稳定代码。但需注意:

  1. torchcodec 和 soundfile 的输出格式可能存在细微差异(如数据类型、声道排列),但 fallback 对 mono 和重采样做了统一处理,差异应在可接受范围内。
  2. 捕获的是通用 Exception,可能掩盖 torchcodec 的其他非预期错误(如格式不支持),但回退路径也能处理这些情况,因此利大于弊。
  • 用户影响:ASR 端点对携带尾部元数据的 WAV 文件不再返回 500 错误,而是正常解码返回结果;日志中会记录一条 warning,可辅助排查问题。
  • 系统影响:无性能退化,异常路径仅在少数文件触发。
  • 团队影响:无,单文件小改动。
外部依赖缺陷 缺少异常场景测试覆盖

关联 Issue

#1378 [Bug] AVIOTensorContext buffer overrun on 24-bit WAV with trailing chunk

完整报告

参与讨论