mirror of
https://github.com/smittix/intercept.git
synced 2026-07-25 17:28:11 -07:00
Add diagnostic logging for SDR device audio debugging
- Log rtl_fm stderr to /tmp/rtl_fm_stderr.log instead of /dev/null - Add detailed logging for audio start requests and parameters - Log audio stream status and bytes transferred - Help diagnose SDR1 airband audio issues Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -439,7 +439,9 @@ def _start_audio_stream(frequency: float, modulation: str):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Use shell pipe for reliable streaming (Python subprocess piping can be unreliable)
|
# Use shell pipe for reliable streaming (Python subprocess piping can be unreliable)
|
||||||
shell_cmd = f"{' '.join(sdr_cmd)} 2>/dev/null | {' '.join(encoder_cmd)}"
|
# Log stderr to a temp file so we can see any errors from rtl_fm
|
||||||
|
stderr_log = '/tmp/rtl_fm_stderr.log'
|
||||||
|
shell_cmd = f"{' '.join(sdr_cmd)} 2>{stderr_log} | {' '.join(encoder_cmd)}"
|
||||||
logger.info(f"Starting audio pipeline: {shell_cmd}")
|
logger.info(f"Starting audio pipeline: {shell_cmd}")
|
||||||
|
|
||||||
audio_rtl_process = None # Not used in shell mode
|
audio_rtl_process = None # Not used in shell mode
|
||||||
@@ -456,10 +458,25 @@ def _start_audio_stream(frequency: float, modulation: str):
|
|||||||
time.sleep(0.3)
|
time.sleep(0.3)
|
||||||
|
|
||||||
if audio_process.poll() is not None:
|
if audio_process.poll() is not None:
|
||||||
stderr = audio_process.stderr.read().decode() if audio_process.stderr else ''
|
# Read rtl_fm stderr from temp file
|
||||||
logger.error(f"Audio pipeline exited immediately: {stderr}")
|
rtl_stderr = ''
|
||||||
|
try:
|
||||||
|
with open(stderr_log, 'r') as f:
|
||||||
|
rtl_stderr = f.read().strip()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
logger.error(f"Audio pipeline exited immediately. rtl_fm stderr: {rtl_stderr}")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Also check for rtl_fm errors even if process is still running
|
||||||
|
try:
|
||||||
|
with open(stderr_log, 'r') as f:
|
||||||
|
rtl_stderr = f.read().strip()
|
||||||
|
if rtl_stderr:
|
||||||
|
logger.warning(f"rtl_fm stderr: {rtl_stderr}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
audio_running = True
|
audio_running = True
|
||||||
audio_frequency = frequency
|
audio_frequency = frequency
|
||||||
audio_modulation = modulation
|
audio_modulation = modulation
|
||||||
@@ -775,7 +792,7 @@ def start_audio() -> Response:
|
|||||||
"""Start audio at specific frequency (manual mode)."""
|
"""Start audio at specific frequency (manual mode)."""
|
||||||
global scanner_running
|
global scanner_running
|
||||||
|
|
||||||
logger.info("Audio start request received")
|
logger.info(f"Audio start request received: {request.json}")
|
||||||
|
|
||||||
# Stop scanner if running
|
# Stop scanner if running
|
||||||
if scanner_running:
|
if scanner_running:
|
||||||
@@ -823,6 +840,8 @@ def start_audio() -> Response:
|
|||||||
scanner_config['device'] = device
|
scanner_config['device'] = device
|
||||||
scanner_config['sdr_type'] = sdr_type
|
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)
|
_start_audio_stream(frequency, modulation)
|
||||||
|
|
||||||
if audio_running:
|
if audio_running:
|
||||||
@@ -858,6 +877,8 @@ def audio_status() -> Response:
|
|||||||
@listening_post_bp.route('/audio/stream')
|
@listening_post_bp.route('/audio/stream')
|
||||||
def stream_audio() -> Response:
|
def stream_audio() -> Response:
|
||||||
"""Stream MP3 audio."""
|
"""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)
|
# Wait for audio to be ready (up to 2 seconds for modulation/squelch changes)
|
||||||
for _ in range(40):
|
for _ in range(40):
|
||||||
if audio_running and audio_process:
|
if audio_running and audio_process:
|
||||||
@@ -865,9 +886,24 @@ def stream_audio() -> Response:
|
|||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
|
|
||||||
if not audio_running or not audio_process:
|
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)
|
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 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
|
||||||
|
|
||||||
def generate():
|
def generate():
|
||||||
|
bytes_sent = 0
|
||||||
try:
|
try:
|
||||||
while audio_running and audio_process and audio_process.poll() is None:
|
while audio_running and audio_process and audio_process.poll() is None:
|
||||||
# Use select to avoid blocking forever
|
# Use select to avoid blocking forever
|
||||||
@@ -875,13 +911,21 @@ def stream_audio() -> Response:
|
|||||||
if ready:
|
if ready:
|
||||||
chunk = audio_process.stdout.read(4096)
|
chunk = audio_process.stdout.read(4096)
|
||||||
if chunk:
|
if chunk:
|
||||||
|
bytes_sent += len(chunk)
|
||||||
yield chunk
|
yield chunk
|
||||||
else:
|
else:
|
||||||
|
logger.warning(f"Audio stream: empty chunk after {bytes_sent} bytes")
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
# 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, running={audio_running}, poll={audio_process.poll() if audio_process else 'N/A'}")
|
||||||
except GeneratorExit:
|
except GeneratorExit:
|
||||||
pass
|
logger.info(f"Audio stream: client disconnected after {bytes_sent} bytes")
|
||||||
except:
|
except Exception as e:
|
||||||
pass
|
logger.error(f"Audio stream error: {e}")
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
generate(),
|
generate(),
|
||||||
|
|||||||
Reference in New Issue
Block a user