MPD and Scene fixes + twitch-bot cleanup

This commit is contained in:
Jakub Zych
2026-04-28 12:13:42 +02:00
parent 4c818e327b
commit 32be7e4073
16 changed files with 858 additions and 972 deletions

View File

@@ -18,7 +18,7 @@
# 2. Python user packages (python-mpd2, websockets)
# 3. Flatpak OBS Studio + filesystems=host override
# 4. Git submodules + asset directories under $HOME
# 5. PipeWire mpd_stream null sink + loopback
# 5. PipeWire null sinks (mpd_stream + discord_stream) + loopbacks
# 6. MPD config (zeroconf_name = this rig) + system units
# 7. Custom systemd --user units (bridge, bot)
# 8. OBS first-launch to seed obs-websocket plugin config
@@ -248,20 +248,32 @@ done
(( MISSING_ASSETS )) && warn " → bring these over manually from Ignia; OBS will surface 'missing source' errors otherwise"
# ────────────────────────────────────────────────────────────────────────────
# Phase 5 — PipeWire mpd_stream sink
# Phase 5 — PipeWire null sinks (mpd_stream + discord_stream)
# ────────────────────────────────────────────────────────────────────────────
step "PipeWire null sink (mpd_stream)"
# Two isolated streams into OBS so Discord voice and MPD music don't mix
# with each other — or with the rest of the desktop. Each gets its own
# null sink + loopback (so you still hear them locally) + monitor source
# that OBS captures via pulse_output_capture.
step "PipeWire null sinks (mpd_stream + discord_stream)"
PW_CONF_DIR="$HOME/.config/pipewire/pipewire-pulse.conf.d"
PW_CONF="$PW_CONF_DIR/mpd-stream.conf"
mkdir -p "$PW_CONF_DIR"
if [[ -f "$PW_CONF" ]]; then
ok "$PW_CONF already present"
else
if would "write $PW_CONF"; then
mkdir -p "$PW_CONF_DIR"
cat > "$PW_CONF" <<'PWCONF'
# Persistent virtual sink for streaming MPD into OBS without mixing in
PW_CONF_CHANGED=0
write_pw_conf() {
# write_pw_conf <path> <body>
local path="$1"; local body="$2"
if [[ -f "$path" ]]; then
ok "$(basename "$path") already present"
elif would "write $path"; then
printf '%s' "$body" > "$path"
ok "wrote $path"
PW_CONF_CHANGED=1
fi
}
write_pw_conf "$PW_CONF_DIR/mpd-stream.conf" '# Persistent virtual sink for streaming MPD into OBS without mixing in
# desktop/browser/Discord audio.
#
# MPD ──► null sink "mpd_stream"
@@ -284,23 +296,64 @@ pulse.cmd = [
args = "module-loopback source=mpd_stream.monitor latency_msec=50"
}
]
PWCONF
ok "wrote $PW_CONF"
if would "systemctl --user restart pipewire-pulse"; then
systemctl --user restart pipewire-pulse.service 2>/dev/null || \
warn "could not restart pipewire-pulse (will load on next login anyway)"
fi
'
write_pw_conf "$PW_CONF_DIR/discord-stream.conf" '# Persistent virtual sink for capturing Discord audio in OBS without mixing
# in the rest of the desktop (browser, MPD, system bleeps).
#
# Mirrors mpd-stream.conf — separate isolated channel for voice chat:
# Discord ──► null sink "discord_stream"
# │
# ├──► loopback ──► default sink (you still hear voice
# │ chat on speakers/headset)
# │
# └──► monitor ──► OBS "Audio Output Capture (PulseAudio)
# → Monitor of Discord-Stream"
#
# Discord side: set the app'"'"'s audio output to "Discord-Stream" once via
# pavucontrol (Playback tab). PipeWire remembers the routing across launches.
# Discord has no equivalent of MPD'"'"'s `target` setting, so this is a
# one-time per-rig manual step.
#
# Loaded automatically when pipewire-pulse starts.
pulse.cmd = [
{
cmd = "load-module"
args = "module-null-sink sink_name=discord_stream sink_properties=device.description=Discord-Stream"
}
{
cmd = "load-module"
args = "module-loopback source=discord_stream.monitor latency_msec=50"
}
]
'
# Restart pipewire-pulse only if we wrote a new conf AND OBS is not running
# (pipewire-pulse restart silently detaches OBS pulse_output_capture sources;
# fix needs OBS process restart, not just a settings refresh).
if (( PW_CONF_CHANGED )) && (( ! CHECK_ONLY )); then
if flatpak ps --columns=application 2>/dev/null | grep -qx com.obsproject.Studio \
|| pgrep -x obs >/dev/null 2>&1; then
warn "OBS is running — skipping pipewire-pulse restart (would detach OBS audio sources)"
warn " → close OBS, then: systemctl --user restart pipewire-pulse.service"
warn " → or just relog; conf loads on next pipewire-pulse start either way"
elif would "systemctl --user restart pipewire-pulse"; then
systemctl --user restart pipewire-pulse.service 2>/dev/null || \
warn "could not restart pipewire-pulse (will load on next login anyway)"
fi
fi
# Verify the sink is actually loaded (only meaningful in install mode).
# Verify the sinks are actually loaded (only meaningful in install mode).
if (( ! CHECK_ONLY )); then
sleep 1
if pactl list short sinks 2>/dev/null | grep -q '^[0-9]*[[:space:]]\+mpd_stream\b'; then
ok "mpd_stream sink loaded"
else
warn "mpd_stream sink NOT visible to pactl — restart pipewire-pulse or relog and re-check"
fi
for sink in mpd_stream discord_stream; do
if pactl list short sinks 2>/dev/null | grep -q "^[0-9]*[[:space:]]\+${sink}\b"; then
ok "$sink sink loaded"
else
warn "$sink sink NOT visible to pactl — restart pipewire-pulse or relog and re-check"
fi
done
fi
# ────────────────────────────────────────────────────────────────────────────
@@ -572,8 +625,13 @@ cat <<DONE
6. Launch OBS:
flatpak run com.obsproject.Studio
7. Route Discord audio to the Discord-Stream sink (one-time):
Open pavucontrol → Playback tab → while Discord plays sound,
click its dropdown and pick "Discord-Stream". PipeWire remembers
this across launches; the OBS "Discord" source picks up audio.
Sanity checks:
pactl list short sinks | grep mpd_stream
pactl list short sinks | grep -E 'mpd_stream|discord_stream'
systemctl --user status mpd obs-mpd-bridge obs-twitch-bot
mpc status
ss -tlnp | grep 4455