diff --git a/drb-edge-node/app/internal/discord_radio.py b/drb-edge-node/app/internal/discord_radio.py index 68d61fa..2516a91 100644 --- a/drb-edge-node/app/internal/discord_radio.py +++ b/drb-edge-node/app/internal/discord_radio.py @@ -115,8 +115,17 @@ class RadioBot: def _on_stream_end(self, error): if error: - logger.error(f"Stream ended: {error}") - if self._loop and self._voice_client and self._voice_client.is_connected() and not self._voice_client.is_playing(): + logger.error(f"Stream ended with error: {error}") + if not (self._loop and self._voice_client and self._voice_client.is_connected() and not self._voice_client.is_playing()): + return + if error: + # Back off before retrying — prevents tight loop when PulseAudio is unavailable + async def _delayed_restart(): + await asyncio.sleep(5) + if self._voice_client and self._voice_client.is_connected() and not self._voice_client.is_playing(): + self._play_stream() + self._loop.call_soon_threadsafe(lambda: asyncio.ensure_future(_delayed_restart())) + else: self._loop.call_soon_threadsafe(self._play_stream) def _stop_stream(self): diff --git a/op25-container/docker-entrypoint.sh b/op25-container/docker-entrypoint.sh index b61c7f3..9e1a6d1 100644 --- a/op25-container/docker-entrypoint.sh +++ b/op25-container/docker-entrypoint.sh @@ -1,17 +1,32 @@ #!/bin/bash # --- Start PulseAudio Daemon --- -# The -D flag starts it as a daemon. -# The --exit-idle-time=-1 prevents it from automatically shutting down. +# -n: skip default config (load modules inline — avoids system.pa parsing issues) +# --system: run as system-wide daemon +# --log-target=stderr: makes errors visible in Docker logs +# &: background so this script continues; output still captured by Docker echo "Starting PulseAudio daemon..." mkdir -p /run/pulse chmod 777 /run/pulse -pulseaudio -D --exit-idle-time=-1 --system +pulseaudio --exit-idle-time=-1 -n --system \ + --load="module-native-protocol-unix socket=/run/pulse/native auth-anonymous=1" \ + --load="module-null-sink sink_name=drb_sink sink_properties=device.description=DRB-Sink" \ + --log-target=stderr & -# Wait a moment for PulseAudio to initialize -sleep 1 +# Wait for the socket to actually exist before continuing +echo "Waiting for PulseAudio socket..." +for i in $(seq 1 20); do + if [ -S /run/pulse/native ]; then + echo "PulseAudio socket ready." + break + fi + sleep 0.5 +done +if [ ! -S /run/pulse/native ]; then + echo "WARNING: PulseAudio socket not found after 10s — edge-node audio will fail." +fi +ls -la /run/pulse/ # --- Execute the main command (uvicorn) --- echo "Starting FastAPI application..." -# The main application arguments are passed directly to this script exec "$@" \ No newline at end of file