🛠️ PipeWire on DietPi (Headless Raspberry Pi + HiFiBerry ADC)

This guide sets up PipeWire as system services tied to the dietpi user, allowing multiple applications (e.g.

  • Actualizado el 7 oct 2026
  • 5 min de lectura
  • Para: organizadores

Esta página aún no está traducida al español. Estás leyendo la versión en inglés.

This guide sets up PipeWire as system services tied to the dietpi user, allowing multiple applications (e.g. InterScribe agent + monitoring tools) to access HiFiBerry ADC simultaneously with low latency.

HiFiBerry ADC devices, when accessed directly through ALSA, can sometimes exhibit quirks or limited compatibility—especially with applications like the InterScribe Agent that expect multi-client audio access. ALSA by itself does not natively allow multiple programs to capture from the same device at once, and some applications may not work reliably with certain ALSA plugins. PipeWire acts as a unified sound server that greatly improves compatibility: it enables simultaneous access from multiple apps, provides a modern replacement for both PulseAudio and JACK, and avoids many of the limitations and device-specific issues found with direct ALSA access.

By default, DietPi doesn’t run systemd --user sessions, so we run PipeWire as system services for the dietpi user.


1. Install required packages

sudo apt update
sudo apt install -y pipewire pipewire-pulse wireplumber pipewire-bin pulseaudio-utils rtkit dbus-user-session libasound2-plugins
  • libasound2-plugins is required so ALSA apps can see/use pcm.pulse → PipeWire.

2. Create runtime + DBus session service

PipeWire expects /run/user/<UID> with correct ownership and permissions. We create a helper service to provide this for dietpi.

sudo tee /etc/systemd/system/dietpi-user-runtime.service >/dev/null <<'EOF'
[Unit]
Description=Create /run/user and session bus for dietpi
After=systemd-logind.service
Wants=systemd-logind.service

[Service]
Type=simple
User=dietpi
Group=audio
PermissionsStartOnly=yes
ExecStartPre=/bin/mkdir -p /run/user/1000
ExecStartPre=/bin/chown dietpi:audio /run/user/1000
ExecStartPre=/bin/chmod 700 /run/user/1000
Environment=XDG_RUNTIME_DIR=/run/user/1000
ExecStart=/usr/bin/dbus-daemon --session --address=unix:path=/run/user/1000/bus --nofork
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now dietpi-user-runtime.service

Verify:

ls -ld /run/user/1000      # expect: drwx------ dietpi audio
ls -l  /run/user/1000/bus  # should be a socket

3. Create PipeWire services for dietpi

PipeWire

sudo tee /etc/systemd/system/pipewire-dietpi.service >/dev/null <<'EOF'
[Unit]
Description=PipeWire for dietpi (headless)
After=dietpi-user-runtime.service
Requires=dietpi-user-runtime.service

[Service]
Type=simple
User=dietpi
Group=audio
Environment=HOME=/home/dietpi
Environment=TMPDIR=/tmp
Environment=XDG_RUNTIME_DIR=/run/user/1000
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
ExecStartPre=-/bin/rm -f /run/user/1000/pipewire-0 /run/user/1000/pipewire-0.lock
ExecStart=/usr/bin/pipewire
Restart=always
RestartSec=2
LimitRTPRIO=95
LimitMEMLOCK=infinity

[Install]
WantedBy=multi-user.target
EOF

WirePlumber

sudo tee /etc/systemd/system/wireplumber-dietpi.service >/dev/null <<'EOF'
[Unit]
Description=WirePlumber (session manager) for dietpi
After=pipewire-dietpi.service
Requires=pipewire-dietpi.service

[Service]
Type=simple
User=dietpi
Group=audio
Environment=HOME=/home/dietpi
Environment=TMPDIR=/tmp
Environment=XDG_RUNTIME_DIR=/run/user/1000
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
ExecStart=/usr/bin/wireplumber
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target
EOF

PulseAudio shim

sudo tee /etc/systemd/system/pipewire-pulse-dietpi.service >/dev/null <<'EOF'
[Unit]
Description=PipeWire PulseAudio compatibility for dietpi
After=pipewire-dietpi.service
Requires=pipewire-dietpi.service

[Service]
Type=simple
User=dietpi
Group=audio
Environment=HOME=/home/dietpi
Environment=TMPDIR=/tmp
Environment=XDG_RUNTIME_DIR=/run/user/1000
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
ExecStartPre=-/bin/rm -f /run/user/1000/pulse/native
ExecStart=/usr/bin/pipewire-pulse
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target
EOF

Enable them:

sudo systemctl daemon-reload
sudo systemctl enable --now pipewire-dietpi wireplumber-dietpi pipewire-pulse-dietpi

4. Configure InterScribe Agent audio settings

To ensure the InterScribe Agent uses the correct audio server, you must configure /etc/default/interscribe-agent.

Preferred method: Set the PULSE_SERVER environment variable. This makes the agent independent of the system's default source and more robust, as it connects directly to the PulseAudio (PipeWire) server socket.

Example /etc/default/interscribe-agent:

# Recommended: Point directly to the PulseAudio (PipeWire) server socket
PULSE_SERVER=unix:/run/user/1000/pulse/native

# Alternative (not recommended): Use PULSE_SOURCE to select a specific input device by name
# PULSE_SOURCE=alsa_input.platform-soc_107c000000_sound.stereo-fallback

Note: Using PULSE_SERVER is recommended. PULSE_SOURCE can be used to select a specific input if needed, but may be less robust if device names change.


5. Expose a pipewire ALSA device

To make pipewire appear in ALSA device lists:

sudo tee /etc/asound.conf >/dev/null <<'EOF'
pcm.pipewire {
    type pulse
    hint.description "PipeWire Sound Server"
}
ctl.pipewire {
    type pulse
}

pcm.!default {
    type pulse
    fallback "hw:CARD=sndrpihifiberry,DEV=0"
    hint.description "PipeWire (Default)"
}
ctl.!default {
    type pulse
    fallback "hw:CARD=sndrpihifiberry,DEV=0"
}
EOF

Now apps that enumerate ALSA devices will show pipewire as an option.


6. Export environment in your shell

PipeWire needs these environment variables in your dietpi session. Add them to ~/.profile so they persist:

export XDG_RUNTIME_DIR=/run/user/1000
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

Load them immediately:

source ~/.profile

7. Verify PipeWire

Check the PulseAudio shim is active:

pactl info | grep "Server Name"
# Expect: Server Name: PulseAudio (on PipeWire 0.3.x)

List inputs:

pactl list short sources
# You should see your HiFiBerry ADC as alsa_input.platform-soc_107c000000_sound.stereo-fallback

Set HiFiBerry as default:

pactl set-default-source alsa_input.platform-soc_107c000000_sound.stereo-fallback

Test recording:

parecord /tmp/test.wav   # Ctrl+C after a few seconds
aplay /tmp/test.wav

8. Low-latency tuning (optional)

Create config override:

mkdir -p ~/.config/pipewire/pipewire.conf.d
nano ~/.config/pipewire/pipewire.conf.d/10-lowlatency.conf

Contents:

context.properties = {
    default.clock.rate          = 48000
    default.clock.quantum       = 128
    default.clock.min-quantum   = 32
    default.clock.max-quantum   = 2048
}

Restart services:

sudo systemctl restart pipewire-dietpi wireplumber-dietpi pipewire-pulse-dietpi

12. [Optional] Enable System D-Bus + RTKit (Cleaner Logs + Realtime Scheduling)

On DietPi, PipeWire and WirePlumber may log warnings like:

Failed to connect to system bus: No such file or directory
Realtime scheduling disabled: insufficient realtime privileges

This happens because DietPi doesn’t run the system D-Bus or RTKit by default. Audio still works, but logs may look noisy and realtime scheduling isn’t used.

✅ Enable system D-Bus and RTKit

sudo apt update
sudo apt install -y dbus rtkit
sudo systemctl enable --now dbus

Verify the socket:

ls -l /run/dbus/system_bus_socket

Restart PipeWire services:

sudo systemctl restart dietpi-user-runtime pipewire-dietpi wireplumber-dietpi pipewire-pulse-dietpi

After this, the “system bus” and “realtime scheduling disabled” warnings should disappear, and PipeWire can make use of RTKit for low-latency scheduling.


10. Troubleshooting

🧪 Quick health check (copy/paste)

Run these as the dietpi user (not root):

# Ensure your shell points to the correct runtime/bus
export XDG_RUNTIME_DIR=/run/user/1000
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

echo "== runtime =="
ls -ld /run/user/1000 || echo "MISSING: /run/user/1000"
ls -l  /run/user/1000/bus          || echo "MISSING: bus socket"
ls -l  /run/user/1000/pulse/native || echo "MISSING: pulse/native"

echo "== services =="
systemctl --no-pager -l status dietpi-user-runtime pipewire-dietpi wireplumber-dietpi pipewire-pulse-dietpi || true

echo "== pactl =="
pactl --server="$XDG_RUNTIME_DIR/pulse/native" info || echo "pactl failed"

If /run/user/1000 is missing or the bus/pulse/native sockets are missing, see the items below.


/run/user/1000 missing (or wrong owner/permissions)

/run is a tmpfs and resets on boot. Recreate and restart in order:

# replace 1000 with your actual UID if different
id -u dietpi
sudo systemctl stop pipewire-dietpi pipewire-pulse-dietpi wireplumber-dietpi || true
sudo mkdir -p /run/user/1000
sudo chown dietpi:audio /run/user/1000
sudo chmod 700 /run/user/1000
sudo systemctl restart dietpi-user-runtime
sudo systemctl start pipewire-dietpi wireplumber-dietpi pipewire-pulse-dietpi

Check why the shim didn’t create it:

sudo journalctl -u dietpi-user-runtime -n 80 --no-pager

(Optional hardening) Create a tmpfiles rule so the directory exists early at boot:

echo "d /run/user/1000 0700 dietpi audio -" | sudo tee /etc/tmpfiles.d/dietpi-user.conf
sudo systemd-tmpfiles --create /etc/tmpfiles.d/dietpi-user.conf

PipeWire won’t start (status=245/254) or WirePlumber exits (status=69)

Common causes & fixes:

# 1) Ownership/permissions on the runtime dir
ls -ld /run/user/1000
sudo chown dietpi:audio /run/user/1000
sudo chmod 700 /run/user/1000

# 2) Stale lock/socket files
sudo rm -f /run/user/1000/pipewire-0 /run/user/1000/pipewire-0.lock /run/user/1000/pulse/native

# 3) Ensure a machine-id exists for D-Bus
[ -s /etc/machine-id ] || sudo systemd-machine-id-setup

# 4) Kill legacy pulseaudio if it’s running (rare on DietPi)
pgrep -a pulseaudio || true
sudo killall pulseaudio 2>/dev/null || true

# 5) Restart in order
sudo systemctl restart dietpi-user-runtime
sudo systemctl restart pipewire-dietpi wireplumber-dietpi pipewire-pulse-dietpi

# 6) Foreground debug (shows the exact error)
sudo -u dietpi \
  XDG_RUNTIME_DIR=/run/user/1000 \
  DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
  PIPEWIRE_DEBUG=4 \
  /usr/bin/pipewire

Also inspect logs:

sudo journalctl -u pipewire-dietpi -u wireplumber-dietpi -u pipewire-pulse-dietpi -n 120 --no-pager

pactl says “Connection refused”

  • Make sure pipewire-pulse-dietpi is active:
    systemctl --no-pager -l status pipewire-pulse-dietpi
  • Ensure your shell has the right env set:
    export XDG_RUNTIME_DIR=/run/user/1000
    export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
    pactl --server="$XDG_RUNTIME_DIR/pulse/native" info
  • If you must run with sudo, target the dietpi runtime:
    sudo -u dietpi XDG_RUNTIME_DIR=/run/user/1000 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus pactl info

PipeWire not listed in ALSA apps

  • Confirm the plugin package is installed:
    dpkg -l | grep libasound2-plugins
  • Ensure /etc/asound.conf defines pcm.pipewire and ctl.pipewire as shown above.
  • Restart apps (some cache ALSA device lists).

View live logs

Follow everything at once:

sudo journalctl -u dietpi-user-runtime -u pipewire-dietpi -u wireplumber-dietpi -u pipewire-pulse-dietpi -f

11. [Optional] Using Multiple Input Devices (Without Changing Default)

By default, PipeWire will expose all connected capture devices (HiFiBerry, USB mics, webcams, etc.). Only one device is set as the default input, but you can still access others explicitly without changing defaults.

🔹 1. List available input devices

pactl list short sources

Example output:

alsa_input.platform-soc_107c000000_sound.stereo-fallback
alsa_input.usb-Generic_AB13X_USB_Audio_20210926172016-00.mono-fallback
  • The first is the HiFiBerry Studio ADC (default).
  • The second is a USB microphone.

🔹 2. Use another device temporarily

Instead of changing the default, run your app with the desired source:

PULSE_SOURCE=alsa_input.usb-Generic_AB13X_USB_Audio_20210926172016-00.mono-fallback my-app

This launches my-app using the USB mic while the system keeps HiFiBerry as default.


🔹 3. Test with parecord

parecord --device=alsa_input.usb-Generic_AB13X_USB_Audio_20210926172016-00.mono-fallback /tmp/usb-test.wav
aplay /tmp/usb-test.wav

🔹 4. Make a friendly ALSA alias (optional)

If your app only enumerates ALSA devices and doesn’t understand PipeWire names, you can define an alias:

sudo tee -a /etc/asound.conf >/dev/null <<'EOF'

pcm.usbmic {
    type pulse
    device "alsa_input.usb-Generic_AB13X_USB_Audio_20210926172016-00.mono-fallback"
    hint.description "USB Microphone (via PipeWire)"
}
EOF

Now the USB mic will appear in ALSA device lists as:

usbmic   USB Microphone (via PipeWire)

12. Common Log Messages (Safe to Ignore)

When using ALSA and PipeWire together, you may occasionally see warnings like:

ALSA lib pcm_dsnoop.c:566:(snd_pcm_dsnoop_open) unable to open slave
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
ALSA lib pcm_oss.c:397:(_snd_pcm_oss_open) Cannot open device /dev/dsp

These messages appear because:

  • dsnoop warnings → the ALSA dsnoop plugin only supports capture. Apps probing playback may trigger these harmless errors.
  • jack server is not running → some apps probe JACK even if you don’t use it. PipeWire can handle JACK apps if you install pipewire-jack, but otherwise these warnings can be ignored.
  • /dev/dsp OSS errors → legacy OSS interface is not available on modern systems, so apps that still try will log a failure, but ALSA/PipeWire continues working fine.

✅ None of these indicate a problem with PipeWire or HiFiBerry. Your audio will still flow normally — you can safely ignore these logs.


🔇 Silencing JACK Warnings

If you want to prevent JACK errors from appearing in logs, set this environment variable in your session:

export JACK_NO_START_SERVER=1

To make it persistent for the dietpi user, add it to ~/.profile:

echo 'export JACK_NO_START_SERVER=1' >> ~/.profile

Then reload:

source ~/.profile

This tells libraries that probe JACK not to try auto-starting a JACK server, removing the “jack server is not running” spam.

¿Esta página resolvió tu problema?

Tu respuesta llega directamente a quienes escriben estas páginas.

We respect your privacy.

TLDR: We use cookies for language selection, theme, and analytics. Learn more.