waittingsummer
deepin
2026-09-11 09:40 好贴,希望官方跟进
Reply Like 0 View the author
好贴,希望官方跟进
好贴,希望官方跟进
有需求在跟进了,研发那边昨天已经构建了本地的包:

等后续某个版本的系统更新即可

AAC(高级音频编码)是有专利限制的。以下是关键信息汇总:
AAC-LC / HE-AAC / HE-AAC v2 / xHE-AAC 等不同 Profile 的授权费率不同,使用前需确认具体使用的 Profile。
| 方案 | 说明 |
|---|---|
| Opus | 完全开源免费,低延迟,适合实时通信 |
| MP3 | 专利已于 2017 年全部过期,免费 |
| FFmpeg 原生 AAC 编码器 | 零专利风险,但音质略逊于 FDK-AAC |
| libfdk-aac | 音质好,但需单独授权,存在专利风险 |
AAC(高级音频编码)是有专利限制的。以下是关键信息汇总:
AAC-LC / HE-AAC / HE-AAC v2 / xHE-AAC 等不同 Profile 的授权费率不同,使用前需确认具体使用的 Profile。
| 方案 | 说明 |
|---|---|
| Opus | 完全开源免费,低延迟,适合实时通信 |
| MP3 | 专利已于 2017 年全部过期,免费 |
| FFmpeg 原生 AAC 编码器 | 零专利风险,但音质略逊于 FDK-AAC |
| libfdk-aac | 音质好,但需单独授权,存在专利风险 |
纠结这玩意儿干啥?openSUSE老早可以用AAC,以前deepin上用pulseaudio的时候也有人折腾AAC,用不用得成AAC在deepin一直是一个技术问题,并不是专利什么的原因;
实在不行deepin告诉方法,用户自己找相关的东西安装就行了,但现实是压根就没有相关的操作方法,网上找到的方法在deepin上也行不通。如果不是AI,就算你搞成了,系统又自动切换回sbc,你可能都发现不了,会一直以为是自己没折腾成功

