984 字
5 分钟
GoldenDict-ng 音频路由问题排查

1. 背景:#

使用GoldenDict-ng的过程中,遇到词典内的音频播放时与默认输出设备不一致的问题,之前凑合着用一直没解决,今天有空就做一下排查。

名称版本
系统内核6.17.0-23-generic
发行版Ubuntu26.04
GoldenDict-ng26.1.1

2. 排查流程#

2.1 先确认系统默认输出设备#

pactlPulseAudio 控制工具。当前系统实际运行 PipeWire,但通过 pipewire-pulse 提供 PulseAudio 兼容层,所以 pactl 仍可查看默认 sink、播放流 sink-input 等信息。

sink 原意是水槽,在音频系统里表示音频流的接收端,也就是输出设备。耳机、扬声器、HDMI 输出都可以是 sink。播放程序产生 streamstream 连接到 sink

Terminal window
pactl get-default-sink

输出为:

bluez_output.44:FB:76:27:4D:D7

说明系统默认输出是蓝牙耳机。

2.2 再看 PipeWire/WirePlumber视角的设备与流#

wpctlWirePlumber/PipeWire 控制工具。

WirePlumberPipeWire 的会话和策略管理器,负责默认设备、流连接、设备切换后的跟随策略等。

Terminal window
wpctl status

得到如下输出:

......
Default Configured Devices:
Audio/Sink bluez_output.44:FB:76:27:4D:D7
......
Streams:
GoldenDict-ng
output_AUX0 > HDMI 0:playback_FL

系统默认是耳机,但 GoldenDict-ng 的实际流走到了 HDMI

2.3 查看 GoldenDict-ng 播放流的具体属性#

Terminal window
pactl list sink-inputs

查看有用的部分:

media.name = "GoldenDict-ng"
node.target = "131"
node.dont-reconnect = "true"
module-stream-restore.id = "sink-input-by-media-role:music"

node.target = "131" 表示该stream明确指定了输出设备为HDMI

node.dont-reconnect = "true" 表示它不希望会话管理器自动重连到别的设备。

2.4 确认 131 是哪个设备#

其实上面已经说明是哪个设备了,不过可以再查一下。

Terminal window
wpctl inspect 131

截取有用的输出部分:

node.description = "AD107 High Definition Audio Controller Digital Stereo (HDMI)"
node.name = "alsa_output.pci-0000_01_00.1.hdmi-stereo"
node.nick = "HDMI 0"

所以 GoldenDict-ng 的流实际绑定到了 HDMI

2.5 查看 WirePlumber 的状态#

排除系统记住了 GoldenDict-ngHDMI 的默认行为。

Terminal window
rg -i "goldendict" ~/.local/state/wireplumber/

这些文件用于保存默认节点、流音量/静音/声道等持久状态。

检查目的不是修复,而是确认是否存在 GoldenDict-ng 专门的路由记录。

结果没有看到 GoldenDict-ng 被绑定到 HDMI 的应用规则。

2.6 用普通 PipeWire 播放流做对照实验。#

pw-playPipeWire 自带的播放测试工具,属于 pw-cat 工具组。它可以直接通过 PipeWire 创建播放流,适合做路由对照实验。

先生成静音音频:

Terminal window
ffmpeg -hide_banner -loglevel error -f lavfi -i "anullsrc=r=48000:cl=stereo" -t 20 -y "/tmp/gd-route-silence.wav"

再播放:

Terminal window
pw-play "/tmp/gd-route-silence.wav"

同时查看:

Terminal window
wpctl status

对照输出显示:

pw-play
output_FL > vivo TWS Air3 Pro:playback_FL
output_FR > vivo TWS Air3 Pro:playback_FR

这说明普通 PipeWire native 播放流会正确走耳机。

GoldenDict-ng 同时仍显示走 HDMI,问题不在 PipeWire 全局默认路由,而是 GoldenDict-ng/Qt 内部播放器路径。

3. 结论#

通过查阅以下文档:

GoldenDict-ng 仓库

GoldenDict-ng 外部播放器文档

GoldenDict-ng FFmpeg 音频输出实现

Qt QAudioSink 文档

Qt QMediaDevices 文档

PipeWire pw-cat/pw-play 文档

确认GoldenDict-ng 使用内部 FFmpeg 播放器时,音频解码本身并不是引发问题的原因。

问题出在内部播放器创建音频输出流时,Qt/PipeWire 路径把流固定到了 HDMI 输出,而不是当前系统默认耳机。

这通常是因为 Qt6 的多媒体后端在枚举音频设备时存在 bug,或者在与 PipeWire/ALSA 兼容层交互时获取了错误的默认设备 ID,导致其触发了 node.dont-reconnect = "true"

当前的方案是把 GoldenDict-ng 的音频播放器改为外部播放器:

Terminal window
mpv --no-video --no-audio-display

mpv 一样用 FFmpeg/Libav 做解码,只不过 mpv 会自己创建 PipeWire/PulseAudio 音频流,所以走的输出设备跟当前系统的默认输出设备一致。

对于我自己做的配置维护脚本,针对GoldenDict-ng,目前的设置为:

只在检测到配置仍是内部播放器 + FFmpeg时,设置播放源切换到外部 mpv

如果已经改成 VLCffplay、其他外部播放器或其他内部后端,脚本不会做出更改,避免不正确的覆盖行为。

GoldenDict-ng 音频路由问题排查
https://blog.astro777.cfd/posts/debug/troubleshooting-goldendict-ng-audio-routing-issue/
作者
ASTRO
发布于
2026-05-12
许可协议
CC BY-NC-SA 4.0