惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Simon Willison's Weblog
Simon Willison's Weblog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
About on SuperTechFans
Last Week in AI
Last Week in AI
月光博客
月光博客
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
U
Unit 42
The Register - Security
The Register - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
H
Hacker News: Front Page
Recent Announcements
Recent Announcements
C
CXSECURITY Database RSS Feed - CXSecurity.com
Latest news
Latest news
小众软件
小众软件
P
Palo Alto Networks Blog
PCI Perspectives
PCI Perspectives
Security Latest
Security Latest
S
Secure Thoughts
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
O
OpenAI News
S
Securelist
云风的 BLOG
云风的 BLOG
H
Help Net Security
T
Troy Hunt's Blog

Peng's Blog

Vibe paper不负责指北 SPFC参考文献阅读《CONGA》 读《Uno:数据中心间和数据中心内拥塞控制与可靠连接的一站式解决方案》 Lenovo Legion Y9000P 在 Linux 下只有 30W:从现象、WMI 到驱动补丁 理解《From ATOP to ZCube》中的ZCube网络拓扑 集合通信原语学习 Zotero在Wayland下侧边栏无法拖动的解决办法 再读CAVER 我读的第一篇论文--NSDI_26_CAVER 在archlinux下使用万象拼音实现更智慧的中文输入法 Traefik实现单Docker容器托管多个静态网站 Pengs.top浴火重生!备案、服务器迁移与全站Docker化 严谨与温度并存:北航宋友老师程设课的学习感悟 Android Studio全流程换源指南 在ThinkBook 16+ 2025上安装archlinux驯服记录【基本信息与触摸板修复】 「行云流水」在挂载移动硬盘时自动启动Syncthing开始同步的丝滑体验 自建图床和PicGo闹不愉快?干脆自己写个脚本,深度整合到KDE右键菜单! btrfs各压缩等级速率测试脚本,选择最适合你的压缩级别 别当冤大头,Adobe全家桶破解源头方案:修图剪辑不求人,盗版网站也得从你这儿进货! 轻松配置aria2下载器,通过systemd设置开机自启并与浏览器集成 Git Commit 规范指南
解决linux系统下pipewire作为音频服务器持续播放声音中断问题
Pengbo · 2025-08-18 · via Peng's Blog

本文接上篇在ThinkBook 16+ 2025上安装archlinux驯服记录【基本信息与触摸板修复】。按理说,本文标题本应是《在ThinkBook 16+ 2025上安装archlinux驯服记录【音频修复】》的,考虑到此问题可能影响到较多机型,故修改为更通用的标题。

闲话少说,开始解决问题。

问题背景

我有时候会用电脑播放音乐,这些音乐都是无损flac格式的盗版音乐。在我的上一台电脑上,一切正常。在这台新款的ThinkBook 16+ 2025上,问题表现为:

播放音乐的时候,能放一会儿(约30秒),然后就没有声音了,插电也是这样
声音中断后KDE设置显示“已失去与声音服务器的连接”,VLC启动时加载时间比正常情况久很多,音量被自动设置到0,且进度条不开始。

这种情况令我糟心,为了立刻重新听上音乐,我通过systemctl重启了pipewire与wireplumber服务,重新打开vlc,播放了2~3分钟后,同样的声音中断发生了。

作为archlinux用户,我的软件包都是滚动更新的最新版本,所以显然上游还没有修复这个问题,只能自己动手了。

调试过程

我查看了与声卡有关的日志,如下:

屏幕截图_20250817_143513

从日志上看,驱动能够正常识别与处理设备,而在播放过程中,pipewire或其下的某个组件崩溃了,造成了broken pipe

考虑到linux音频系统的混乱与复杂(如下图),我没有能力深度调试,决定先进行“猜测”。

linux混乱的音频系统

我首先怀疑是省电配置导致的,因为我希望延长续航时间,所以安装了tlp并且手动配置了许多省电选项。

所以我直接修改了/etc/tlp.conf,找到了与声卡节能有关的配置并修改为以下内容:

1
2
SOUND_POWER_SAVE_ON_BAT=0
SOUND_POWER_SAVE_ON_AC=0

这意味着在交流供电与电源供电时都不会尝试让声卡通过挂起等方式节能。根据我的经验与直觉,linux下硬件不能正常工作,常常是和suspend(挂起)与recover(恢复)有关的。所以我满心期待以为问题解决了。

然后我跟着音乐哼着哼着,音乐停了。

我寻思是不是有内核参数在作祟,于是又折腾了好久。可是并没有用。

就在这个时候我注意到一个此前忽略的细节:虽然连续播放的音乐会中断,但是如果不播放音乐,系统的提示音效在开机后多久,甚至睡眠又唤醒后都是正常的。

也就是说长音频不行而短音频没有影响。

诡异吧?

缓冲区玄学

这个玄学问题,最终还要归结于“缓冲区”。

什么是缓冲区?

想象一下你在搬砖,有一个小推车(缓冲区)。CPU负责往小推车里放砖(音频数据),声卡负责从车里取砖去砌墙(播放声音)。为了让声卡能源源不断地拿到砖,小推车里必须一直有存货。

什么是欠载?

如果CPU因为某些原因(比如在忙别的事情)没来得及往车里放砖,导致小推车空了,声卡过来取砖时发现没东西可取,这就叫“欠载”。
欠载后会发生什么? 通常情况下,ALSA驱动会检测到这个问题,并尝试快速“恢复”现场,比如重置指针、清空缓冲区等,这可能会导致你听到一声非常短暂的“咔哒”声,但播放会继续。

实际情况(猜测)

我的硬件驱动/固件(SOF)非常新,它的“欠载恢复”机制可能有Bug。当欠载发生时,驱动尝试恢复,但操作失败了,把自己搞“死机”了。这就解释了最初日志里的那句 snd_pcm_avail after recover: 断开的管道 (Broken pipe) —— “恢复后管道断开”,意思就是恢复失败了!

刑,既然咱猜是缓存区害得,那把缓存区调大不就好了!

问题解决

我们即将创建一个配置文件覆盖原有默认设置:

1
2
sudo mkdir -p /etc/pipewire/pipewire.conf.d/
sudo nano /etc/pipewire/pipewire.conf.d/99-custom-buffer.conf

数字-XXX是linux下约定俗成的配置文件(主要是在XXconf..d下的)的命名方式,前面的数字表示加载的先后顺序,数字越大越晚被加载,而后加载的配置会覆盖先加载的,所以99(几乎肯定)能覆盖默认配置。

写入以下内容:

1
2
3
4
context.properties = {
default.clock.quantum = 2048,
default.clock.min-quantum = 2048
}

这是把缓冲区大小设置为了2048,对于咱们32GB RAM的高端机器来说不值得一提😎

但是如果你想显得自己很阔气把这个值调的极大呢?

哈哈,我已经帮你试过了。

不会再有什么正面影响了,同时,音频的延迟性会上升,打游戏估计不爽,但对我没影响。实际播放其实影响也不大,因为pipewire似乎会选择一个较为合适的quantum.


更新:与sof-firmware交流,有以下新消息:

#5284中有人提出了类似的问题,他们修改了一个与alsa有关的参数,经过我的测试,可以奏效,方法如下:

新建文件~/.config/wireplumber/wireplumber.conf.d/50-alsa-config.conf,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
monitor.alsa.rules = [
{

matches = [
{
api.alsa.card.name = "~sof-*"
},
{
node.name = "~alsa_output.*"
}
]
actions = {
update-props = {
api.alsa.headroom = 1024
}
}
}
]

关于为什么要这么修改,我咨询了开发人员,感谢@kv2019i的耐心解答。

原文:

In short, headroom controls how close to the hardware read pointer Pipewire stays. In systems without audio DSPs, the data is consumed at a steady pace, so Pipewire can keep only very little data in the buffer (to minimize latency). When you have a DSP, power can be saved by not transferring data all the time, but moving data in bigger chunks. What happens in your case, that Pipewire keeps too little data in the audio buffer and a single DSP transfer (from main memory to DSP memory) can dry out the buffer and cause an xrun (there is nothing to play).
We are not talking about large buffers here. With regular PCMs, typical DSP configuration will be a 4ms buffer, so small addition to headroom will be enough to avoid xruns.
Pipewire is doing this to minimize latency, but in this case, it is too aggressive by default and ends up causing continuous xruns.
We do have a separate question how to solve this better in the longer term, but currently we don't have means in ALSA interface to describe (to apps like Pipewire) what is the maximum DMA burst size.

中文:

简而言之,headroom 控制着 Pipewire 与硬件读取指针的距离。在没有音频 DSP 的系统中,数据以稳定的速度被消耗,因此 Pipewire 只需在缓冲区中保留极少的数据(以最小化延迟)。当系统配备 DSP 时,可以通过不持续传输数据,而是以更大的块为单位传输数据来节省电量。在你的情况下,问题在于 Pipewire 在音频缓冲区中保留的数据太少,一次 DSP 传输(从主内存到 DSP 内存)就可能耗尽缓冲区,从而导致 xrun(没有可播放的内容)。
这里我们说的并不是大型缓冲区。对于常规的 PCM,典型的 DSP 配置会采用 4 毫秒的缓冲区,因此稍微增加一点 headroom 就足以避免 xrun。
Pipewire 这样做是为了最小化延迟,但在这种情况下,其默认设置过于激进,最终导致了持续的 xrun。
我们另外有一个问题,即如何在长期内更好地解决这个问题,但目前我们在 ALSA 接口中还没有办法向 Pipewire 这类应用程序描述最大 DMA 突发大小。

也就是说问题是出在alsa与pipewire的协商。而sof-firmware本身并没有问题。让我们等待上游修复吧

最后重启电脑,或者重启服务都可以

1
systemctl --user restart pipewire.service

长远考虑

以上内容算是一个对我可用的workaround,我不知道别人有没有遇到过这样的问题,也不知道这样能不能奏效。

如果你也遇到了这样的问题,希望你在评论区告诉我这样的方案能不能奏效。

同时为了帮助到更多人,我在sof的github仓库上打开了一个issue,不知道上游会怎么说。

就到这里吧。