Skip to content

fix: Linux 下通过 RAII 守卫注入 PIPEWIRE_PROPS 确保 PipeWire 硬件时钟自适应采样率 - #226

Merged
imsyy merged 1 commit into
SPlayer-Dev:devfrom
scsfu:fix/issue-225
Sep 7, 2026
Merged

imsyy merged 1 commit into
SPlayer-Dev:devfrom
scsfu:fix/issue-225

Conversation

@scsfu

@scsfu scsfu commented Sep 1, 2026 •

Copy link
Copy Markdown

改动类型

  • 新功能(feat)
  • 缺陷修复(fix)
  • 重构 / 优化(不改变对外行为)
  • 文档(docs)
  • 其他(请在「改动说明」中注明)

是否包含破坏性变更

  • 是(请在「改动说明」中详细描述)
  • 否

改动说明

在 Linux PipeWire 环境下播放高采样率音频(如 96kHz / 192kHz)时,外接硬件 DAC 解码器屏幕始终显示系统默认的固定采样率(44.1kHz 或 48kHz)。

排查与原因

  1. SPlayer-Next 实际上成功走的是原生 PipeWire 协议(未发生后端回退)。
  2. 但 cpal 在创建 PipeWire 流节点时,仅在 Format 参数中协商了样本格式,遗漏了向流属性字典中注入 "node.rate": "1/{rate}" 调度指令。
  3. 导致 PipeWire 调度器认为流未显式声明硬件时钟意图,从而按全局默认图时钟运行,并通过 libspa-audioconvert 进行静默重采样,未驱动硬件 ALSA Sink 节点触发硬件切频。

修复方案

在 native/audio-engine/src/audio_output.rs 中:

  1. 封装 RAII 守卫模块(pipewire_props::Guard):
    • 在调用 device.build_output_stream 前,临时注入 PIPEWIRE_PROPS='{"node.rate":"1/{sample_rate}"}'。
    • build_output_stream 完成后,通过 Drop 立即将环境变量还原为原本状态(若原本不存在则彻底注销),零环境持久污染,彻底避免切歌累积。
    • 内置静态互斥锁 ENV_LOCK,串行化建流期间的环境变量读写。
    • 包含 sample_rate == 0 防御性校验,避免生成畸形属性字符串。
  2. 跨平台隔离:
    • 带有 #[cfg(target_os = "linux")] 条件编译保护,Windows/macOS 完全不受影响。

关联 Issue

Fixes #106
Fixes #225

测试情况

  • 测试环境:Arch Linux(Kernel 7.1.11-zen,PipeWire 1.6.8,WirePlumber 0.5.15)+ 外接 USB DAC(BRZHIFI)
  • 验证步骤与结果:
    1. 播放 96kHz FLAC 曲目,外接 DAC 解码器前面板屏幕成功由 48kHz 自适应切换为 96kHz。
    2. 使用 pactl list sinks 检查,硬件 ALSA Sink 采样规格实时变为 s32le 2ch 96000Hz,无中间重采样。
    3. 进行连续切歌(48k $\to$ 44.1k $\to$ 96k),每次采样率均平滑切换,日志无任何错误与资源泄漏。
    4. 运行 cargo test,全量 64 项 Rust 单元测试全部通过。
    5. 运行 pnpm typecheck 与 pnpm lint 检查全部通过。

自查清单

  • 本 PR 只包含一个主要功能 / 修复,没有夹带无关改动
  • 已在本地完整测试通过;AI 生成的代码同样自行测试并审阅过,未做未经验证的提交
  • 已运行 pnpm format,并确认 pnpm typecheck、pnpm lint 通过
  • 改动涉及原生模块时已 pnpm build:native 验证;未手写 native/*/index.d.ts
  • 已向 dev 分支提交

@scsfu scsfu changed the title fix: Linux 下注入 PIPEWIRE_PROPS 确保 PipeWire 硬件时钟自适应采样率 fix: Linux 下通过 RAII 守卫注入 PIPEWIRE_PROPS 确保 PipeWire 硬件时钟自适应采样率 Sep 1, 2026
@imsyy
imsyy merged commit 6f3e6c3 into SPlayer-Dev:dev Sep 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants