From deb87d5888d3fc330c83bc72b90c071b940ae768 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 4 Jan 2026 01:51:01 -0500 Subject: [PATCH] Trying to retransmit UDP audio --- app/internal/discord_radio.py | 41 ++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/app/internal/discord_radio.py b/app/internal/discord_radio.py index 3b991ec..75440b2 100644 --- a/app/internal/discord_radio.py +++ b/app/internal/discord_radio.py @@ -64,7 +64,11 @@ class UDPAudioSource(discord.AudioSource): def cleanup(self): if self.ffmpeg_process: - self.ffmpeg_process.kill() + try: + self.ffmpeg_process.stdin.close() + self.ffmpeg_process.terminate() + except: + pass class DiscordRadioBot(discord.Client): """ @@ -103,17 +107,18 @@ class DiscordRadioBot(discord.Client): Runs in a background thread. Listens for UDP packets from OP25. """ self.udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - # Bind to 0.0.0.0 to ensure we catch traffic from any interface (Docker/Localhost) + # Bind to all interfaces to ensure we catch the OP25 stream self.udp_sock.bind(('0.0.0.0', self.listen_port)) self.udp_sock.settimeout(1.0) LOGGER.info(f"UDP Audio Bridge listening on 0.0.0.0:{self.listen_port}") LOGGER.info(f"Forwarding audio to: {self.forward_ports}") - forward_socks = [] + # Create sockets for each forward port + forward_targets = [] for port in self.forward_ports: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - forward_socks.append((s, port)) + forward_targets.append((s, port)) self.running = True while self.running: @@ -121,21 +126,23 @@ class DiscordRadioBot(discord.Client): data, addr = self.udp_sock.recvfrom(4096) self.packets_received += 1 - # 1. Forward to Liquidsoap/Other tools - for sock, port in forward_socks: - # Send to localhost (where Liquidsoap should be listening) - sock.sendto(data, ('127.0.0.1', port)) - self.packets_forwarded += 1 + # 1. Forward to Liquidsoap/audio.py + for sock, port in forward_targets: + try: + sock.sendto(data, ('127.0.0.1', port)) + self.packets_forwarded += 1 + except Exception as fe: + # Log forwarding errors only once per 5 seconds to avoid spam + if self.packets_forwarded % 100 == 0: + LOGGER.error(f"Forward error to port {port}: {fe}") # 2. Add to Discord Buffer self.audio_buffer.extend(data) - # Periodic Debug Logging (Every 5 seconds, only if active) - if time.time() - self.last_log_time > 5: + # Periodic Stats Logging + if time.time() - self.last_log_time > 10: if self.packets_received > 0: - LOGGER.info(f"UDP Stats [5s]: Rx {self.packets_received} pkts | Tx {self.packets_forwarded} pkts | Buffer: {len(self.audio_buffer)} bytes") - - # Reset counters + LOGGER.info(f"Discord Audio Bridge Stats: Received {self.packets_received} packets, Forwarded {self.packets_forwarded}") self.packets_received = 0 self.packets_forwarded = 0 self.last_log_time = time.time() @@ -208,10 +215,8 @@ class DiscordRadioBot(discord.Client): This turns the green ring ON. """ if self.voice_client and not self.voice_client.is_playing(): - # clear buffer slightly to ensure we aren't playing old data - # but keep a little to prevent jitter - # self.audio_buffer.clear() - + # Clear old audio so we don't start with a delay + self.audio_buffer.clear() source = UDPAudioSource(self.audio_buffer) self.voice_client.play(source)