mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Add listening audio probe diagnostics
This commit is contained in:
@@ -346,7 +346,7 @@ def scanner_loop():
|
||||
logger.info("Scanner thread stopped")
|
||||
|
||||
|
||||
def _start_audio_stream(frequency: float, modulation: str):
|
||||
def _start_audio_stream(frequency: float, modulation: str):
|
||||
"""Start audio streaming at given frequency."""
|
||||
global audio_process, audio_rtl_process, audio_running, audio_frequency, audio_modulation
|
||||
|
||||
@@ -442,43 +442,51 @@ def _start_audio_stream(frequency: float, modulation: str):
|
||||
'pipe:1'
|
||||
]
|
||||
|
||||
try:
|
||||
# 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'
|
||||
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(
|
||||
shell_cmd,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
bufsize=0,
|
||||
start_new_session=True # Create new process group for clean shutdown
|
||||
)
|
||||
|
||||
# Brief delay to check if process started successfully
|
||||
time.sleep(0.3)
|
||||
|
||||
if audio_process.poll() is not None:
|
||||
# Read stderr from temp files
|
||||
rtl_stderr = ''
|
||||
ffmpeg_stderr = ''
|
||||
try:
|
||||
with open(rtl_stderr_log, 'r') as f:
|
||||
rtl_stderr = f.read().strip()
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
with open(ffmpeg_stderr_log, 'r') as f:
|
||||
ffmpeg_stderr = f.read().strip()
|
||||
except:
|
||||
pass
|
||||
logger.error(f"Audio pipeline exited immediately. rtl_fm stderr: {rtl_stderr}, ffmpeg stderr: {ffmpeg_stderr}")
|
||||
return
|
||||
try:
|
||||
# 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'
|
||||
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(
|
||||
shell_cmd,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
bufsize=0,
|
||||
start_new_session=True # Create new process group for clean shutdown
|
||||
)
|
||||
|
||||
# Brief delay to check if process started successfully
|
||||
time.sleep(0.3)
|
||||
|
||||
if audio_process.poll() is not None:
|
||||
# Read stderr from temp files
|
||||
rtl_stderr = ''
|
||||
ffmpeg_stderr = ''
|
||||
try:
|
||||
with open(rtl_stderr_log, 'r') as f:
|
||||
rtl_stderr = f.read().strip()
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
with open(ffmpeg_stderr_log, 'r') as f:
|
||||
ffmpeg_stderr = f.read().strip()
|
||||
except:
|
||||
pass
|
||||
logger.error(f"Audio pipeline exited immediately. rtl_fm stderr: {rtl_stderr}, ffmpeg stderr: {ffmpeg_stderr}")
|
||||
return
|
||||
|
||||
# Validate that audio is producing data quickly
|
||||
try:
|
||||
ready, _, _ = select.select([audio_process.stdout], [], [], 2.0)
|
||||
if not ready:
|
||||
logger.warning("Audio pipeline produced no data in startup window")
|
||||
except Exception as e:
|
||||
logger.warning(f"Audio startup check failed: {e}")
|
||||
|
||||
audio_running = True
|
||||
audio_frequency = frequency
|
||||
@@ -878,6 +886,7 @@ def audio_debug() -> Response:
|
||||
"""Get audio debug status and recent stderr logs."""
|
||||
rtl_log_path = '/tmp/rtl_fm_stderr.log'
|
||||
ffmpeg_log_path = '/tmp/ffmpeg_stderr.log'
|
||||
sample_path = '/tmp/audio_probe.bin'
|
||||
|
||||
def _read_log(path: str) -> str:
|
||||
try:
|
||||
@@ -897,7 +906,34 @@ def audio_debug() -> Response:
|
||||
'audio_process_alive': bool(audio_process and audio_process.poll() is None),
|
||||
'rtl_fm_stderr': _read_log(rtl_log_path),
|
||||
'ffmpeg_stderr': _read_log(ffmpeg_log_path),
|
||||
'audio_probe_bytes': os.path.getsize(sample_path) if os.path.exists(sample_path) else 0,
|
||||
})
|
||||
|
||||
|
||||
@listening_post_bp.route('/audio/probe')
|
||||
def audio_probe() -> Response:
|
||||
"""Grab a small chunk of audio bytes from the pipeline for debugging."""
|
||||
global audio_process
|
||||
|
||||
if not audio_process or not audio_process.stdout:
|
||||
return jsonify({'status': 'error', 'message': 'audio process not running'}), 400
|
||||
|
||||
sample_path = '/tmp/audio_probe.bin'
|
||||
size = 0
|
||||
try:
|
||||
ready, _, _ = select.select([audio_process.stdout], [], [], 2.0)
|
||||
if not ready:
|
||||
return jsonify({'status': 'error', 'message': 'no data available'}), 504
|
||||
data = audio_process.stdout.read(4096)
|
||||
if not data:
|
||||
return jsonify({'status': 'error', 'message': 'no data read'}), 504
|
||||
with open(sample_path, 'wb') as handle:
|
||||
handle.write(data)
|
||||
size = len(data)
|
||||
except Exception as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
|
||||
return jsonify({'status': 'ok', 'bytes': size})
|
||||
|
||||
|
||||
@listening_post_bp.route('/audio/stream')
|
||||
|
||||
Reference in New Issue
Block a user