diff --git a/docker-compose.yml b/docker-compose.yml index 3c343a5..99d34e1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,7 @@ services: - ./configs:/configs - /dev:/dev - ./op25-container/app:/app + - pulse_socket:/run/pulse depends_on: - icecast @@ -29,6 +30,12 @@ services: - ./configs:/configs - ./recordings:/recordings - ./drb-edge-node/app:/app/app + - pulse_socket:/run/pulse + environment: + PULSE_SERVER: unix:/run/pulse/native depends_on: - icecast - op25 + +volumes: + pulse_socket: diff --git a/drb-edge-node/app/internal/discord_radio.py b/drb-edge-node/app/internal/discord_radio.py index 15530e5..ca17cf5 100644 --- a/drb-edge-node/app/internal/discord_radio.py +++ b/drb-edge-node/app/internal/discord_radio.py @@ -2,7 +2,6 @@ import asyncio from typing import Optional import discord from discord.ext import commands -from app.config import settings from app.internal.logger import logger BOT_READY_TIMEOUT = 15 # seconds to wait for Discord bot to become ready @@ -18,9 +17,6 @@ class RadioBot: self._watchdog_task: Optional[asyncio.Task] = None self._ready_event: Optional[asyncio.Event] = None self._current_token: Optional[str] = None - self._icecast_url = ( - f"http://{settings.icecast_host}:{settings.icecast_port}{settings.icecast_mount}" - ) # Remembered so we can rejoin after an unexpected disconnect self._guild_id: Optional[int] = None @@ -114,9 +110,11 @@ class RadioBot: def _play_stream(self): if not self._voice_client: return + # Read directly from PulseAudio monitor (zero-delay, no Icecast buffer). + # PULSE_SERVER is set in the container environment to the shared socket. source = discord.FFmpegPCMAudio( - self._icecast_url, - before_options="-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5", + "default.monitor", + before_options="-f pulse", ) self._voice_client.play( discord.PCMVolumeTransformer(source, volume=1.0), diff --git a/drb-edge-node/app/internal/mqtt_manager.py b/drb-edge-node/app/internal/mqtt_manager.py index a3d0a24..941eeb1 100644 --- a/drb-edge-node/app/internal/mqtt_manager.py +++ b/drb-edge-node/app/internal/mqtt_manager.py @@ -141,11 +141,13 @@ class MQTTManager: self._publish(self._t_key_request, {}, qos=1) async def _publish_checkin(self): + from app.internal.discord_radio import radio_bot payload = { "node_id": settings.node_id, "name": settings.node_name, "lat": settings.node_lat, "lon": settings.node_lon, + "discord_connected": radio_bot.is_connected, "timestamp": datetime.now(timezone.utc).isoformat(), } self._publish(self._t_checkin, payload, qos=1)