diff --git a/instance/intercept.db b/instance/intercept.db index 15137ad..2c3aa90 100644 Binary files a/instance/intercept.db and b/instance/intercept.db differ diff --git a/routes/listening_post.py b/routes/listening_post.py index d768473..fb4960e 100644 --- a/routes/listening_post.py +++ b/routes/listening_post.py @@ -440,14 +440,12 @@ def _start_audio_stream(frequency: float, modulation: str): ] try: - # Use shell pipe for reliable streaming (Python subprocess piping can be unreliable) - # Log stderr to temp files so we can see any errors from rtl_fm and ffmpeg + # Use shell pipe for reliable streaming + # Log stderr to temp files for error diagnosis rtl_stderr_log = '/tmp/rtl_fm_stderr.log' ffmpeg_stderr_log = '/tmp/ffmpeg_stderr.log' - rtl_raw_output = '/tmp/rtl_fm_raw.bin' - # Use tee to capture rtl_fm raw output for diagnostics while also piping to ffmpeg - shell_cmd = f"{' '.join(sdr_cmd)} 2>{rtl_stderr_log} | tee {rtl_raw_output} | {' '.join(encoder_cmd)} 2>{ffmpeg_stderr_log}" - logger.info(f"Starting audio pipeline: {shell_cmd}") + shell_cmd = f"{' '.join(sdr_cmd)} 2>{rtl_stderr_log} | {' '.join(encoder_cmd)} 2>{ffmpeg_stderr_log}" + logger.info(f"Starting audio: {frequency} MHz, mod={modulation}, device={scanner_config['device']}") audio_rtl_process = None # Not used in shell mode audio_process = subprocess.Popen( @@ -479,22 +477,6 @@ def _start_audio_stream(frequency: float, modulation: str): logger.error(f"Audio pipeline exited immediately. rtl_fm stderr: {rtl_stderr}, ffmpeg stderr: {ffmpeg_stderr}") return - # Also check for errors even if process is still running - try: - with open(rtl_stderr_log, 'r') as f: - rtl_stderr = f.read().strip() - if rtl_stderr: - logger.warning(f"rtl_fm stderr: {rtl_stderr}") - except: - pass - try: - with open(ffmpeg_stderr_log, 'r') as f: - ffmpeg_stderr = f.read().strip() - if ffmpeg_stderr: - logger.warning(f"ffmpeg stderr: {ffmpeg_stderr}") - except: - pass - audio_running = True audio_frequency = frequency audio_modulation = modulation @@ -810,8 +792,6 @@ def start_audio() -> Response: """Start audio at specific frequency (manual mode).""" global scanner_running - logger.info(f"Audio start request received: {request.json}") - # Stop scanner if running if scanner_running: scanner_running = False @@ -858,8 +838,6 @@ def start_audio() -> Response: scanner_config['device'] = device scanner_config['sdr_type'] = sdr_type - logger.info(f"Starting audio: freq={frequency} MHz, mod={modulation}, device={device}, gain={gain}, squelch={squelch}") - _start_audio_stream(frequency, modulation) if audio_running: @@ -895,8 +873,6 @@ def audio_status() -> Response: @listening_post_bp.route('/audio/stream') def stream_audio() -> Response: """Stream MP3 audio.""" - logger.info(f"Audio stream requested - running: {audio_running}, process: {audio_process is not None}") - # Wait for audio to be ready (up to 2 seconds for modulation/squelch changes) for _ in range(40): if audio_running and audio_process: @@ -904,71 +880,25 @@ def stream_audio() -> Response: time.sleep(0.05) if not audio_running or not audio_process: - logger.warning("Audio stream requested but no audio running") return Response(b'', mimetype='audio/mpeg', status=204) - # Check if process is still alive - poll_result = audio_process.poll() - logger.info(f"Audio process poll result: {poll_result} (None means running)") - - # Check for rtl_fm and ffmpeg errors - try: - with open('/tmp/rtl_fm_stderr.log', 'r') as f: - rtl_stderr = f.read().strip() - if rtl_stderr: - logger.warning(f"rtl_fm stderr (at stream request): {rtl_stderr}") - except: - pass - try: - with open('/tmp/ffmpeg_stderr.log', 'r') as f: - ffmpeg_stderr = f.read().strip() - if ffmpeg_stderr: - logger.warning(f"ffmpeg stderr (at stream request): {ffmpeg_stderr}") - except: - pass - def generate(): - bytes_sent = 0 - iterations = 0 - logger.info("Audio stream generator started") try: while audio_running and audio_process and audio_process.poll() is None: - iterations += 1 # Use select to avoid blocking forever ready, _, _ = select.select([audio_process.stdout], [], [], 2.0) if ready: chunk = audio_process.stdout.read(4096) if chunk: - bytes_sent += len(chunk) - if bytes_sent < 50000 or bytes_sent % 100000 < 4096: - logger.debug(f"Audio chunk: {len(chunk)} bytes, total: {bytes_sent}") yield chunk else: - logger.warning(f"Audio stream: empty chunk after {bytes_sent} bytes, iterations={iterations}") break else: - # Check raw rtl_fm output file size - raw_size = 0 - try: - raw_size = os.path.getsize('/tmp/rtl_fm_raw.bin') - except: - pass - logger.warning(f"Audio stream: select timeout after {bytes_sent} bytes, iterations={iterations}, poll={audio_process.poll()}, rtl_raw_size={raw_size}") - # Check for errors on timeout - try: - with open('/tmp/ffmpeg_stderr.log', 'r') as f: - ffmpeg_err = f.read().strip() - if ffmpeg_err: - logger.warning(f"ffmpeg stderr (timeout): {ffmpeg_err}") - except: - pass # Timeout - check if process died if audio_process.poll() is not None: - logger.warning(f"Audio process died during streaming after {bytes_sent} bytes") break - logger.info(f"Audio stream ended - sent {bytes_sent} bytes, iterations={iterations}, running={audio_running}, poll={audio_process.poll() if audio_process else 'N/A'}") except GeneratorExit: - logger.info(f"Audio stream: client disconnected after {bytes_sent} bytes") + pass except Exception as e: logger.error(f"Audio stream error: {e}") diff --git a/templates/adsb_dashboard.html b/templates/adsb_dashboard.html index 4e49a37..7f0ae52 100644 --- a/templates/adsb_dashboard.html +++ b/templates/adsb_dashboard.html @@ -257,7 +257,7 @@
SQ - + VOL
@@ -3221,6 +3221,14 @@ sudo make install } } + function updateAirbandSquelch() { + // If airband is playing, restart with new squelch value + if (isAirbandPlaying) { + stopAirband(); + setTimeout(() => startAirband(), 300); + } + } + // Initialize airband on page load document.addEventListener('DOMContentLoaded', initAirband);