Release Notes
PySceneDetect 0.7 is a major breaking release which overhauls how timestamps are handled. This allows PySceneDetect to properly process variable framerate (VFR) videos. A significant amount of technical debt has been addressed, including removal of deprecated or overly complicated APIs.
Care was taken to minimize changes for most common API uses, however more advanced use cases may run into breaking changes. Please review the Migration Guide when updating from v0.6. Minimum supported Python version is now Python 3.10.
CLI Changes
- [feature] VFR videos are handled correctly by the OpenCV and PyAV backends, and should work correctly with default parameters
- [feature] All CLI options which used to accept frame numbers only now accept seconds (e.g.
0.6s) and timecodes (e.g.00:00:00.600) #531 - [feature] New
save-fcpcommand allows exporting in Final Cut Pro format (FCP7/FCPX) #156 - [feature] New
save-qpcommand writes a QP file with scene boundary frame numbers, suitable for forcing keyframes at scene cuts in x264/x265 #448 - [feature] New
save-htmlcommand replaces the deprecatedexport-html; the prior command remains as an alias and emits a deprecation warning #518 - [feature] Add
save-edloption--start-timecode/-sto providde a custom start timecode for generated EDLs, supports SMPTEHH:MM:SS:FFor 8-digitHHMMSSFFinput #515 - [bugfix] Fix floating-point precision error in
save-otiooutput where frame values near integer boundaries (e.g.90.00000000000001) were serialized with spurious precision - [bugfix] Add mitigation for transient
OSErrorin the MoviePy backend as it is susceptible to subprocess pipe races on slow or heavily loaded systems #496 - [feature] The MoviePy backend now supports overriding the source frame rate via
-f/--frame-rate(and theVideoStreamMoviePy(frame_rate=...)API), bringing it in line with the OpenCV and PyAV backends - [bugfix]
detect-thresholdcut frame numbers are now backend-deterministic; previously the cut could differ by 1 frame between PyAV and OpenCV when the fade midpoint landed on a.5rounding boundary (PyAV uses sub-microsecond PTS, OpenCV uses millisecond-truncatedCAP_PROP_POS_MSEC) - [breaking] Remove deprecated
-d/--min-delta-hsvoption fromdetect-adaptivecommand (use-c/--min-content-valinstead) - [breaking] Rename
-f/--framerateto-f/--frame-rateas part of VFR overhaul (legacy--framerateform is preserved as a hidden alias but will be removed in v0.8) - [general] Support
SCENEDETECT_DEBUGenvironment variable to control how exceptions and debugging are handled. Unhandled exceptions andCtrl+Cnow produce a logger-formatted error message and exit cleanly with code 1 instead of dumping a raw Python traceback. SetSCENEDETECT_DEBUG=1to ensure all exceptions are re-raised instead of being logged. In both cases, the program will exit with a non-zero exit code.
API Changes
VFR & Timestamp Overhaul:
- Add
write_scene_list_edl,write_scene_list_fcpx,write_scene_list_fcp7, andwrite_scene_list_otioto thescenedetect.outputmodule sosave-edl,save-fcp, andsave-otiocan be invoked directly from Python (previously CLI-only) write_scene_list_edlaccepts an optionalstart_timecodeparameter (SMPTEHH:MM:SS:FFor 8-digitHHMMSSFF) that is added to every event's source and record columns #515- Add new
Timecodetype to represent frame timings in terms of the video's source timebase - Add
time_baseandptsproperties toFrameTimecodefor more accurate timing information - All backends (PyAV, OpenCV, MoviePy) now return PTS-backed timestamps from
VideoStream.position VideoStream.frame_ratenow returnsFractioninstead offloat- Framerates are now stored as rational
Fractionvalues (e.g.Fraction(24000, 1001)instead of23.976) to avoid float precision loss - Common NTSC rates (23.976, 29.97, 59.94) are automatically detected from float values
FrameTimecode.frame_numis now approximate for VFR video (based on PTS-derived time)- Add
frame_rateproperty (returns exactFraction) as the canonical replacement forframerate(returnsfloat) inFrameTimecodeandVideoStream- For CFR sources, both properties represent the same rate, i.e.
time_baseequals1 / frame_ratefor CFR sources #548
- For CFR sources, both properties represent the same rate, i.e.
- Add
frame_ratekeyword argument toopen_video()and theVideoStreamCv2,VideoCaptureAdapter,VideoStreamAv, andVideoStreamMoviePyconstructors as the canonical replacement forframerate#548; acceptsfloat | Fraction | None. The legacyframeratekeyword is retained as a deprecated alias and is ignored whenframe_rateis provided - Add
equal_frame_rate(other)method as the canonical replacement forequal_framerate(fps)
General:
- Type hints: audit and overhaul: first-party code is now clean with Pyright basic mode, migrated deprecated type hints to comply with PEP 585
- Code quality: expand static analysis rules, audit and cleanup existing suppressions
- Packaging: modernized to comply with PEP 621, make
opencv-pythona requirement, add separatescenedetect-headlessvariant instead
Detector Interface:
- Replace
frame_numparameter (int) withtimecode(FrameTimecode) inSceneDetectorinterface #168:- The detector interface:
SceneDetector.process_frame()andSceneDetector.post_process()(thepost_processsignature on the abstract base is now consistently typed asFrameTimecodeto match its concrete-detector overrides; the priorintannotation did not reflect the actual runtime value) - Statistics:
StatsManager.get_metrics(),StatsManager.set_metrics(), andStatsManager.metrics_exist()formally accept eitherFrameTimecodeorint(theintform is retained for compatibility with the deprecatedload_from_csv()path, which keys metrics by integer frame number)
- The detector interface:
StatsManager.load_from_csv()andsave_images()output_dirnow acceptos.PathLike(e.g.pathlib.Path) in addition tostrSceneManager.detect_scenes()durationandend_timeformally acceptint(frames),float(seconds),str(timecode), orFrameTimecode- matching the documented and runtime-supported behaviorSceneDetectoris now a Python abstract classSceneDetectorinstances can now assume they always have frame data to process whenprocess_frameis called- Remove
SceneDetector.is_processing_required()method - Remove
SceneDetector.stats_manager_requiredproperty, no longer required - Remove deprecated
SparseSceneDetectorinterface - Detector
min_scene_lenandsave_images()frame_marginarguments now accept seconds (float) and timecode strings (e.g."0.6s","00:00:00.600") in addition to a frame count (int); these are evaluated using the source video's timing for correct behavior on VFR videos #531
Module Reorganization:
scenedetect.scene_detectormoved toscenedetect.detectorscenedetect.frame_timecodemoved toscenedetect.common- Image/HTML/CSV export in
scenedetect.scene_managermoved toscenedetect.output#463 scenedetect.video_splittermoved toscenedetect.output.video#463
FrameTimecode:
- Add properties to access
frame_num,frame_rate, andsecondsinstead of getter methods frame_numandframe_rateare now read-only properties (construct a newFrameTimecodeto change them)- Remove
FrameTimecode.previous_frame()method - Deprecated functionality preserved from v0.6 now uses the
warningsmodule to emit runtime deprecation warnings, these features will be removed in v0.8 - Soft-deprecate
framerateproperty andequal_framerate()method via docstring; the legacy forms will continue to work until v0.8 when they will be upgraded toDeprecationWarningbefore removal in v0.9
Removals:
- Remove deprecated module
scenedetect.video_manager, use thescenedetect.open_video()function instead - Remove deprecated parameters
base_timecodeandvideo_managerfrom various functions - Remove deprecated
SceneManager.get_event_list()method - Remove deprecated
AdaptiveDetector.get_content_val()method (useStatsManagerinstead) - Remove deprecated
AdaptiveDetectorconstructor argmin_delta_hsv(usemin_content_valinstead) - Remove
advanceparameter fromVideoStream.read() - Remove
SceneDetector.stats_manager_requiredproperty, no longer required SceneDetectoris now a Python abstract class
Windows Distribution
- [general] Updates to Windows distributions:
- av 14.2.0 -> 17.0.1
- click 8.1.8 -> 8.2.1
- imageio-ffmpeg 0.6.0
- moviepy 2.1.2 -> 2.2.1
- numpy 2.2.3 -> 2.4.4
- opencv-python-headless 4.11.0.86 -> 4.13.0.92
- platformdirs 4.3.6 -> 4.9.6
- tqdm 4.67.1 -> 4.67.3
- ffmpeg 8.0 -> 8.1
- [general] Reduced size of Windows distribution without affecting functionality
- [bugfix] Pressing
Ctrl+Cduring scene detection in the bundled distribution now exits cleanly instead of surfacing the PyInstaller bootloader traceback