厉害
感谢你的添砖加瓦。
Popular Ranking
ChangePopular Events
More
关于蓝牙编码的问题我折腾了好多次,有时候折腾到半夜,搞的人火都起来https://bbs.deepin.org.cn/post/288847
继前些天让小U同学自动编译内核之后突发奇想让小U同学分析一下这个问题,本来也没想着能解决,想着能理出来思路也行
结果,结果,结果,竟然成了。小U直接把控制中心的选项都给弄出来了
好的,我先检查一下系统音频服务(PulseAudio 还是 PipeWire)以及 AAC 编解码库是否已安装,再决定怎么切换。
好消息:系统已安装 libfdk-aac(Fraunhofer FDK AAC 库),但当前 PipeWire 的蓝牙插件列表里没看到 AAC 插件。我进一步确认一下 PipeWire 是否编译了 AAC 支持,以及 WirePlumber 的编解码器配置:
发现关键线索:PipeWire 插件已内置 AAC 支持,而且用户配置目录里有个
.bak备份文件恰好启用了aac编码。我再确认下当前生效的配置文件:情况明确了:
libfdk-aac库.bak备份,内容正是启用aac的配置)现在我来恢复这个配置并重启音频服务,让 AAC 编码生效:
配置文件已恢复。现在重启音频服务使配置生效:
音频服务已重启,但蓝牙设备当前只显示了通话(HFP)配置,A2DP 音频配置暂时消失。我看下完整状态并重新连接设备:
A2DP 音频配置在重启后消失了,这是重启音频服务后的常见现象。我通过重新连接蓝牙设备来恢复:
设备已重新连接,A2DP 配置恢复了(SBC / SBC-XQ),但 AAC 配置仍然没有出现。我需要排查是配置没生效,还是音箱本身不支持 AAC:
日志里没看到编解码协商信息。我再查一下音箱本身通过蓝牙广播支持哪些 A2DP 编码(这是决定能否用 AAC 的关键):
SDP 记录只说明音箱支持 A2DP 协议,具体编码需要看 AVDTP 协商结果。我先确认配置是否被 WirePlumber 正确加载:
配置加载情况还不明确,我深入检查一下 PipeWire 中蓝牙监视器的完整配置和设备协商出的编码列表:
配置信息还没完全确认。我通过开启蓝牙插件的调试日志,直接查看音箱协商时上报的编码端点(SEP)列表,这是判断设备是否支持 AAC 的最可靠方式:
日志没有输出,我检查一下调试日志是否生效并查看更完整的输出:
日志中未捕获到编码协商信息。我改用直接捕获调试输出的方式,彻底确认音箱上报的编码能力:
调试日志级别不够。我用更高级别的调试重试一次,抓取设备上报的编码端点:
pkill误杀了自身命令,我改用精确的进程名方式重试:手动进程在运行,但调试输出仍然没有编码细节。我换用 WirePlumber 自身的调试变量确认配置文件是否被加载:
配置文件确认已被加载(日志显示
section 'monitor.bluez.properties' is used as-is from ...51-monitor.bluez.properties.conf)。现在重连设备,在完整调试日志中查找它上报的编码端点:日志确认了关键信息:音箱只有一个编码端点(sep1),且只用于 SBC/SBC-XQ 协商。我再搜索日志中设备上报的全部编码端点列表,做最终确认:
🎯 找到根本原因了! 日志显示:
系统缺少 AAC 编解码插件文件
libspa-codec-bluez5-aac.so(虽然 FDK AAC 库已装,但 PipeWire 的 AAC 桥接插件缺失)。我来查找安装这个插件:包已确认:Deepin 编译的
libspa-0.2-bluetooth(1.6.4)没有附带 AAC 插件(依赖列表里也没��� fdk-aac)。在想办法获取插件前,我先确认音箱本身是否支持 AAC(如果不支持,装插件也没用):从日志看,音箱有 4 个端点(sep1-4),sep1 用于 SBC,其余端点编码不明——但因为本地 AAC 插件缺失,无法确认音箱是否支持 AAC。最稳妥的做法是先把缺失的 AAC 插件装上。我搜索一下哪个软件包提供它:
搜索结果显示系统有编译工具但缺少 meson。我先查询 Debian 官方仓库中该插件是否可用(这是最快的获取途径):
packages.debian.org 被拦截了。我换用 Debian 的 API 查询该插件是否在 Debian 的软件包中:
sudo 需要密码,无法直接安装编译工具。我采用另一条路:直接从 Debian 官方镜像下载软件包索引,确认其是否包含 AAC 插件(不需要 root):
Debian trixie 的版本是 1.4.2,依赖列表同样没有 fdk-aac。我直接下载这个 .deb 包检查内容里是否真的有 AAC 插件:
Debian 官方包也不包含 AAC 插件(Deepin 和 Debian 都没编译它)。在决定是否自行编译前,我先直接读取音箱各端点的编码 ID(0x00=SBC,0x02=AAC),确认它到底支不支持 AAC:
🎯 重大发现!音箱本身是支持 AAC 的!
sep2 的 Codec ID = 2(AAC),capabilities
80 01 8c 84 09 b6正是 AAC 编码参数!也就是说:问题纯粹在系统侧缺少 AAC 插件。sep1=SBC、sep2=AAC、sep3/sep4=通话编码。现在确认获取插件的可行途径,先看看 Arch Linux 是否提供预编译的 AAC 插件:
Arch 的页面是动态加载的。我直接查它的 PKGBUILD 构建脚本,看是否编译了 AAC 支持:
Arch 也被反爬拦截。我换用直接下载源码的方式——PipeWire 的 AAC 插件源码是单文件,可以用 gcc 直接编译。先下载 PipeWire 1.6.4 源码(与系统版本一致)和 fdk-aac 开发头文件:
两个文件都下载成功。现在解压源码,检查 AAC 插件源码的结构和编译方式,同时解压 fdk-aac 开发头文件:
源码结构清晰。现在查看编译配置,确认需要哪些头文件和编译参数:
编译配置明确了:需要
a2dp-codec-aac.c+media-codecs.c两个文件。我检查是否依赖生成的头文件(config.h)和其他编译参数:编译需要额外的
bluetooth/bluetooth.h头文件(libbluetooth-dev)和-DCODEC_PLUGIN宏。我先确认插件加载器对插件目录的搜索机制(决定如何让系统找到新插件),同时下载缺少的蓝牙开发头文件:蓝牙头文件已就绪。现在确认插件目录的解析机制:
确认了
SPA_PLUGIN_DIR是单一路径覆盖机制。我再仔细看下 codec-loader 的具体加载方式,寻找最稳妥的安装途径:加载机制确认。现在开始编译 AAC 插件(使用刚下载的头文件,编译成与系统 PipeWire 1.6.4 匹配的插件):
链接到了静态库导致失败,改用系统已有的共享库来链接:
使用
-l:libfdk-aac.so强制链接共享库重新编译:开发包里的
.so符号链接是断的(目标文件不在包内)。直接链接系统已装的共享库:✅ 编译成功! 插件已生成(47KB),导出标准 SPA 工厂符号,正确链接系统 fdk-aac 库。
现在部署插件。由于无法用 sudo 写入系统目录,我采用用户级方案:镜像 spa 插件目录到用户目录并添加新插件,然后仅为 wireplumber 服务设置插件目录环境变量:
镜像完成(6.2MB,仅新增 AAC 插件)。现在为 wireplumber 服务创建配置覆盖,指定用户插件目录:
服务已带新环境变量重启。现在重新连接蓝牙设备,检查 AAC 编码是否出现:
🎉 AAC 编码出现了! 现在音箱的可用配置里多了
a2dp-sink (codec AAC)。立即切换到 AAC:✅ AAC 切换成功! 确认
bluetoothAudioCodec: "aac"。最后清理之前的调试环境变量,并做完整状态确认:咦,编码显示又回到了 sbc_xq?让我检查一下实际状态:
AAC 配置仍然可用,但活动配置被自动切回了 sbc_xq。我重新切换到 AAC 并持续监控,确认是否稳定:
AAC 切换后约 10 秒又被自动切回 SBC-XQ。查看 WirePlumber 日志找出是谁在"抢回"配置:
找到关键线索:切换时
spa.audioconvert报 "out of buffers"(缓冲区不足),导致 AAC 链路建立失败并回退到 SBC-XQ。这通常发生在切换时有音频正在播放的情况。现在没有活动音频流,我再次切换并观察:仍然回退,且无错误日志。我检查 WirePlumber 的状态恢复文件和完整日志,找出回退的真正触发源:
状态文件里记录着
bluez_card...=a2dp-sink-sbc_xq,说明有恢复机制。我需要弄清楚是谁在回切。先开启调试日志捕捉回切瞬间的详细信息:切换命令报"无此实体",可能重启后卡片名有变化。先查看当前卡片状态:
重启后设备配置还没协商好(显示 off)。重新连接设备并查看完整配置:
设备已重连,AAC 配置可用。现在开启调试日志的情况下切换到 AAC,捕捉回切瞬间的详细过程:
AAC 传输建立失败(
Failure in Bluetooth audio transport)。先确认调试环境变量是否真正生效,并查看完整日志:调试日志没有完整输出到 journald。我改用之前有效的方式——手动运行 wireplumber 并把完整调试日志写到文件,然后复现 AAC 切换过程:
AAC 切换实际成功过(codec switched status 0),但 0.5 秒后又有请求把编码切回 SBC-XQ。我在日志里找出是谁发起了"回切"请求:
找到模式了:AAC 切换成功后,节点重建时外部程序又把配置切回了 sbc_xq。系统中正好有 Deepin 的控制中心/会话守护进程在运行,很可能是它们保存的"首选配置"在作祟。我检查 Deepin 存储的音频配置:
找到了嫌疑文件:
audio-config-keeper.json(音频配置守护)。查看这些配置内容:找到元凶了! Deepin 音频守护进程的
audio.json里保存着"bluez_card.50_88_11_06_15_0B": "a2dp-sink-sbc_xq",它会在设备变化时强制恢复这个配置。我修改它并同步切换:配置已修改并切换。关键测试:等待一段时间看是否还会被回切:
audio.json 已改但依然回切,说明还有别的恢复源。我查看 WirePlumber 自己的状态文件是否也在强制恢复,并检查调试日志中是谁发出了 SetProfile 请求:
WirePlumber 的自动切换脚本正在保存/恢复
sbc_xq配置。我读取这个脚本的逻辑,理解它的恢复机制:脚本的 restoreProfile 逻辑不会在我们处于非通话配置时回切(已排除)。回切发生在 AAC 成功后的 0.018 秒内——这是 PipeWire 内部的编码选择逻辑。查看编码器的优先顺序定义:
AAC 的优先级高于 SBC-XQ(排序中 AAC 在前),所以不是优先级问题。我深入查看
ensure_media_codec和check_profiles的代码逻辑,找出触发回切的内部条件:回切速度太快(18毫秒),必然是内部调用。我找出所有触发
ensure_media_codec的调用点:真相大白! 回切的真正来源是 WirePlumber 的状态文件
default-profile(还存着a2dp-sink-sbc_xq)。编码切换导致节点重建时,WirePlumber 用这个文件恢复"用户保存的配置",把编码又切回 SBC-XQ。我来修正这个状态文件:切换完成。现在进行关键的稳定性验证(等待较长时间确认不再回切):
状态文件都改了还是回切。再次运行完整调试捕获,这次精确定位是谁调用了
set_profile:连接超时了,检查服务状态并重试:
有两个 wireplumber 进程在冲突!清理后重新开始:
环境干净了。现在切换 AAC 并完整捕获回切过程的调用链:
关键日志出现了!
setting profile 2 codec:X记录中 codec 编号需要对照枚举值。查看编码枚举定义:枚举明确了:codec:2 = SBC_XQ,codec:4 = AAC。日志显示 AAC(codec:4)设置后 0.6 秒又有
codec:2 save:1的调用。查看回切调用前的上下文找出调用者:save:1标记说明这是"用户保存的配置恢复"操作。我搜索是谁通过 D-Bus 发起的这次调用:看到关键元数据:
device.restore-profile = true。检查状态文件当前内容(可能被 WirePlumber 又写回了 sbc_xq):状态文件在 11:44:42 被 WirePlumber 重新写回了 sbc_xq——恢复机制确认存在。查看 WirePlumber 的配置恢复脚本,弄清恢复触发条件:
配置恢复机制清楚了。现在查看回切(11:44:38.059)前 9 毫秒内的事件流,找出是谁发起:
bluez-profile-changed钩子只保存不设置,已排除。现在怀疑是 dde-daemon 进程(独立进程,内存里缓存着旧配置 sbc_xq)。查看当前连接的音频客户端:确认关键嫌疑人:
dde-session-daemon(go-pulseaudio 客户端)和dde-control-center都连接着音频服务!dde-daemon 内存里缓存了 sbc_xq,会在检测到配置变化时强制恢复。先检查 audio.json 是否被它写回,然后重启 dde 守护进程使其重新加载:audio.json 保持正确(未被写回)。dde-daemon 运行中缓存了旧值。查找它的 D-Bus 服务,看能否通过接口更新配置或安全重启:
找到
org.deepin.dde.Audio1接口!查看它的方法,看能否通过它正确更新配置:🎯 终极元凶找到! dde 音频守护进程有专门的蓝牙音频模式属性:
BluetoothAudioMode= "a2dp-sink-sbc_xq" ← 它一直在强制这个!SetBluetoothAudioMode(s)方法 ← 正确的修改途径!通过官方接口设置 AAC:
调用报错但属性已变为 a2dp-sink、编码已是 AAC!立即验证稳定性——等待观察是否还会回切:
🎉🎉 AAC 编码稳定保持! 连续 45 秒无回切,dde 与 PipeWire 状态一致。现在收尾:恢复正常服务模式(保留插件目录配置、移除调试日志),并做最终验证:
服务恢复正常(单个实例)。重新连接设备做最终验证:
✅ 最终验证通过!AAC 编码稳定保持! 以下是完整总结:
🎉 切换完成:系统现使用 AAC 蓝牙编码
最终状态
bluetoothAudioCodec: "aac")✅a2dp-sink(AAC)排查过程(为什么之前不行���
libspa-0.2-bluetooth包没有附带libspa-codec-bluez5-aac.so(Debian 官方包同样没有)解决方案(无需 root)
~/.local/lib/spa-0.2/bluez5/libspa-codec-bluez5-aac.so~/.config/systemd/user/wireplumber.service.d/override.conf)设置SPA_PLUGIN_DIR指向用户插件目录org.deepin.dde.Audio1的SetBluetoothAudioMode("a2dp-sink"),更新了 Deepin 音频守护进程的缓存配置⚠️ 注意事项
~/.local/lib/spa-0.2/是镜像的系统插件目录,若 PipeWire 大版本更新,建议重新同步(rm -rf ~/.local/lib/spa-0.2 && cp -a /usr/lib/x86_64-linux-gnu/spa-0.2 ~/.local/lib/spa-0.2再拷贝插件)busctl --user call org.deepin.dde.Audio1 /org/deepin/dde/Audio1 org.deepin.dde.Audio1 SetBluetoothAudioMode s a2dp-sink/tmp/,重启后自动清理,不影响使用现在用 AAC(默认 320 kbps)听音乐,相比 SBC-XQ 在中高频细节和压缩效率上会有更好表现。有其他需要随时告诉我!