From e8727358eb8d0d55771f1bf52c608614236303cf Mon Sep 17 00:00:00 2001 From: Smittix Date: Sat, 7 Feb 2026 11:12:38 +0000 Subject: [PATCH] Log rtl_fm stderr when pipeline fails and surface error to UI When rtl_fm exits unexpectedly, read its stderr output to diagnose the failure (no device, permission denied, etc.) and include the error message in both the server log and the SSE progress event sent to the browser. Co-Authored-By: Claude Opus 4.6 --- utils/sstv/sstv_decoder.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/utils/sstv/sstv_decoder.py b/utils/sstv/sstv_decoder.py index 61df778..c67d3c4 100644 --- a/utils/sstv/sstv_decoder.py +++ b/utils/sstv/sstv_decoder.py @@ -372,13 +372,27 @@ class SSTVDecoder: current_mode_name: str | None = None logger.info("Audio decode thread started") + rtl_fm_error: str = '' while self._running and self._rtl_process: try: raw_data = self._rtl_process.stdout.read(chunk_bytes) if not raw_data: if self._running: - logger.warning("rtl_fm stream ended unexpectedly") + # Read stderr to diagnose why rtl_fm exited + stderr_msg = '' + if self._rtl_process and self._rtl_process.stderr: + with contextlib.suppress(Exception): + stderr_msg = self._rtl_process.stderr.read().decode( + errors='replace').strip() + rc = self._rtl_process.poll() if self._rtl_process else None + logger.warning( + f"rtl_fm stream ended unexpectedly " + f"(exit code: {rc})" + ) + if stderr_msg: + logger.warning(f"rtl_fm stderr: {stderr_msg}") + rtl_fm_error = stderr_msg break # Convert int16 PCM to float64 @@ -450,9 +464,11 @@ class SSTVDecoder: if was_running: logger.warning("Audio decode thread stopped unexpectedly") + err_detail = rtl_fm_error.split('\n')[-1] if rtl_fm_error else '' + msg = f'rtl_fm failed: {err_detail}' if err_detail else 'Decode pipeline stopped unexpectedly' self._emit_progress(DecodeProgress( status='error', - message='Decode pipeline stopped unexpectedly' + message=msg )) else: logger.info("Audio decode thread stopped")