00 PipeWire nedir
PipeWire, PulseAudio, JACK ve ALSA'yı tek bir çatı altında birleştiren modern Linux ses ve video sunucusudur. Wim Taymans tarafından Red Hat'te geliştirilen PipeWire, 2021'den itibaren birçok distro'da varsayılan ses sunucusu olmuştur.
Geçiş motivasyonu
| Eski Sistem | Sorunu | PipeWire Çözümü |
|---|---|---|
| PulseAudio | Yüksek gecikme (20–80 ms), JACK uyumsuz, video yok | PA API'sini emüle eder, <5 ms gecikme |
| JACK | Kurulumu karmaşık, PulseAudio ile çakışır | JACK API'sini emüle eder, ortaklaşa çalışır |
| ALSA | Çoklu uygulama karıştırma zor (dmix hack) | ALSA plugin ile şeffaf yönlendirme |
| V4L2 (video) | Kamera paylaşımı yok | Video node'ları üzerinden portal ile kamera paylaşımı |
Session manager rolü
PipeWire kendisi sadece çekirdek medya sunucusudur. Cihazları yönetmek, node'ları bağlamak ve politika uygulamak için bir session manager gerekir. Günümüzde standart session manager WirePlumber'dır (eski pipewire-media-session yerini aldı).
Raspberry Pi OS Bookworm ve Ubuntu 22.10+ artık varsayılan olarak PipeWire + WirePlumber kullanır. pactl info komutu çalışıyorsa pipewire-pulse arka planda PulseAudio'yu emüle ediyor demektir.
01 Mimari
PipeWire, graph tabanlı bir medya işleme modelidir. Her ses kaynağı, filtresi veya çıkışı bir node'dur. Node'lar link'lerle bağlanır, session manager topolojiyi yönetir.
Bileşen mimarisi
┌──────────────────────────────────────────────────────────┐
│ Uygulamalar │
│ GStreamer SDL mpv Firefox JACK-app PulseAudio-app │
└──────┬──────┬────┬──────┬──────────┬────────────┬────────┘
│ │ │ │ │ │
Native ALSA SDL PW-native pw-jack pipewire-pulse
API plugin plugin API shim (PA compat)
│ │ │ │ │ │
└──────┴────┴──────┴──────────┴─────────────┘
│
┌───────────▼────────────┐
│ PipeWire Core │
│ (graph engine, IPC) │
│ SPA plugin loader │
└───────────┬────────────┘
│
┌───────────▼────────────┐
│ WirePlumber │
│ (session manager, │
│ Lua policy engine) │
└───────────┬────────────┘
│
┌───────────▼────────────┐
│ Hardware Layer │
│ ALSA / V4L2 / BT │
└────────────────────────┘
SPA (Simple Plugin API)
02 Kurulum ve temel araçlar
PipeWire araç seti ile sistem durumunu incelemek, ses kaydı/oynatma yapmak ve sorunları teşhis etmek için komut satırı araçları.
Kurulum (Debian/Ubuntu)
sudo apt install pipewire pipewire-audio-client-libraries \
pipewire-pulse pipewire-jack \
wireplumber \
pipewire-alsa \
libspa-0.2-bluetooth \
gstreamer1.0-pipewire
# Servisleri etkinleştir (user session)
systemctl --user enable --now pipewire pipewire-pulse wireplumber
# Durum kontrolü
systemctl --user status pipewire wireplumber
pw-cli — PipeWire CLI
# Tüm object'leri listele
pw-cli list-objects
# Belirli node bilgisi
pw-cli info <node-id>
# Tüm node'lar
pw-cli list-objects Node
# İnteraktif mod
pw-cli
# pw-cli > list-objects
# pw-cli > info 42
# pw-cli > set-param 42 Props '{ volume: 0.8 }'
pw-dump — JSON formatında tam döküm
# Tüm PipeWire graph'ını JSON olarak al
pw-dump | python3 -m json.tool | less
# Sadece node'lar
pw-dump | python3 -c "
import json, sys
data = json.load(sys.stdin)
for obj in data:
if obj.get('type') == 'PipeWire:Interface:Node':
print(obj['id'], obj.get('info',{}).get('props',{}).get('node.name','?'))
"
pw-record / pw-play
# 10 sn kayıt — raw audio
pw-record --target=alsa_input.usb-0d8c_0014-00.mono-fallback \
--rate=48000 --channels=1 --format=s16 \
capture.raw
# WAV formatında kayıt
pw-record --target=default output.wav
# Oynatma
pw-play test.wav
pw-play --target=alsa_output.pci-0000_00_1f.3.analog-stereo test.wav
# Döngü testi: kaydet ve aynı anda çal
pw-record - | pw-play -
wpctl — WirePlumber ctl
# Tüm ses cihazlarını listele
wpctl status
# Varsayılan sink ses seviyesi
wpctl get-volume @DEFAULT_AUDIO_SINK@
wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.8
wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
# Node ID ile işlem
wpctl set-volume 42 0.6
03 WirePlumber
WirePlumber, PipeWire'ın politika motorudur. Lua scripting engine üzerinde çalışır; cihazları otomatik bağlar, varsayılan sink/source belirler ve özel kurallar uygular.
Konfigürasyon yapısı
| Dizin | İçerik |
|---|---|
| /usr/share/wireplumber/ | Sistem varsayılan konfigürasyonu |
| ~/.config/wireplumber/ | Kullanıcı override (öncelikli) |
| /etc/wireplumber/ | Sistem geneli override |
ls /usr/share/wireplumber/
# wireplumber.conf ← ana konfigürasyon
# wireplumber.conf.d/ ← snippet'ler
# scripts/ ← Lua scriptleri
# bluetooth.lua.d/ ← Bluetooth politikası
Özel cihaz kuralı — Lua
-- ~/.config/wireplumber/wireplumber.conf.d/50-usb-mic-rules.conf
monitor.alsa.rules = [
{
matches = [
{
-- USB mikrofonu her zaman mono + 48kHz'de aç
node.name = "~alsa_input.usb.*"
}
]
actions = {
update-props = {
audio.rate = 48000
audio.channels = 1
audio.format = "S16LE"
-- Varsayılan source yap
priority.session = 200
}
}
}
]
Otomatik bağlantı kuralı
-- ~/.config/wireplumber/wireplumber.conf.d/60-auto-connect.conf
-- Belirli bir uygulamayı belirli bir cihaza yönlendir
default.clock.rate = 48000
-- Uygulama bazlı yönlendirme
node.rules = [
{
matches = [{ application.name = "vlc" }]
actions = {
update-props = {
target.object = "alsa_output.pci-0000_00_1f.3.hdmi-stereo"
}
}
}
]
WirePlumber debug
# Debug log seviyesi
WIREPLUMBER_DEBUG=3 wireplumber
# Veya ortam değişkeni ile:
systemctl --user set-environment WIREPLUMBER_DEBUG=4
systemctl --user restart wireplumber
# Log izle
journalctl --user -u wireplumber -f
04 ALSA → PipeWire
ALSA uygulamalarının PipeWire üzerinden şeffaf çalışması için pipewire-alsa paketi bir ALSA plugin sağlar. Uygulama hw:0,0'a yazar, aslında PipeWire graph'ına bağlanır.
ALSA PipeWire plugin kurulumu
# Debian/Ubuntu
sudo apt install pipewire-alsa
# Plugin dosyası
ls /usr/lib/*/alsa-lib/libasound_module_pcm_pipewire.so
# Konfigürasyon
cat /usr/share/alsa/alsa.conf.d/99-pipewire-default.conf
# pcm.!default { type pipewire ... }
# ctl.!default { type pipewire ... }
/etc/pipewire/pipewire.conf
cat /etc/pipewire/pipewire.conf
# veya
cat /usr/share/pipewire/pipewire.conf
# Temel parametreler:
# default.clock.rate = 48000 ← sistem sample rate
# default.clock.quantum = 1024 ← buffer boyutu (frame)
# default.clock.min-quantum = 32 ← minimum buffer
# default.clock.max-quantum = 8192 ← maximum buffer
# Özelleştirme (override):
mkdir -p ~/.config/pipewire/pipewire.conf.d/
cat > ~/.config/pipewire/pipewire.conf.d/10-rates.conf <<'EOF'
context.properties = {
default.clock.rate = 48000
default.clock.quantum = 512
default.clock.min-quantum = 64
}
EOF
.asoundrc ile PipeWire varsayılan olarak ayarlama
# ~/.asoundrc — PipeWire'ı varsayılan ALSA cihazı yap
pcm.!default {
type pipewire
}
ctl.!default {
type pipewire
}
# Fallback (PipeWire yoksa doğrudan HW)
pcm.pipewire {
type pipewire
}
# Test: aplay artık PipeWire üzerinden çalışır
aplay -D default test.wav
# Hangi ALSA backend kullanılıyor?
ALSA_CONFIG_TINYALSA=1 aplay -l 2>&1 | head -5
05 JACK uyumluluğu
PipeWire, JACK API'sini tam olarak emüle eder. Mevcut JACK uygulamaları (Ardour, LADSPA, LV2 host'ları) yeniden derlenmeden PipeWire üzerinde çalışır.
pw-jack wrapper
# JACK uygulamasını PipeWire üzerinde çalıştır
pw-jack ardour5
pw-jack jackd # jackd daemon'unu taklit et
pw-jack qjackctl
# LD_PRELOAD ile manuel:
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/pipewire-0.3/jack/libjack.so.0 \
./myjackapp
# JACK kütüphane semlink (pipewire-jack paketi)
ls -la /usr/lib/*/pipewire-0.3/jack/
# libjack.so.0 → pipewire-jack kütüphanesi
JACK API programı — PipeWire'da çalışma
/* Standart JACK kodu — pw-jack ile PipeWire'da çalışır */
#include <jack/jack.h>
#include <stdio.h>
static int process_cb(jack_nframes_t nframes, void *arg) {
jack_port_t *port = (jack_port_t *)arg;
jack_default_audio_sample_t *buf =
jack_port_get_buffer(port, nframes);
/* DSP işleme: buf üzerinde nframes frame */
return 0;
}
int main(void) {
jack_client_t *client = jack_client_open("myapp",
JackNoStartServer, NULL);
jack_port_t *out = jack_port_register(client, "out",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
jack_set_process_callback(client, process_cb, out);
jack_activate(client);
/* ... */
jack_client_close(client);
}
JACK gecikme bilgisi
# pw-jack ile JACK gecikme ölçümü
pw-jack jack_iodelay
# PipeWire quantum (JACK period size'a eşdeğer)
pw-metadata -n settings 0 clock.force-quantum 256
# Gerçek zamanlı JACK latency
pw-jack jack_lsp -l # port listesi + latency
06 Düşük gecikme ayarı
PipeWire'da düşük gecikme için quantum (buffer boyutu), sample rate, realtime priority ve rtkit ayarlarının doğru yapılandırılması gerekir.
Gecikme hesaplama
Gecikme = (quantum / sample_rate) × 2 (çift buffer)
Örnek: quantum=256, rate=48000 → (256/48000)×2 = 10.7 ms
Örnek: quantum=64, rate=48000 → (64/48000)×2 = 2.7 ms
Quantum ayarı
# Geçici quantum değiştir (pw-metadata)
pw-metadata -n settings 0 clock.force-quantum 256
# Kalıcı quantum ayarı:
cat > ~/.config/pipewire/pipewire.conf.d/20-lowlatency.conf <<'EOF'
context.properties = {
default.clock.rate = 48000
default.clock.quantum = 256
default.clock.min-quantum = 64
default.clock.max-quantum = 2048
}
EOF
# Quantum sıfırla (otomatik mod)
pw-metadata -n settings 0 clock.force-quantum 0
Realtime priority ve rtkit
# rtkit paketi kurulu mu?
which rtkit-daemon
cat /etc/rtkit.conf
# pipewire.conf'ta RT ayarı
# context.properties = {
# mem.mlock-all = true ← tüm belleği RAM'de kilitle
# default.clock.rate = 48000
# }
# /etc/security/limits.d/99-pipewire.conf
@audio - rtprio 99
@audio - memlock unlimited
@audio - nice -19
# Kullanıcıyı audio grubuna ekle
sudo usermod -aG audio $USER
# PipeWire RT thread önceliğini kontrol et
chrt -p $(pidof pipewire)
Gecikme ölçümü
# pw-jack ile round-trip gecikme ölçümü
pw-jack jack_iodelay
# PipeWire yerleşik gecikme bilgisi
pw-cli info | grep latency
pw-dump | python3 -c "
import json, sys
for obj in json.load(sys.stdin):
props = obj.get('info', {}).get('props', {})
if 'latency.min' in props or 'node.latency' in props:
print(obj['id'], props.get('node.name'),
props.get('node.latency'))
"
07 Embedded entegrasyonu
PipeWire'ı Yocto ile derlemek, systemd user service olarak başlatmak ve headless (ekransız) embedded sistemde konfigüre etmek için adımlar.
Yocto meta-pipewire katmanı
# meta-pipewire katmanını klonla
git clone https://gitlab.freedesktop.org/pipewire/meta-pipewire.git
# bblayers.conf'a ekle
BBLAYERS += "${TOPDIR}/../meta-pipewire"
# local.conf veya image recipe
IMAGE_INSTALL:append = " \
pipewire \
pipewire-modules \
wireplumber \
wireplumber-modules \
pipewire-alsa \
"
# Headless konfigürasyon için session manager olmadan sadece core
IMAGE_INSTALL:append = " pipewire pipewire-spa-plugins"
# Servis dosyası otomatik gelir:
# /usr/lib/systemd/user/pipewire.service
# /usr/lib/systemd/user/wireplumber.service
systemd user service — headless başlatma
# Headless sistemde user session olmadan PipeWire başlatmak için:
# /etc/systemd/system/pipewire.service (system service)
[Unit]
Description=PipeWire Sound System (system mode)
After=network.target
[Service]
Type=simple
User=audio
Group=audio
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
Environment=XDG_RUNTIME_DIR=/run/user/1000
Environment=PIPEWIRE_RUNTIME_DIR=/run/user/1000
ExecStartPre=/usr/bin/mkdir -p /run/user/1000
ExecStartPre=/usr/bin/chown audio:audio /run/user/1000
ExecStart=/usr/bin/pipewire
Restart=on-failure
[Install]
WantedBy=multi-user.target
Headless WirePlumber konfigürasyonu
# /etc/wireplumber/wireplumber.conf.d/90-headless.conf
wireplumber.settings = {
# Bluetooth'u devre dışı bırak (yoksa)
bluetooth.autoswitch-to-headset-profile = false
}
# Sadece ALSA cihazlarını yönet
context.components = [
{ factory = monitor.alsa, type = script/lua/module }
{ factory = policy.node, type = script/lua/module }
]
# Systemd loginctl linger — kullanıcı oturumu olmadan service başlat
loginctl enable-linger audio
systemctl --user --machine=audio@ start pipewire wireplumber
08 Pratik: RPi4 USB mikrofon + hoparlör, <10ms gecikme
Raspberry Pi 4 üzerinde USB ses kartı ile 10 ms altında gecikme elde etmek ve WirePlumber ile otomatik routing kurmak için adım adım rehber.
Adım 1: USB ses cihazlarını tespit et
# USB ses cihazlarını listele
lsusb | grep -i audio
aplay -l
arecord -l
# PipeWire'da cihazları gör
wpctl status
# Audio
# ├─ Devices:
# │ 39. USB Audio Device [vol: 0.80]
# └─ Sinks:
# 40. USB Audio Device Analog Stereo [vol: 0.80]
# Sources:
# 41. USB Audio Device Mono [vol: 1.00]
# Detaylı node bilgisi
pw-cli info 40
Adım 2: Düşük gecikme konfigürasyonu
# /etc/pipewire/pipewire.conf.d/10-rpi4-lowlatency.conf
context.properties = {
default.clock.rate = 48000
default.clock.quantum = 256 # ~5.3 ms
default.clock.min-quantum = 128 # ~2.7 ms minimum
default.clock.max-quantum = 1024
mem.mlock-all = true
}
# USB cihazlar için özel quantum (bazı USB cihazlar 512 gerektirir)
context.objects = [
{
factory = adapter
args = {
factory.name = api.alsa.pcm.sink
node.name = "usb-audio-sink"
node.description = "USB Audio Sink"
media.class = "Audio/Sink"
api.alsa.path = "hw:1,0"
audio.rate = 48000
audio.channels = 2
api.alsa.period-size = 256
api.alsa.headroom = 2
}
}
]
Adım 3: WirePlumber otomatik routing
-- /etc/wireplumber/wireplumber.conf.d/50-usb-routing.conf
-- USB mikrofonu varsayılan source, USB hoparlörü varsayılan sink yap
monitor.alsa.rules = [
{
matches = [{ node.name = "~alsa_output.usb.*" }]
actions = {
update-props = {
priority.session = 2000
node.pause-on-idle = false
}
}
},
{
matches = [{ node.name = "~alsa_input.usb.*" }]
actions = {
update-props = {
priority.session = 2000
audio.rate = 48000
audio.channels = 1
node.pause-on-idle = false
}
}
}
]
Adım 4: Gecikme testi ve doğrulama
# Servisler başlat
systemctl --user restart pipewire wireplumber
# Quantum doğrula
pw-metadata -n settings 0
# Key: clock.quantum, Value: 256
# Round-trip gecikme ölçümü
pw-jack jack_iodelay
# Capture latency: 5.3 ms
# Playback latency: 5.3 ms
# Round-trip: 10.6 ms
# Realtime thread önceliği doğrula
chrt -p $(pidof pipewire)
# scheduling policy: SCHED_RR
# current scheduling priority: 88
# Canlı graph izleme
watch -n 1 "wpctl status | head -30"
# Ses testi — loopback
pw-record --target=@DEFAULT_SOURCE@ - | pw-play --target=@DEFAULT_SINK@ -
Adım 5: xrun (buffer underrun) izleme
# PipeWire xrun sayısı
pw-cli info | grep xrun
pw-dump | python3 -c "
import json, sys
for obj in json.load(sys.stdin):
stats = obj.get('info', {}).get('params', {})
if 'xrun-count' in str(stats):
print(obj.get('id'), stats)
"
# ALSA xrun
cat /proc/asound/card*/pcm*/sub*/xrun_debug
# Sistem tune: CPU governor
echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# CPU frekans scaling gecikme spike'larına yol açabilir
PipeWire, PulseAudio ve JACK'ı tek çatı altında birleştirir. WirePlumber'ın Lua tabanlı politika motoru ile cihaz yönlendirme kuralları kolayca özelleştirilebilir. Embedded sistemlerde quantum=256@48kHz ile ~10 ms, quantum=128@48kHz ile ~5 ms gecikme elde edilebilir. RT priority ve CPU performance governor ile xrun sayısı minimuma indirilir.