Skip to content

Finalize VFR Support#540

Open
Breakthrough wants to merge 7 commits intomainfrom
vfr-support
Open

Finalize VFR Support#540
Breakthrough wants to merge 7 commits intomainfrom
vfr-support

Conversation

@Breakthrough
Copy link
Copy Markdown
Owner

@Breakthrough Breakthrough commented Apr 5, 2026

  • OpenCV + PyAV backends correctly handle VFR videos now
  • Fix PyAV backend dropping last frame
  • Fix OpenCV seeking for VFR video
  • Greatly expand test suite to ensure both backends give the same results for both CFR and VFR videos
  • Ensure FlashFilter uses units of time internally instead of frames, since frame pacing may not be consistent

…uracy

- Fix PyAV read() to reuse persistent decoder generator, preventing the last
  frame from being dropped at EOF due to B-frame buffer flush on GC
- Fix _handle_eof() to seek by PTS seconds instead of frame number (which is
  now a CFR-equivalent approximation, not a decode count)
- Fix get_timecode() to skip nearest-frame snapping for Timecode-backed
  FrameTimecodes, so scene boundary timecodes are PTS-accurate for VFR
- Fix FlashFilter to cache min_scene_len threshold in seconds from first frame's
  framerate, avoiding incorrect thresholds when OpenCV reports wrong average fps
- Fix FCP7 XML: use seconds*fps for frame numbers, dynamic NTSC flag
- Fix OTIO: use seconds*frame_rate for RationalTime values
- Add $START_PTS and $END_PTS (ms) to split-video filename templates
- Refactor test_vfr.py: use open_video(), add EXPECTED_SCENES_VFR ground truth,
  parameterize scene detection test for both pyav and opencv backends
…eration

OpenCV's CAP_PROP_POS_FRAMES does not map linearly to time in VFR video
(e.g. at the same timestamp, PyAV and OpenCV report frame indices that differ
by 35+ frames), causing thumbnails to land in the wrong scene.

Two fixes:
1. VideoStreamCv2.seek(): switch from CAP_PROP_POS_FRAMES to CAP_PROP_POS_MSEC
   for time-accurate seeking on both CFR and VFR video. Seeking one nominal frame
   before the target ensures the subsequent read() returns the frame at the target.

2. ImageSaver.generate_timecode_list(): rewrite to use seconds-based arithmetic
   instead of frame-number ranges. This avoids the frame_num approximation
   (round(seconds * avg_fps)) which gives wrong indices for VFR video.
Use Click's CliRunner rather than subprocesses for CLI tests.

Add CSV, EDL, and expand OTIO tests for VFR and compare that the OpenCV and PyAV backends return equal results for both CFR and VFR video.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants