# PR #39079 完整报告

- 仓库：`vllm-project/vllm`
- 标题：[Refactor] Drop direct dependency on librosa
- 合并时间：2026-04-18 14:55
- 原文链接：http://prhub.com.cn/vllm-project/vllm/pull/39079

---

# 执行摘要

- 一句话：移除 librosa 依赖，替换为 torchaudio 及内部音频处理函数。
- 推荐动作：建议快速浏览此 PR 以了解依赖清理模式，重点关注 `vllm/transformers_utils/processors/cohere_asr.py` 中滤波器组替换的数值验证方法。对于音频处理模块的开发者，此变更展示了如何将外部依赖迁移到内部或标准库工具。

# 功能与动机

根据 PR body，主要动机是“Drop dependency on librosa due to license concerns.”，即出于许可证担忧，需要移除对 librosa 的依赖以规避潜在风险。

# 实现拆解

1. **替换 Mel 滤波器组生成**：在 `vllm/transformers_utils/processors/cohere_asr.py` 的 `FilterbankFeatures` 类中，将 `librosa.filters.mel` 调用改为 `torchaudio.functional.melscale_fbanks`。关键符号包括 `__init__` 方法。原因：使用 torchaudio 提供的等效函数，确保数值收敛，同时移除 librosa 依赖。影响：音频特征提取的核心逻辑保持不变，但依赖链简化。
2. **更新音频加载和重采样函数**：在示例文件如 `examples/online_serving/openai_realtime_client.py` 和多个测试文件中，将 `librosa.load`、`librosa.resample`、`librosa.get_duration` 替换为内部函数 `load_audio`、`AudioResampler.resample`、`get_audio_duration`。原因：统一使用项目内部的音频处理工具，减少外部依赖。影响：示例和测试代码不再依赖 librosa，但功能等价。
3. **调整注释和文档**：在 `vllm/multimodal/media/audio.py` 和 `docs/contributing/model/transcription.md` 中，更新对 librosa 的引用，改为 soundfile/PyAV 作为后端。原因：反映实际依赖变化，确保文档准确性。影响：开发者文档与代码实现一致。
4. **同步测试配套**：修改了 7 个测试文件，包括 `tests/models/multimodal/generation/test_whisper.py` 等，以使用新函数，确保测试覆盖音频处理场景。原因：维持测试有效性，避免因依赖变更导致测试失败。影响：测试套件继续验证音频功能，不引入回归。

关键文件：
- `vllm/transformers_utils/processors/cohere_asr.py`（模块 音频处理器；类别 source；类型 dependency-wiring；符号 FilterbankFeatures.__init__）: 核心音频特征提取文件，替换了 Mel 滤波器组生成，直接影响音频处理质量。
- `vllm/multimodal/media/audio.py`（模块 多模态媒体；类别 source；类型 documentation）: 多模态音频处理模块，更新注释以反映后端从 librosa 切换到 soundfile/PyAV。
- `examples/online_serving/openai_realtime_client.py`（模块 示例服务；类别 source；类型 dependency-wiring；符号 audio_to_pcm16_base64）: 示例代码展示实时音频转录，替换 librosa.load 为内部 load_audio 函数。
- `tests/models/multimodal/generation/test_whisper.py`（模块 语音测试；类别 test；类型 test-coverage；符号 resampled_assets）: 测试文件，替换 librosa.resample 为 AudioResampler，确保测试覆盖新函数。

关键符号：FilterbankFeatures.__init__, load_audio, AudioResampler.resample, get_audio_duration


## 关键源码片段

### `vllm/transformers_utils/processors/cohere_asr.py`

核心音频特征提取文件，替换了 Mel 滤波器组生成，直接影响音频处理质量。

```python
# 在 FilterbankFeatures 类的 __init__ 方法中，替换 librosa.filters.mel 为 torchaudio.functional.melscale_fbanks
filterbanks = melscale_fbanks(
    n_freqs=self.n_fft // 2 + 1,  # 计算频率点数，对应 n_fft 参数
    f_min=lowfreq,                 # 最低频率
    f_max=highfreq,                # 最高频率
    n_mels=nfilt,                  # Mel 滤波器数量
    sample_rate=sample_rate,       # 采样率
    norm=mel_norm,                 # 归一化方式
    mel_scale="slaney",            # 使用 slaney 尺度以匹配 librosa 行为
).T.unsqueeze(0)                   # 转置并增加批次维度以适配原有张量形状
self.register_buffer("fb", filterbanks)  # 注册为缓冲区，供前向传播使用
```

### `examples/online_serving/openai_realtime_client.py`

示例代码展示实时音频转录，替换 librosa.load 为内部 load_audio 函数。

```python
# 音频加载函数，替换 librosa.load 为内部 load_audio
def audio_to_pcm16_base64(audio_path: str) -> str:
    # Load audio and resample to 16kHz mono
    audio, _ = load_audio(audio_path, sr=16000, mono=True)  # 使用项目内部函数，避免 librosa 依赖
    # Convert to PCM16
    pcm16 = (audio * 32767).astype(np.int16)
    # Encode as base64
    return base64.b64encode(pcm16.tobytes()).decode("utf-8")
```

# 评论区精华

Review 中主要讨论了数值收敛性问题：Isotr0py 询问“Can you verify if this is fully numeric converged?”，NickCao 回复指出“This is already covered upstream”，即 torchaudio 的测试已确保 `melscale_fbanks` 与 librosa 的等效性。结论：变更已通过上游验证，数值一致性有保障，无未解决疑虑。

- 数值收敛性验证 (correctness): 变更已通过上游验证，数值一致性有保障。

# 风险与影响

- 风险：技术风险包括：1. 数值精度风险：`torchaudio.functional.melscale_fbanks` 与 `librosa.filters.mel` 可能存在微妙差异，但已通过上游测试覆盖，风险较低。2. 性能风险：变更主要发生在初始化路径（如 `__init__`）和测试 / 示例中，不在热路径，预计无性能回归。3. 依赖链残留：PR 评论中提到 `datasets` 库仍可能拉入 librosa，但本 PR 已处理代码层面依赖，后续需更新 `datasets` 版本以完全移除。
- 影响：对用户影响：音频处理功能应保持不变，用户无需调整使用方式。对系统影响：移除 librosa 依赖降低许可证风险，简化部署依赖；内部函数调用可能引入轻微开销，但非关键路径。对团队影响：需确保新代码不重新引入 librosa，并关注 `datasets` 等第三方库的更新。
- 风险标记：数值精度风险 , 依赖链残留

# 关联脉络

- PR #37058 （推断为移除主代码依赖）: 先前 PR 已移除主代码中的 librosa 依赖，本 PR 扩展清理到示例和测试代码。