由于部署飞牛nas的那台电脑连接着唯一的音箱,另外一台电脑无音箱可用,希望通过网络将音频传输到飞牛,之前使用shairport-sync方式,现在改为基于pipewire的netjack2模块来实现。
飞牛目前基于debian 12,自带的pipewire版本太老,另外一台电脑系统是archlinux,pipewire版本是最新的1.6.2,担心二者不兼容,所以考虑升级飞牛的pipewire。
升级方式,使用debian的打包系统,基于pipewire源码重新构建,生成deb格式的安装包。整个过程在docker中进行,最后将生成的deb包复制到主机中安装,这样可以避免在fnos中安装编译工具及依赖。
环境准备
- 创建编译容器,使用debian:12.13的镜像,以便和fnos基础库文件兼容
- 在容器内部,修改镜像源,增加bookworm-backports和src源
root@6c376f9a79d7:~/pipewire-deb/pipewire-1.6.2# cat /etc/apt/sources.list.d/debian.sources
Types: deb
URIs: https://mirrors.tuna.tsinghua.edu.cn/debian
Suites: bookworm bookworm-updates bookworm-backports
Components: main contrib
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
Types: deb-src
URIs: https://mirrors.tuna.tsinghua.edu.cn/debian
Suites: bookworm bookworm-updates bookworm-backports
Components: main contrib
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
- 进入容器内部,安装编译依赖
apt update
apt -t bookworm-backports install -y build-essential devscripts debhelper meson cmake pkg-config
apt -t bookworm-backports build-dep -y pipewire
- 下载pipewire 1.6.2的源代码
- 下载源码仓库中的pipewire,获取打包deb所需的文件
mkdir build
cd build
apt -t bookworm-backports source pipewire
# 执行之后目录中的内容
root@6c376f9a79d7:~/build# ls -1 --color
pipewire-1.4.2
pipewire_1.4.2-1~bpo12+1.debian.tar.xz
pipewire_1.4.2-1~bpo12+1.dsc
pipewire_1.4.2.orig.tar.bz2
- 解压最新版本pipewire源码到build目录中,复制打包脚本到源码目录
root@6c376f9a79d7:~/build# tar -xf ../pipewire-1.6.2.tar.gz -C .
root@6c376f9a79d7:~/build# ls -1
pipewire-1.4.2
pipewire-1.6.2
pipewire_1.4.2-1~bpo12+1.debian.tar.xz
pipewire_1.4.2-1~bpo12+1.dsc
pipewire_1.4.2.orig.tar.bz2
root@6c376f9a79d7:~/build# cp -r pipewire-1.4.2/debian/ pipewire-1.6.2/
升级打包脚本
- 修改changelog文件,格式要完全一致,不能随意添加或减少空格
pipewire (1.6.2-1~bpo12+1) bookworm-backports; urgency=medium
* Rebuild for bookworm-backports.
* use latest source code for fnos
-- Dylan Aïssi <daissi@debian.org> Thu, 26 Mar 2026 11:54:22 +0800
- 删除补丁文件:rm debian/patches/*
- 修改以下文件,避免编译错误
apt install libspandsp-dev -t bookworm-backports
# 修改debian/rules 文件
-Dbluez5-codec-ldac-dec=disabled \
-Donnxruntime=disabled \
-Dlibcamera=disabled \
-Dtest=disabled \
-Dinstalled_tests=disabled \
# -c4 改为 -c0
dh_makeshlibs --nosymbols \
--exclude=/usr/lib/$(DEB_HOST_MULTIARCH)/gstreamer-1.0 \
--exclude=/usr/lib/$(DEB_HOST_MULTIARCH)/pipewire-0.3 \
--exclude=/usr/lib/$(DEB_HOST_MULTIARCH)/spa-0.2 \
-- -c0
# debian/libspa-0.2-libcamera.install 注释一行
root@6c376f9a79d7:~/build/pipewire-1.6.2/debian# cat libspa-0.2-libcamera.install
#usr/lib/*/spa-0.2/libcamera/libspa-libcamera.so
# 在debian/pipewire-bin.install 文件中添加
usr/bin/pw-midi2play
usr/bin/pw-midi2record
usr/bin/pw-sy**
# 从文件中删除一些内容
文件:libspa-0.2-modules.install
usr/lib/*/spa-0.2/test
文件:pipewire-tests.install
usr/libexec/installed-tests
usr/share/installed-tests
- 执行打包
root@6c376f9a79d7:~/build/pipewire-1.6.2/debian# debuild -us -uc -b
完成之后会在build目录生成安装包:
root@6c376f9a79d7:~/build# ls -1 --color *.deb|tail -n 10
pipewire-bin_1.6.2-1~bpo12+1_amd64.deb
pipewire-doc_1.6.2-1~bpo12+1_all.deb
pipewire-jack-dbgsym_1.6.2-1~bpo12+1_amd64.deb
pipewire-jack_1.6.2-1~bpo12+1_amd64.deb
pipewire-libcamera_1.6.2-1~bpo12+1_all.deb
pipewire-pulse_1.6.2-1~bpo12+1_amd64.deb
pipewire-tests_1.6.2-1~bpo12+1_amd64.deb
pipewire-v4l2-dbgsym_1.6.2-1~bpo12+1_amd64.deb
pipewire-v4l2_1.6.2-1~bpo12+1_amd64.deb
pipewire_1.6.2-1~bpo12+1_amd64.deb
- 安装软件包
# 将软件包从容器中复制到主机中,然后安装
apt install ./pipewire_1.6.2-1~bpo12+1_amd64.deb \
./pipewire-bin_1.6.2-1~bpo12+1_amd64.deb \
./pipewire-alsa_1.6.2-1~bpo12+1_amd64.deb \
./pipewire-jack_1.6.2-1~bpo12+1_amd64.deb \
./pipewire-pulse_1.6.2-1~bpo12+1_amd64.deb \
./libpipewire-0.3-0_1.6.2-1~bpo12+1_amd64.deb \
./libspa-0.2-modules_1.6.2-1~bpo12+1_amd64.deb
netjack2模块配置
# netjack 替换为要使用的普通用户
sudo loginctl enable-linger netjack
- 配置pipewire的netjack2模块
在连接音箱的电脑中配置
// netjack@fnos:~/.config/pipewire/pipewire.conf.d$ cat netjack2.conf
context.modules = [
{ name = libpipewire-module-netjack2-manager
args = {
local.ifname = enp0s31f6-ovs
net.loop = false
net.ip = 225.3.19.154
net.port = 19000
net.mtu = 1500
net.ttl = 1
netjack2.sample-rate = 48000
netjack2.period-size = 1024
netjack2.encoding = float
netjack2.kbps = 64
audio.ports = 2
midi.ports = 0
audio.channels = 2
audio.position = [ FL FR ]
source.props = {
netjack2.connect = true
node.autoconnect = true
node.name = jack2_source
node.description = jack2_fnos_source
media.class = Stream/Output/Audio
target.object = alsa_output.pci-0000_00_1f.3.**og-stereo
}
sink.props = {
netjack2.connect = true
node.autoconnect = true
node.name = jack2_sender
node.description = jack2_fnos_sink
media.class = Stream/Input/Audio
target.object = alsa_input.pci-0000_00_1f.3.**og-stereo
}
}
}
]
target.object 参数指定的设备可以通过pw-link命令查看:
netjack@fnos:~$ pw-link -i
Midi-Bridge:Midi Through Port-0 (playback)
alsa_output.pci-0000_00_1f.3.**og-stereo:playback_FL
alsa_output.pci-0000_00_1f.3.**og-stereo:playback_FR
alsa_output.platform-pcspkr.mono-fallback:playback_MONO
jack2_sender:send_FL
jack2_sender:send_FR
netjack@fnos:~$ pw-link -o
Midi-Bridge:Midi Through Port-0 (capture)
alsa_output.pci-0000_00_1f.3.**og-stereo:monitor_FL
alsa_output.pci-0000_00_1f.3.**og-stereo:monitor_FR
alsa_input.pci-0000_00_1f.3.**og-stereo:capture_FL
alsa_input.pci-0000_00_1f.3.**og-stereo:capture_FR
alsa_output.platform-pcspkr.mono-fallback:monitor_MONO
jack2_source:receive_FL
jack2_source:receive_FR
mpd.pipewire:output_FL
mpd.pipewire:output_FR
在没有连接音箱的电脑中配置
//[netjack@optiplex pipewire.conf.d]$ cat netjack2.conf
context.modules = [
{ name = libpipewire-module-netjack2-driver
args = {
driver.mode = duplex
local.ifname = br0
net.ip = 225.3.19.154
net.port = 19000
net.mtu = 1500
net.ttl = 1
net.loop = false
source.ip = 0.0.0.0
source.port = 0
netjack2.client-name = Pipewire
netjack2.latency = 2
midi.ports = -1
audio.ports = -1
audio.channels = 0
audio.position = [ FL FR ]
source.props = {
}
sink.props = {
}
}
}
]
drive.mode 设置为 duplex时,不仅可以使用远程音箱,还可以使用远程麦克风,设置为sink时,表示仅使用远程的音箱。
实测设置为sink时,manager端一直打印错误日志,改为duplex后日志就消失了。
systemctl --user restart pipewire.service wireplumber.service
启动之后,在无音箱的电脑中查看,系统声音设置中会多出一个输出设备,输入设备也会多一个远程的输入。
在飞牛系统中查看,有连接建立:
Audio
**─ Devices:
** 44. Built-in Audio [alsa]
** 45. Built-in Audio [alsa]
**
**─ Sinks:
** * 49. Built-in Audio **og Stereo [vol: 1.00]
** 51. Built-in Audio Mono [vol: 0.40]
**
**─ Sources:
** 50. Built-in Audio **og Stereo [vol: 1.00]
**
**─ Filters:
**
**─ Streams:
60. jack2_sender
63. send_FR < ALC3234 **og:capture_FR [active]
64. send_FL < ALC3234 **og:capture_FL [active]
61. jack2_source
67. receive_FL > ALC3234 **og:playback_FL [active]
68. receive_FR > ALC3234 **og:playback_FR [active]
62. Music Player Daemon
73. output_FL > ALC3234 **og:playback_FL [paused]
74. output_FR > ALC3234 **og:playback_FR [paused]
这时无论是播放音乐,还是网页看视频直播,都会通过飞牛连接的音箱进行播放,就像是本机连接的音箱一样。
对比及其它
之前一直基于shairport-sync配置airplay2服务使用,也可以将音频通过网络传输,但在arch的pipewire更新到1.6之后,突然不能用了。发现pipewire还支持rtp和netjack,也可以实现这个效果,在经过一阵子探索配置成功之后,这里记录一下。
实际使用后发现,同样都是使用有线网络连接,netjack的延迟几乎感知不到,而之前airplay2能明显感到大约有半秒的延迟,shairport-sync这个方案可以丢掉了。
mpd + upmpdcli 可以将音箱作为upnp服务暴露出来,我在飞牛的虚拟机中安装了一个innuos的系统,用来做音乐播放,就是使用的upnp连接的,使用的是同一个音箱。
编译生成的安装包:pipewire.tar.gz 提取码: hp2f