Context manager bridging clip_manager callbacks to Rich progress bars. clip_manager's callback protocol doesn't know about Rich, so this class owns the Progress instance and exposes bound methods as callbacks. ``__exit__`` always cleans up, even if inference raises.
| 93 | |
| 94 | |
| 95 | class ProgressContext: |
| 96 | """Context manager bridging clip_manager callbacks to Rich progress bars. |
| 97 | |
| 98 | clip_manager's callback protocol doesn't know about Rich, so this class |
| 99 | owns the Progress instance and exposes bound methods as callbacks. |
| 100 | ``__exit__`` always cleans up, even if inference raises. |
| 101 | """ |
| 102 | |
| 103 | def __init__(self) -> None: |
| 104 | self._progress = Progress( |
| 105 | SpinnerColumn(), |
| 106 | TextColumn("[progress.description]{task.description}"), |
| 107 | BarColumn(), |
| 108 | MofNCompleteColumn(), |
| 109 | TimeElapsedColumn(), |
| 110 | console=console, |
| 111 | ) |
| 112 | self._frame_task_id: TaskID | None = None |
| 113 | |
| 114 | def __enter__(self) -> "ProgressContext": |
| 115 | self._progress.__enter__() |
| 116 | return self |
| 117 | |
| 118 | def __exit__(self, *exc: object) -> None: |
| 119 | self._progress.__exit__(*exc) |
| 120 | |
| 121 | def on_clip_start(self, clip_name: str, num_frames: int) -> None: |
| 122 | """Callback: reset the progress bar for a new clip.""" |
| 123 | if self._frame_task_id is not None: |
| 124 | self._progress.remove_task(self._frame_task_id) |
| 125 | self._frame_task_id = self._progress.add_task(f"[cyan]{clip_name}", total=num_frames) |
| 126 | |
| 127 | def on_frame_complete(self, frame_idx: int, num_frames: int) -> None: |
| 128 | """Callback: advance the progress bar by one frame.""" |
| 129 | if self._frame_task_id is not None: |
| 130 | self._progress.advance(self._frame_task_id) |
| 131 | |
| 132 | |
| 133 | def _on_clip_start_log_only(clip_name: str, total_clips: int) -> None: |
no outgoing calls