fix: use returncode is None instead of .done() for subprocess check

This commit is contained in:
Zac Gaetano 2026-04-14 11:32:17 -04:00
parent 565c524c6f
commit 122d732db2

View file

@ -10,10 +10,14 @@ logger = logging.getLogger(__name__)
def _deltacast_device_exists(port_index: int) -> bool: 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}") 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: class HLSPreviewManager:
""" """
Manages FFmpeg HLS transcoding processes for video preview. Manages FFmpeg HLS transcoding processes for video preview.
@ -26,13 +30,10 @@ class HLSPreviewManager:
self._processes: dict[int, asyncio.subprocess.Process] = {} self._processes: dict[int, asyncio.subprocess.Process] = {}
async def start_preview(self, port_index: int) -> None: async def start_preview(self, port_index: int) -> None:
if port_index in self._processes and self._processes[port_index] is not None: existing = self._processes.get(port_index)
proc = self._processes[port_index] if _proc_running(existing):
if not proc.done(): logger.info(f"Port {port_index}: HLS preview already running")
logger.info(f"Port {port_index}: HLS preview already running") return
return
# Process died — clean up and restart
self._processes.pop(port_index)
self.hls_dir.mkdir(parents=True, exist_ok=True) self.hls_dir.mkdir(parents=True, exist_ok=True)
@ -44,8 +45,6 @@ class HLSPreviewManager:
else: else:
logger.info(f"Port {port_index}: Starting HLS preview from deltacast{port_index}") logger.info(f"Port {port_index}: Starting HLS preview from deltacast{port_index}")
logger.debug(f"Port {port_index}: FFmpeg command: {' '.join(command)}")
try: try:
process = await asyncio.create_subprocess_exec( process = await asyncio.create_subprocess_exec(
*command, *command,
@ -60,10 +59,10 @@ class HLSPreviewManager:
raise raise
async def stop_preview(self, port_index: int) -> None: 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 return
process = self._processes[port_index]
logger.info(f"Port {port_index}: Stopping HLS preview (PID: {process.pid})") logger.info(f"Port {port_index}: Stopping HLS preview (PID: {process.pid})")
try: try:
@ -107,23 +106,18 @@ class HLSPreviewManager:
return self.hls_dir / f"port_{port_index}.m3u8" return self.hls_dir / f"port_{port_index}.m3u8"
def is_previewing(self, port_index: int) -> bool: def is_previewing(self, port_index: int) -> bool:
if port_index not in self._processes: return _proc_running(self._processes.get(port_index))
return False
process = self._processes[port_index]
return process is not None and not process.done()
def _build_hls_command(self, port_index: int, use_test_src: bool = False) -> list[str]: def _build_hls_command(self, port_index: int, use_test_src: bool = False) -> list[str]:
playlist_path = self.get_playlist_path(port_index) playlist_path = self.get_playlist_path(port_index)
if use_test_src: if use_test_src:
# lavfi test source: colour bars + timestamp overlay + tone
# Port number overlaid so each card is visually distinct
command = [ command = [
self.settings.ffmpeg_path, self.settings.ffmpeg_path,
"-f", "lavfi", "-f", "lavfi",
"-i", ( "-i", (
f"testsrc2=size=1280x720:rate=30," 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"fontsize=36:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2,"
f"drawtext=text='%{{localtime\\:%H\\:%M\\:%S}}':" f"drawtext=text='%{{localtime\\:%H\\:%M\\:%S}}':"
f"fontsize=24:fontcolor=yellow:x=10:y=10" f"fontsize=24:fontcolor=yellow:x=10:y=10"