Prhub

#39079 [Refactor] Drop direct dependency on librosa

原始 PR 作者 NickCao 合并时间 2026-04-18 14:55 文件变更 13 提交数 6 评论 12 代码增减 +40 / -44

执行摘要

移除 liborsa 直接依赖,用 torchaudio 和内部工具替代

PR 作者指出,移除 librosa 的原因是许可问题。参见 PR body: 'Drop dependency on librosa due to license concerns.'

建议阅读此 PR 以了解如何系统替换一个外部依赖并保证数值等价。值得关注的设计决策:使用 torchaudio 的 melscale_fbanks 替代 librosa.filters.mel,并参考了上游兼容性测试。此外,示例和测试的统一替换模式(通过内部工具统一入口)也值得在类似重构中复用。

讨论亮点

Isotr0py 在 review 中询问 melscale_fbanks 替换是否完全数值收敛,因为音频处理对微小差异敏感。NickCao 回复指出该替换已被上游 PyTorch Audio 的兼容性测试覆盖(test/torchaudio_unittest/functional/librosa_compatibility_test_impl.py)。无未解决疑虑。

实现拆解

  1. 在 vllm/transformers_utils/processors/cohere_asr.py 中,将 librosa.filters.mel 替换为 torchaudio.functional.melscale_fbanks,参数映射并进行转置调整,生成与之前等价的 mel 滤波器组。
  2. 在示例 openai_realtime_client.py 中,将 librosa.load 替换为 vllm.multimodal.media.audio.load_audio,该函数已基于 soundfile / PyAV 实现音频加载和重采样;同时更新注释,从 "librosa" 改为 "soundfile/PyAV"。
  3. 在测试文件 test_whisper.py、test_phi4mm.py 等中,将 librosa.resample 替换为 vllm.multimodal.audio.AudioResampler,将 librosa.load 替换为 load_audio,并移除对 librosa 的导入。
  4. 在 vllm/multimodal/media/audio.py 中,更新注释原文,移除 "librosa's main backend" 字样,改为 "soundfile being the main audio loading backend"。
  5. 同步更新文档 docs/contributing/model/transcription.md 中的相关引用,以及多个测试文件的 import 和注释。
文件 模块 状态 重要度
vllm/transformers_utils/processors/cohere_asr.py 处理器 modified 6.25
examples/online_serving/openai_realtime_client.py 示例 modified 5.22
vllm/multimodal/media/audio.py 多媒体 modified 5.31
tests/models/multimodal/generation/test_whisper.py 测试 modified 4.9
tests/models/multimodal/generation/test_phi4mm.py 测试 modified 4.62

关键符号

FilterbankFeatures.__init__ audio_to_pcm16_base64 resampled_assets test_vision_speech_models

关键源码片段

vllm/transformers_utils/processors/cohere_asr.py dependency-wiring

核心模型处理器,将 librosa.filters.mel 替换为 torchaudio.functional.melscale_fbanks,是本次移除直接依赖的关键变更。

# 在 FilterbankFeatures.__init__ 中,使用 torchaudio 的 melscale_fbanks 生成 mel 滤波器组
filterbanks = melscale_fbanks(
    n_freqs=self.n_fft // 2 + 1, # 原始 librosa 通过 n_fft 推断,这里显式减半 +1
    f_min=lowfreq,
    f_max=highfreq,
    n_mels=nfilt,
    sample_rate=sample_rate,
    norm=mel_norm,
    mel_scale="slaney", # 明确指定 slaney 尺度以匹配 librosa 默认行为
).T.unsqueeze(0) # 转置并增加 batch 维度,与原来 (1, n_mels, n_freqs) 形状一致
self.register_buffer("fb", filterbanks)
examples/online_serving/openai_realtime_client.py dependency-wiring

示例脚本,将 librosa.load 替换为内部 load_audio,展示依赖移除对用户代码的影响。

# 示例中的音频加载函数,原先使用 librosa.load,现切换为内部统一 load_audio
def audio_to_pcm16_base64(audio_path: str) -> str:
    # 使用 vllm 的 load_audio 加载音频并重采样至 16kHz 单声道
    audio, _ = load_audio(audio_path, sr=16000, mono=True)
    # 转换为 PCM16 并 base64 编码
    pcm16 = (audio * 32767).astype(np.int16)
    return base64.b64encode(pcm16.tobytes()).decode("utf-8")

评论区精华

melscale_fbanks 数值一致性验证 正确性

Isotr0py 评论:要求验证 melscale_fbanks 与 librosa.filters.mel 是否数值收敛。NickCao 回复:上游 PyTorch Audio 已有兼容性测试覆盖。

结论:NickCao 确认数值等价,PR 继续合并。 · 已解决

风险与影响

主要风险为数值不一致:虽然 melscale_fbanks 在上游通过了与 librosa 的兼容性测试,但 Cohere ASR 的特定参数(如 mel_scale='slaney', norm 等)需要与 librosa 默认行为完全对齐。目前实现未额外验证。另外,librosa 可能仍被间接依赖(如 datasets 库),本次 PR 未移除间接依赖,用户环境可能仍会安装 librosa,需要后续升级 huggingface datasets 版本才能真正解除。

对用户而言,不再需要显式安装 librosa,降低了环境配置复杂度。对系统而言,避免了可能引起合规风险的许可问题(librosa 使用 ISC 许可,但项目可能因其他原因担忧)。对团队而言,维护负担轻微减少——音频加载和重采样功能统一由内部工具提供。

数值不一致风险 间接依赖残留

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论