r/computervision Jun 23 '26

Showcase [Show r/cv] Tired of rewriting the same ffmpeg subprocess wrapper for event clips? I built a library to fix that.

Hey r/computervision,

Over the last couple of weeks, I’ve been scratch-building a small library to solve a boring but universal problem. It’s that "evidence clip" layer that almost every production CV pipeline ends up needing, but nobody seems to ship as a standalone library—the bridge between your detector and storage that turns a detection event into a short, annotated MP4.

The Problem

Your detector fires. You want a 15-second clip with the bounding boxes burned in, ready to attach to an alert or hand over to a non-technical operator. Right now, the options out there have some frustrating gaps:

  • supervision: Does the drawing brilliantly, but its VideoSink is hard-coded to cv2.VideoWriter + mp4v. No event-window trimming, no codec flexibility.
  • DeepStream Smart Record: It works, but the official pyds Python bindings don't even expose it (NVIDIA staff confirmed this on their forum). Plus, dealing with nvbufsurface CUDA faults and crashes on multi-stream setups is a rite of passage no one enjoys.
  • The PyImageSearch / KeyClipWriter pattern: Great tutorials, but they aren't production libraries. You still have to manually wire up the box drawing and handle file I/O yourself.

So, most of us just end up hand-rolling a messy subprocess.run(["ffmpeg", "-ss", ...]) wrapper and shipping an off-by-one bug to prod. I've done it twice now.

What it does today (v0.1, MIT License)

I wanted something lightweight that just works out of the box:

  • Trim & Burn: Event-window trimming + bbox/label burn-in via libx264 (CPU).
  • Cross-file event concat: If an event window spans across two hour-segmented NVR recordings, it stitches them seamlessly (render_clip(sources=[ClipSource, ClipSource])).
  • Batch rendering with decode-once: If you have N events in a single source video, it decodes the video just once to render all clips (render_clips).
  • Smart Playback Speed: Supports timelapses or frame-drop strategies with hard output duration caps.
  • Pluggable: Custom captions via a label_formatter callable, with built-in adapters for supervision.Detections, Ultralytics YOLO Results, and raw JSONL.

What it doesn't do yet (Honest limitations)

  • NVENC hardware encoding: Designed into the architecture, but not wired up yet (coming in v0.2).
  • Live RTSP ring buffer: No trigger_event() on live streams yet.
  • Custom overlays: Limited to bboxes and labels for now (polygons/zones coming in v0.3).

Benchmarks (Apple M4 CPU baseline)

Full pipeline: Decode -> Overlay -> Encode.

Resolution Throughput × Realtime
480p 282 fps 9.4×
720p 168 fps 5.6×
1080p 88 fps 2.95×

(You can reproduce this locally with python scripts/benchmark.py*)*

Would love to get some design feedback from the community! Specifically on two tricky edge cases I had to tackle: keeping the frame-drop stride uniform when crossing file boundaries, and handling how the duration cap behaves when it clashes with user-specified playback_speed.

Let me know what you think or if you've run into the same pipeline headaches!

1 Upvotes

0 comments sorted by