Process video frames asynchronously using a threaded pipeline. This function orchestrates a three-stage pipeline to optimize video processing throughput: 1. Reader thread: Continuously reads frames from the source video file and enqueues them into a bounded queue (`frame_re
(
source_path: str,
target_path: str,
callback: Callable[[npt.NDArray[np.uint8], int], npt.NDArray[np.uint8]],
*,
max_frames: int | None = None,
prefetch: int = 32,
writer_buffer: int = 32,
show_progress: bool = False,
progress_message: str = "Processing video",
preserve_audio: bool = False,
)
| 281 | |
| 282 | |
| 283 | def process_video( |
| 284 | source_path: str, |
| 285 | target_path: str, |
| 286 | callback: Callable[[npt.NDArray[np.uint8], int], npt.NDArray[np.uint8]], |
| 287 | *, |
| 288 | max_frames: int | None = None, |
| 289 | prefetch: int = 32, |
| 290 | writer_buffer: int = 32, |
| 291 | show_progress: bool = False, |
| 292 | progress_message: str = "Processing video", |
| 293 | preserve_audio: bool = False, |
| 294 | ) -> None: |
| 295 | """ |
| 296 | Process video frames asynchronously using a threaded pipeline. |
| 297 | |
| 298 | This function orchestrates a three-stage pipeline to optimize video processing |
| 299 | throughput: |
| 300 | |
| 301 | 1. Reader thread: Continuously reads frames from the source video file and |
| 302 | enqueues them into a bounded queue (`frame_read_queue`). The queue size is |
| 303 | limited by the `prefetch` parameter to control memory usage. |
| 304 | 2. Main thread (Processor): Dequeues frames from `frame_read_queue`, applies the |
| 305 | user-defined `callback` function to process each frame, then enqueues the |
| 306 | processed frames into another bounded queue (`frame_write_queue`) for writing. |
| 307 | The processing happens in the main thread, simplifying use of stateful objects |
| 308 | without synchronization. |
| 309 | 3. Writer thread: Dequeues processed frames from `frame_write_queue` and writes |
| 310 | them sequentially to the output video file. |
| 311 | |
| 312 | Args: |
| 313 | source_path: Path to the input video file. |
| 314 | target_path: Path where the processed video will be saved. |
| 315 | callback: Function called for |
| 316 | each frame, accepting the frame as a numpy array and its zero-based index, |
| 317 | returning the processed frame. |
| 318 | max_frames: Optional maximum number of frames to process. |
| 319 | If None, the entire video is processed (default). |
| 320 | prefetch: Maximum number of frames buffered by the reader thread. |
| 321 | Controls memory use; default is 32. |
| 322 | writer_buffer: Maximum number of frames buffered before writing. |
| 323 | Controls output buffer size; default is 32. |
| 324 | show_progress: Whether to display a tqdm progress bar during processing. |
| 325 | Default is False. |
| 326 | progress_message: Description shown in the progress bar. |
| 327 | preserve_audio: If True, copy the audio stream from `source_path` into |
| 328 | `target_path` after frame processing. Requires `ffmpeg` on PATH |
| 329 | (e.g. `apt install ffmpeg`, `brew install ffmpeg`). If ffmpeg is |
| 330 | not found or the mux step fails, a warning is logged and the output |
| 331 | video is saved without audio — no exception is raised. Audio is |
| 332 | truncated to match the processed video duration. Default is False. |
| 333 | |
| 334 | Returns: |
| 335 | None |
| 336 | |
| 337 | Example: |
| 338 | ```python |
| 339 | import supervision as sv |
| 340 | from rfdetr import RFDETRMedium |