From 122d732db2ecec580a57217c4344db0bdeb3f545 Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Tue, 14 Apr 2026 11:32:17 -0400 Subject: [PATCH] fix: use returncode is None instead of .done() for subprocess check --- backend/app/utils/hls.py | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/backend/app/utils/hls.py b/backend/app/utils/hls.py index e5da209..b2120ed 100644 --- a/backend/app/utils/hls.py +++ b/backend/app/utils/hls.py @@ -10,10 +10,14 @@ logger = logging.getLogger(__name__) def _deltacast_device_exists(port_index: int) -> bool: - """Return True if the deltacast device node exists on the host.""" return os.path.exists(f"/dev/deltacast{port_index}") +def _proc_running(proc) -> bool: + """Return True if the subprocess is still alive.""" + return proc is not None and proc.returncode is None + + class HLSPreviewManager: """ Manages FFmpeg HLS transcoding processes for video preview. @@ -26,13 +30,10 @@ class HLSPreviewManager: self._processes: dict[int, asyncio.subprocess.Process] = {} async def start_preview(self, port_index: int) -> None: - if port_index in self._processes and self._processes[port_index] is not None: - proc = self._processes[port_index] - if not proc.done(): - logger.info(f"Port {port_index}: HLS preview already running") - return - # Process died — clean up and restart - self._processes.pop(port_index) + existing = self._processes.get(port_index) + if _proc_running(existing): + logger.info(f"Port {port_index}: HLS preview already running") + return self.hls_dir.mkdir(parents=True, exist_ok=True) @@ -44,8 +45,6 @@ class HLSPreviewManager: else: logger.info(f"Port {port_index}: Starting HLS preview from deltacast{port_index}") - logger.debug(f"Port {port_index}: FFmpeg command: {' '.join(command)}") - try: process = await asyncio.create_subprocess_exec( *command, @@ -60,10 +59,10 @@ class HLSPreviewManager: raise async def stop_preview(self, port_index: int) -> None: - if port_index not in self._processes or self._processes[port_index] is None: + process = self._processes.get(port_index) + if not _proc_running(process): return - process = self._processes[port_index] logger.info(f"Port {port_index}: Stopping HLS preview (PID: {process.pid})") try: @@ -107,23 +106,18 @@ class HLSPreviewManager: return self.hls_dir / f"port_{port_index}.m3u8" def is_previewing(self, port_index: int) -> bool: - if port_index not in self._processes: - return False - process = self._processes[port_index] - return process is not None and not process.done() + return _proc_running(self._processes.get(port_index)) def _build_hls_command(self, port_index: int, use_test_src: bool = False) -> list[str]: playlist_path = self.get_playlist_path(port_index) if use_test_src: - # lavfi test source: colour bars + timestamp overlay + tone - # Port number overlaid so each card is visually distinct command = [ self.settings.ffmpeg_path, "-f", "lavfi", "-i", ( f"testsrc2=size=1280x720:rate=30," - f"drawtext=text='SDI PORT {port_index} — NO SIGNAL':" + f"drawtext=text='SDI PORT {port_index} \u2014 NO SIGNAL':" f"fontsize=36:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2," f"drawtext=text='%{{localtime\\:%H\\:%M\\:%S}}':" f"fontsize=24:fontcolor=yellow:x=10:y=10"