资讯详情

资讯详情

Audio学习7(PipeWire/PulseAudio)

1 概念PipeWire 是一个由 Red Hat 主导、目前已成为 Linux 桌面音频/视频服务基座的现代多媒体框架它在同一套体系内统一处理音频采集与播放、视频/摄像头流以及跨应用的实时信号路由核心特点是以有向图graph方式组织节点和链路让多个应用可以同时读写同一设备、自由组合输入输出并天然支持低延迟的 Pro-Audio 实时调度对比旧方案它同时取代了 PulseAudio 的通用混音与 JACK 的专业低延迟且默认与 PulseAudio 和 JACK 兼容可平滑接管二者的协议与客户端。相比前辈PipeWire 的优势在于图式动态重连、强安全隔离会话与设备权限由系统策略控制、低延迟高精度时钟、以及对 Flatpak/Snap 等容器化应用的透明支持。它由 systemd 用户服务管理现已是 Fedora、Debian、Ubuntu 等主流发行版桌面环境的默认音频服务常配合 WirePlumber 作为会话管理器。在具体应用上若是嵌入式/音频开发者PipeWire 常用作音视频中继、虚拟设备如 virtual sink/source以及连接蓝牙、USB、HDMI 等多路音频的统一枢纽。核心功能就是多路音视频流在 CPU 上的统一零拷贝混音/复用、图状路由与低延迟定时调度”。如下可以看到PipeWire往下其实不止ALSA还有蓝牙V4L2等。具体拆解就是统一混音与复用Mixing Compositing音频把多个播放软件浏览器、播放器、游戏产生的不同采样率、不同通道数的 PCM 音频流在 CPU 上统一重采样、格式转换并混音成一路。视频把多个应用如屏幕共享、摄像头捕捉、OBS的视频 Frame 统一管理和分发基于 DMA-BUF 零拷贝传输。图状路由Graph Routing在系统内部构建一个动态节点图Graph。你可以像接音频电缆一样任意把应用 A 的音频输出拉线路由给应用 B比如做录音/效果器处理再路由给硬件扬声器或者把某个窗口的视频流路由给会议软件。硬件调度输出Scheduling Sync作为用户态应用与 ALSA音频驱动/ V4L2视频驱动之间的中介以极低的延迟甚至达到毫秒级的专业 RT 实时调度把混好或路由好的数据包送入硬件缓冲区并严格保证音画同步A/V Sync。2 安装环境是之前的树莓派5WM8960。Audio学习4WM8960的bringup-CSDN博客来自GitHub - mikeroyal/PipeWire-Guide: PipeWire Guide. Learn about how PipeWire gives your Linux system a Professional Audio/Video Processing workflow. · GitHubRun these three commands as your regular user (not as root):Check for new service files with:systemctl --user daemon-reloadDisable and stop the PulseAudio service with:systemctl --user --now disable pulseaudio.service pulseaudio.socketEnable and start the new pipewire-pulse service with:systemctl --user --now enable pipewire pipewire-pulse下面是运行结果tomraspberrypi:~ $ systemctl --user daemon-reload tomraspberrypi:~ $ systemctl --user enable --now pipewire.socket pipewire-pulse.socket Created symlink /home/tom/.config/systemd/user/sockets.target.wants/pipewire.socket → /usr/lib/systemd/user/pipewire.socket. Created symlink /home/tom/.config/systemd/user/sockets.target.wants/pipewire-pulse.socket → /usr/lib/systemd/user/pipewire-pulse.socket. tomraspberrypi:~ $ systemctl --user enable --now pipewire.service wireplumber.service pipewire-pulse.service Created symlink /home/tom/.config/systemd/user/default.target.wants/pipewire.service → /usr/lib/systemd/user/pipewire.service. Created symlink /home/tom/.config/systemd/user/pipewire.service.wants/wireplumber.service → /usr/lib/systemd/user/wireplumber.service. Created symlink /home/tom/.config/systemd/user/default.target.wants/pipewire-pulse.service → /usr/lib/systemd/user/pipewire-pulse.service. tomraspberrypi:~ $ systemctl --user is-active pipewire wireplumber pipewire-pulse active active active查看运行状态tomraspberrypi:~ $ wpctl status -n PipeWire pipewire-0 [1.4.2, tomraspberrypi, cookie:1359508960] └─ Clients: 33. pipewire [1.4.2, tomraspberrypi, pid:2099] 35. WirePlumber [1.4.2, tomraspberrypi, pid:2098] 47. WirePlumber [export] [1.4.2, tomraspberrypi, pid:2098] 74. wpctl [1.4.2, tomraspberrypi, pid:2175] Audio ├─ Devices: │ 48. alsa_card.platform-107c701400.hdmi [alsa] │ 49. alsa_card.platform-107c706400.hdmi [alsa] │ 50. alsa_card.platform-soc_107c000000_sound [alsa] │ ├─ Sinks: │ * 71. alsa_output.platform-soc_107c000000_sound.stereo-fallback [vol: 0.40] │ ├─ Sources: │ * 72. alsa_input.platform-soc_107c000000_sound.stereo-fallback [vol: 1.00] │ ├─ Filters: │ └─ Streams: Video ├─ Devices: │ 54. v4l2_device.platform-1000800000.codec [v4l2] │ 55. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 56. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 57. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 58. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 59. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 60. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 61. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 62. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 63. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 64. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 65. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 66. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 67. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 68. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 69. v4l2_device.platform-1000880000.pisp_be [v4l2] │ 70. v4l2_device.platform-1000880000.pisp_be [v4l2] │ ├─ Sinks: │ ├─ Sources: │ ├─ Filters: │ └─ Streams: Settings └─ Default Configured Devices:这里ID对象含义50DeviceWM8960 这张物理声卡71Sink应用把声音送到这里再通过耳机播放72Source应用从这里获取麦克风录音*默认标记未指定设备的应用优先使用它3 基本功能3.1 录音pw-record --rate48000 --channels2 ~/pipewire-recording.wav此时观察音频图watch -n 0.5 wpctl status -n此时查看端口连接tomraspberrypi:~ $ pw-link -l alsa_input.platform-soc_107c000000_sound.stereo-fallback:capture_FL |- pw-record:input_FL alsa_input.platform-soc_107c000000_sound.stereo-fallback:capture_FR |- pw-record:input_FR pw-record:input_FL |- alsa_input.platform-soc_107c000000_sound.stereo-fallback:capture_FL pw-record:input_FR |- alsa_input.platform-soc_107c000000_sound.stereo-fallback:capture_FRWM8960:capture_FL → pw-record:input_FLWM8960:capture_FR → pw-record:input_FR这里pw-record是应用创建的流节点。3.2 播放pplay ~/pipewire-recording.wav观察结果此时查看端口连接tomraspberrypi:~ $ pw-link -l alsa_output.platform-soc_107c000000_sound.stereo-fallback:playback_FL |- pw-play:output_FL alsa_output.platform-soc_107c000000_sound.stereo-fallback:playback_FR |- pw-play:output_FR pw-play:output_FL |- alsa_output.platform-soc_107c000000_sound.stereo-fallback:playback_FL pw-play:output_FRpw-play:output_FL → WM8960:playback_FLpw-play:output_FR → WM8960:playback_FR4 高级应用4.1 命令行对于基本功能看这几个常用的功能就行了。wpctl status -n 看全局wpctl inspect 看对象pw-link -l 看连线pw-link / -d 连线、断线pw-record 录音pw-play 播放例子1应用节点存在时可以没有声音建立到声卡的连接后声音才能送出去。//播放此时只有播放没有任何路由pw-play --target0 ~/pipewire-test-tone.wav//连接到左声道pw-link pw-play:output_FL alsa_output.platform-soc_107c000000_sound.stereo-fallback:playback_FL//查看连接pw-link -lalsa_output.platform-soc_107c000000_sound.stereo-fallback:playback_FL|- pw-play:output_FLpw-play:output_FL|- alsa_output.platform-soc_107c000000_sound.stereo-fallback:playback_FL例子2混音//终端1播放pw-play ~/pipewire-test-long.wav//终端2播放pw-play ~/pipewire-recording.wav//此时能同时听到两个声音。路径如下当两个播放流连接到同一个 Sink 时PipeWire 会处理格式转换、音量和混音再把结果送到声卡。此时PipeWire可以针对某一路单独控制。例子3Monitor//启动一个不自动连接麦克风的录音流pw-record --target0 ~/monitor-test.wav//保持它运行再把 Sink 的 monitor_FL/FR 分别连到录音程序的 input_FL/FR。此时播放测试音录音文件就能收到播放链路中的声音。4.2 图形工具工具主要用途与已学命令的对应qpwgraph显示节点、端口和连线鼠标连接断开支持 Patchbay 连接规则类似图形版pw-linkHelvum较简洁的节点连线界面也是图形化音频图pavucontrol应用音量、静音、输入输出选择、设备配置覆盖部分wpctl操作通过pipewire-pulse工作qpwgraphpavucontrol4.3 低延迟这个功能感觉大部分是硬件不过软件也可以控制一部分。这里以麦克风实时监听为例麦克风 → ADC → 驱动缓冲 → PipeWire → 音效处理 → 驱动缓冲 → DAC → 耳机环节主要由谁决定PipeWire 能做什么ADCDAC 转换、芯片内部滤波硬件通常只能间接通过设备支持的参数影响声卡传输与 DMA 缓冲硬件驱动通过 ALSA 协商采样率、缓冲等参数音频图每次处理多少数据PipeWire调整quantum节点唤醒、执行顺序软件调度操作系统安排处理顺序、申请实时调度音效、重采样等处理软件算法管理处理节点但算法本身也可能引入延迟这里PipeWire可以控制缓冲大小。 假设采样率为 48 kHz一批处理的帧数对应音频时长102421.33 ms2565.33 ms1282.67 ms基本上硬件决定了能力和下限PipeWire 决定如何在这些条件下组织处理在低延迟与稳定性之间取舍。 同一套硬件用大缓冲和用小缓冲实际延迟可以相差很大。在之前的练习中就尝试了采集麦克风的帧大小Audio学习2麦克风和喇叭-CSDN博客。5 APP层的使用一般来说要使用这一套功能就要用PipeWire的接口。不过PipeWire 在设计之初就考虑到了兼容性它提供了完备的垫片Shim/Emulation Library和透明兼容层。ALSA 应用直连底层驱动的轻量应用/嵌入式程序 PipeWire 提供了pipewire-alsa插件libasound_module_pcm_pipewire.so。应用以为自己是在直接向 ALSA 设备写 PCM 数据实际数据被偷偷重定向到了 PipeWire 的 Graph 中。PulseAudio 应用绝大多数桌面应用如 Chrome、Firefox、网易云音乐 PipeWire 实现了pipewire-pulse服务提供了一个和 PulseAudio 一模一样的 UNIX Socket 接口。应用发给 PulseAudio 的音频指令和数据直接由 PipeWire 接管解析。JACK 专业音频应用如 Ardour、REAPER、FL Studio Linux 版 PipeWire 提供了pipewire-jack替换库。应用调用的libjack.so被替换为 PipeWire 的实现瞬间获得低延迟的专业路由能力。直接使用pipewire当然是现在更好的选择一个简单的播放例子如下#include stdio.h #include math.h #include spa/param/audio/format-utils.h #include spa/pod/builder.h #include pipewire/pipewire.h struct data { struct pw_main_loop *loop; struct pw_stream *stream; float phase; }; // 核心音频处理回调函数当 PipeWire 需要新数据时会触发此函数 static void on_process(void *userdata) { struct data *data userdata; struct pw_buffer *b; struct spa_buffer *buf; float *samples; int n_frames, n_channels; int i, c; // 1. 从管道中获取一个可写缓冲区 b pw_stream_dequeue_buffer(data-stream); if (!b) return; buf b-buffer; if (!buf-datas[0].data) return; samples buf-datas[0].data; n_channels 2; // 双声道立体声 n_frames buf-datas[0].maxsize / (sizeof(float) * n_channels); // 2. 实时生成 440 Hz 正弦波填充缓冲区 for (i 0; i n_frames; i) { // 生成幅值为 0.2 的正弦波防止声音过大 float val sinf(data-phase) * 0.2f; // 步进相角2 * pi * 频率 / 采样率 ># ~/.config/wireplumber/wireplumber.conf.d/50-my-card.conf monitor.alsa.rules [ { matches [ { node.name alsa_output.pci-0000_00_1f.3.analog-stereo } ] actions { update-props { node.description 我的内置扬声器 node.nick Speaker priority.driver 100 } } } ]7 PulseAudioPulseAudio 是一个运行在应用和 ALSA 之间的音频服务主要解决桌面上多个应用共享音频设备的问题。它提供的典型功能包括多个应用同时播放并混音。每个应用独立调音量、静音。选择默认麦克风和输出设备。将应用声音切换到耳机、HDMI、蓝牙等设备。通过输出的 Monitor 录制系统声音。不过目前PipeWire 覆盖的场景更广又能承接原来的应用生态。所以基本上都升级到PipeWire了。这里也就不重点看了。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →