Using Pipewire with HDMI

This was harder to find out how to do than I'd expected, which may, of course, be due to my lack of web skills, but at any rate, I'm putting this up so I don't have to look again.

This was done on a minimal Fedora install, a small Arch install, and a Voidlinux install. All used openbox as the window manager, I suspect that it may be even simpler in desktop environments like Gnome.

My use case is occasionally connecting a laptop, through an HDMI cable, to a large TV. I wanted it to automatically use the TV's speaker when connected and the laptop's speakers when not. I only connect it to the TV infrquently, say for a maximum of an hour or so, a few times a week.

First, you need pipewire and wireplumber. Once you have these installed, you can hook the laptop up to the TV and type, as the user who will be doing this
wpctl status |more

This will give output that will contain, among other things, something like
       40. Built-in Audio                      [alsa]
       41. Built-in Audio                      [alsa]

      44. Built-in Audio Digital Stereo (HDMI) [vol: 0.74]
     * 45. Built-in Audio Analog Stereo        [vol: 0.72]

You'll want to pipe it through more or less as I did in the example as there will be a lot of output. Anyway, in that example, you see that the HDMI sink is number 44. Now set it as default.
wpctl set-default 44

It will now use the HDMI when it is plugged in. If it's not attached to the TV it will use the laptop speakers. In my experience, once I unplug it, I have to get out of X and restart it, for the sound to change. But for my needs, this isn't a big deal.


With Voidlinux, and probably others that don't use systemd, it's a little more complicated, but not terribly so. Aside from pipewire and wireplumber, you'll need to install rtkit. You also have to set the $XDG_RUNTIME_DIR. If you don't do these two things, pipewire will fail to start.

On Voidlinux, you can install elogind, which will automatically set the $XDG_RUNTIME_DIR variable without any further action on your part. However, many who use Void prefer to not use systemd associated programs. So, if you don't wish to use elogind, just set the path in your $HOME/.bash_profile. Add to the end of your .bash_profile
export XDG_RUNTIME_DIR=$(mktemp -d /tmp/$(id -u)-runtime-dir.XXX)

Note that that is exactly what you type, dir.XXX. When it's created it will take a specific name but your .bash_profile should have the letters XXX as shown.

If you do this and install rtkit with sudo xbps-install -Sy rtkit, pipewire will start. It may give some messages, but start it with pipewire &, and it will run happily in the background. Another option, and what I use, is dmenu which I run in openbox. I open dmenu, type pipewire, and I can then run the wpctl status command mentioned earlier.

For my use, when I don't have it hooked to the TV, I don't even need pipewire. So, I can, if just running the laptop, not even use the pipewire command and get sound through the speakers. Therefore, I only run pipewire (through dmenu) when hooking it up to the TV. I assume, though I haven't tried it, that one could also add pipewire & above the line that calls the window manager in .xinitrc, but again, I only need it on occasion.

FreeBSD does have pipewire, but doesn't have the wpctl command. To switch between laptop and HDMI speakers, one can cat /dev/sndstat to see what you have. For example, my T495 Thinkpad's /dev/sndstat is
Installed devices:
pcm0: <ATI R6xx (HDMI)> (play)
pcm1: <ATI R6xx (HDMI)> (play)
pcm2: <ATI R6xx (HDMI)> (play)
pcm3: <Realtek ALC257 (Analog 2.0+HP/2.0)> (play/rec) default
pcm4: <Realtek ALC257 (Right Analog Mic)> (rec)
No devices installed from userspace.

Note that the default is pcm3, which refers to the laptop speakers. To get it to use HDMI, I can edit it on the fly with
sysctl hw.snd.default_unit=1

This switches the default to HDMI. Once disconnected from the TV, I can go back to the laptop speakers with
sysctl hw.snd.default_unit=3

If you use this frequently, it might be worth making a shell script.

I hope that this helps the reader to quickly and easily use pipewire with HDMI speakers. Some of the docs that I found were lacking in information while others seemed to overcomplicate it. I hope this strikes a happy medium.