From f8b05b243e67116e4afd29b8fe3600ebbe0253bc Mon Sep 17 00:00:00 2001 From: Breakthrough Date: Tue, 21 Jul 2026 20:51:44 -0400 Subject: [PATCH] [release] Release 0.7.1 --- Dockerfile | 5 +- appveyor.yml | 12 +++- docs/LATEST_VERSION | 2 +- docs/cli.rst | 14 +++- packaging/logo/pyscenedetect-new.svg | 41 ++++++++++++ packaging/windows/installer/PySceneDetect.aip | 10 +-- packaging/windows/requirements.txt | 14 ++-- scenedetect/__init__.py | 2 +- scenedetect/detectors/histogram_detector.py | 10 +-- website/pages/changelog.md | 65 ++++++++++--------- website/pages/download.md | 10 +-- website/pages/index.md | 2 +- 12 files changed, 127 insertions(+), 60 deletions(-) create mode 100644 packaging/logo/pyscenedetect-new.svg diff --git a/Dockerfile b/Dockerfile index b7fcc0de..039790f3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,10 @@ RUN apt-get update && \ # moviepy provides an alternative video splitting backend RUN --mount=type=cache,target=/root/.cache/pip \ cp packaging/variants/pyproject-scenedetect-headless.toml pyproject.toml && \ - pip install ".[pyav,moviepy]" + pip install ".[pyav,moviepy]" && \ + # TODO(https://github.com/Zulko/moviepy/issues/2553): moviepy caps pillow<12.0, but 11.x has + # CVEs only fixed in 12.3.0+. Tests pass against 12.3.0; drop this once moviepy lifts the cap. + pip install "pillow==12.3.0" # Switch to the non-root user USER scenedetect diff --git a/appveyor.yml b/appveyor.yml index e10f47ba..0ffafc7c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,12 +12,13 @@ cache: - '%LOCALAPPDATA%\uv\cache -> pyproject.toml' - 'C:\Program Files\Inkscape' -# Branches applies to tags as well. We only build on tagged releases of the form vX.Y.Z-release +# Branches applies to tags as well. We only build on tagged releases of the form +# vX.Y[.Z] (the legacy -release suffix is also accepted, matching the GitHub workflows). branches: only: - main - /releases\/.+/ - - /v.+-release/ + - /v.+/ skip_tags: false skip_non_tags: true @@ -30,7 +31,7 @@ environment: secure: QRCPoNYF1nqgXDn7pHgBzg== ai_license_salt: secure: +Gy+SRk8JUsaM+5pMEKITiJxdLilrxHpkKlrZzR3C9DPwdgYLGxt5sJn6uXuAJg7e6JsKHcT7tRks/HcSKkHPw== - ffmpeg_version: "8.1" + ffmpeg_version: "8.1.2" # SignPath Config for Code Signing deploy: @@ -50,6 +51,11 @@ install: - python -m pip install uv - uv pip install --system .[docs] - uv pip install --system -r packaging/windows/requirements.txt --no-binary imageio-ffmpeg + # TODO(https://github.com/Zulko/moviepy/issues/2553): moviepy caps pillow<12.0, but 11.x has + # CVEs only fixed in 12.3.0+. Installed as a separate step since a pin in requirements.txt + # would fail strict resolution against moviepy's constraint. Tests pass against 12.3.0; + # drop this once moviepy lifts the cap. + - uv pip install --system pillow==12.3.0 - if not exist ffmpeg-%ffmpeg_version%-full_build.7z appveyor DownloadFile https://github.com/GyanD/codexffmpeg/releases/download/%ffmpeg_version%/ffmpeg-%ffmpeg_version%-full_build.7z - 7z e ffmpeg-%ffmpeg_version%-full_build.7z -odist/ffmpeg ffmpeg.exe LICENSE -r # moviepy.config reads FFMPEG_BINARY (which routes through imageio_ffmpeg) at import time. diff --git a/docs/LATEST_VERSION b/docs/LATEST_VERSION index eb49d7c7..7deb86fe 100644 --- a/docs/LATEST_VERSION +++ b/docs/LATEST_VERSION @@ -1 +1 @@ -0.7 +0.7.1 \ No newline at end of file diff --git a/docs/cli.rst b/docs/cli.rst index c252efad..d19cc4a2 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -61,9 +61,13 @@ Options Stats file (.csv) to write frame metrics. Existing files will be overwritten. Used for tuning detection parameters and data analysis. -.. option:: -f FPS, --framerate FPS +.. option:: -f FPS, --frame-rate FPS - Override framerate with value as frames/sec. + Override frame rate with value as frames/sec. + +.. option:: --framerate FPS + + [DEPRECATED] Use :option:`-f/--frame-rate <-f>` instead. .. option:: -m TIMECODE, --min-scene-len TIMECODE @@ -549,6 +553,10 @@ Options Output directory to save EDL file to. Overrides global option :option:`-o/--output `. +.. option:: -s TIMECODE, --start-timecode TIMECODE + + Start timecode added to every event so the EDL aligns with the source media's on-screen timecode. Accepts SMPTE HH:MM:SS:FF or 8 digits (HHMMSSFF, e.g. 01000000). + .. _command-save-fcp: @@ -859,7 +867,7 @@ Options .. option:: --expand - Extend the first/last output clips to cover the full input video, even if the :ref:`time ` command's ``--start``/``--end`` limited the analysis window. Useful for keeping content outside the analyzed region attached to the adjacent split. + Extend the first/last output clips to cover the full input video, even if `time -s/-e` limited the analysis window. Useful for keeping content outside the analyzed region attached to the adjacent split. .. _command-time: diff --git a/packaging/logo/pyscenedetect-new.svg b/packaging/logo/pyscenedetect-new.svg new file mode 100644 index 00000000..fb383852 --- /dev/null +++ b/packaging/logo/pyscenedetect-new.svg @@ -0,0 +1,41 @@ + + + + + + + + + diff --git a/packaging/windows/installer/PySceneDetect.aip b/packaging/windows/installer/PySceneDetect.aip index 607630a9..7865d2a2 100644 --- a/packaging/windows/installer/PySceneDetect.aip +++ b/packaging/windows/installer/PySceneDetect.aip @@ -23,10 +23,10 @@ - + - + @@ -159,7 +159,7 @@ - + @@ -291,7 +291,7 @@ - + @@ -1743,7 +1743,7 @@ - + diff --git a/packaging/windows/requirements.txt b/packaging/windows/requirements.txt index edf740a7..dc31fa21 100644 --- a/packaging/windows/requirements.txt +++ b/packaging/windows/requirements.txt @@ -1,12 +1,14 @@ # PySceneDetect Requirements for Windows Build -av==17.0.1 -click==8.2.1 +# NOTE: pillow (transitive, via moviepy) is overridden to 12.3.0 in appveyor.yml for CVE fixes +# (see https://github.com/Zulko/moviepy/issues/2553). +av==18.0.0 +click==8.4.2 imageio-ffmpeg==0.6.0 moviepy==2.2.1 -opencv-python-headless==4.13.0.92 -numpy==2.4.4 -platformdirs==4.9.6 -tqdm==4.67.3 +opencv-python-headless==5.0.0.93 +numpy==2.5.1 +platformdirs==4.11.0 +tqdm==4.69.0 # Build-only and test-only requirements. pyinstaller diff --git a/scenedetect/__init__.py b/scenedetect/__init__.py index 1e36405a..ad2dc8dc 100644 --- a/scenedetect/__init__.py +++ b/scenedetect/__init__.py @@ -79,7 +79,7 @@ # Used for module identification and when printing version & about info # (e.g. calling `scenedetect version` or `scenedetect about`). -__version__ = "0.7.1-dev0" +__version__ = "0.7.1" init_logger() logger = getLogger("pyscenedetect") diff --git a/scenedetect/detectors/histogram_detector.py b/scenedetect/detectors/histogram_detector.py index c8b74112..da20359f 100644 --- a/scenedetect/detectors/histogram_detector.py +++ b/scenedetect/detectors/histogram_detector.py @@ -145,10 +145,12 @@ def calculate_histogram( relative frequency. Example: - >>> img = cv2.imread("path_to_image.jpg") - >>> hist = calculate_histogram(img, bins=256, normalize=True) - >>> print(hist.shape) - (256,) + + .. code:: python + + img = cv2.imread("path_to_image.jpg") + hist = HistogramDetector.calculate_histogram(img, bins=256, normalize=True) + assert hist.shape == (256,) """ # Extract Luma channel from the frame image y, _, _ = cv2.split(cv2.cvtColor(frame_img, cv2.COLOR_BGR2YUV)) diff --git a/website/pages/changelog.md b/website/pages/changelog.md index 7750c66e..1b9812f1 100644 --- a/website/pages/changelog.md +++ b/website/pages/changelog.md @@ -3,6 +3,40 @@ ## PySceneDetect 0.7 +### PySceneDetect 0.7.1 (July 2026) + +PySceneDetect 0.7.1 adds a new `scenedetect-core` package and official Docker images to make downstream integration easier, along with support for concatenating multiple videos. It also includes several stability and robustness fixes for the PyAV and OpenCV backends. + +#### CLI Changes + + - [feature] `split-video` has a new `--expand` flag: when scenes are detected within a time window (`-s`/`-e`), the first output clip is extended back to the start of the video and the last clip is extended forward to the end, so no footage outside the analysis window is dropped [#115](https://github.com/Breakthrough/PySceneDetect/issues/115) + +#### API Changes + + - [feature] `scenedetect.detect()` now accepts a `backend` keyword argument (`"opencv"`, `"pyav"`, or `"moviepy"`) similar to `open_video`. Defaults to `"opencv"`, matching prior behavior. + - [feature] Add `expand_scenes_to_bounds()` helper in `scenedetect.scene_manager` to extend a scene list so the first scene starts at a given lower bound and the last scene ends at a given upper bound + - [feature] `VideoStream` now provides a public read-only `decode_failures` property reporting the number of frames that failed to decode and were skipped (defaults to 0; populated by the OpenCV and PyAV backends) + - [feature] Add `VideoStreamConcat` (`scenedetect.backends.concat`) which concatenates multiple videos into a single continuous stream with a monotonic PTS timeline; `open_video()` and `detect()` now accept a list of paths. `VideoStreamConcat.map_span()` maps spans of the global timeline back to per-source local times + - [bugfix] The PyAV backend (`VideoStreamAv`) now skips corrupt frames during `read()` and continues decoding instead of failing, giving up only after 8 consecutive decode failures (matching the OpenCV backend's tolerance behavior) + - [bugfix] The PyAV backend now normalizes presentation times by the stream start time, so files with a delayed start (e.g. from edit lists) report the first frame at `position` 0, consistent with other backends and with `seek()` + - [bugfix] Comparisons between two `FrameTimecode` objects that both carry exact presentation times (e.g. positions from VFR videos) and share the same frame rate are now performed exactly using `pts` and `time_base` instead of rounded frame numbers. Previously, distinct frames in VFR sections could compare equal or fail strict ordering when their times rounded to the same approximate frame number. Comparisons involving frame- or seconds-based timecodes, plain values (`int`/`float`/`str`), or differing frame rates are unchanged + - [bugfix] Fix image sequence inputs when using OpenCV 5.0 + +#### Packaging + + - [feature] Add `scenedetect-core`, a new library-only package with minimal dependencies (`numpy` only): it does not depend on any specific OpenCV variant, allowing downstream projects to choose their own (e.g. `opencv-contrib-python`), and does not include the CLI dependencies or the `scenedetect` command [#558](https://github.com/Breakthrough/PySceneDetect/issues/558). Convenience extras `scenedetect-core[opencv]` and `scenedetect-core[opencv-headless]` are provided + - [general] `scenedetect` and `scenedetect-headless` are unchanged: they continue to ship the full program (library + CLI) with `opencv-python` / `opencv-python-headless` respectively. All three packages provide the same `scenedetect` module (install or depend only one) + - [feature] Official Docker images are now published to the GitHub Container Registry with the full CLI, all backends, and external tools (ffmpeg, mkvmerge) included, thanks [@FNGarvin](https://github.com/FNGarvin) [#537](https://github.com/Breakthrough/PySceneDetect/pull/537) + - Example usage (process a video in the current directory): +```bash +docker run --rm -v "$(pwd):/files" ghcr.io/breakthrough/pyscenedetect -i /files/video.mp4 detect-adaptive split-video -o /files +``` + - [general] The Windows distribution now bundles OpenCV 5.0, PyAV 18, and FFmpeg 8.1.2. The Windows and Docker builds also override Pillow to 12.3.0 for upstream security fixes ([moviepy#2553](https://github.com/Zulko/moviepy/issues/2553)) + +#### General + + - [general] Benchmark results are now published on the website ([scenedetect.com/benchmarks](https://www.scenedetect.com/benchmarks/)), including accuracy at default settings and parameter sweep curves for each detector + ### 0.7 (May 3, 2026) 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. @@ -747,33 +781,4 @@ Both the Windows installer and portable distributions now include signed executa Development ========================================================== -## PySceneDetect 0.7.1 (TDB) - -#### CLI Changes - - - [feature] `split-video` has a new `--expand` flag: when scenes are detected within a time window (`-s`/`-e`), the first output clip is extended back to the start of the video and the last clip is extended forward to the end, so no footage outside the analysis window is dropped [#115](https://github.com/Breakthrough/PySceneDetect/issues/115) - -#### API Changes - - - [feature] `scenedetect.detect()` now accepts a `backend` keyword argument (`"opencv"`, `"pyav"`, or `"moviepy"`) similar to `open_video`. Defaults to `"opencv"`, matching prior behavior. - - [feature] Add `expand_scenes_to_bounds()` helper in `scenedetect.scene_manager` to extend a scene list so the first scene starts at a given lower bound and the last scene ends at a given upper bound - - [feature] `VideoStream` now provides a public read-only `decode_failures` property reporting the number of frames that failed to decode and were skipped (defaults to 0; populated by the OpenCV and PyAV backends) - - [feature] Add `VideoStreamConcat` (`scenedetect.backends.concat`) which concatenates multiple videos into a single continuous stream with a monotonic PTS timeline; `open_video()` and `detect()` now accept a list of paths. `VideoStreamConcat.map_span()` maps spans of the global timeline back to per-source local times - - [bugfix] The PyAV backend (`VideoStreamAv`) now skips corrupt frames during `read()` and continues decoding instead of failing, giving up only after 8 consecutive decode failures (matching the OpenCV backend's tolerance behavior) - - [bugfix] The PyAV backend now normalizes presentation times by the stream start time, so files with a delayed start (e.g. from edit lists) report the first frame at `position` 0, consistent with other backends and with `seek()` - - [bugfix] Comparisons between two `FrameTimecode` objects that both carry exact presentation times (e.g. positions from VFR videos) and share the same frame rate are now performed exactly using `pts` and `time_base` instead of rounded frame numbers. Previously, distinct frames in VFR sections could compare equal or fail strict ordering when their times rounded to the same approximate frame number. Comparisons involving frame- or seconds-based timecodes, plain values (`int`/`float`/`str`), or differing frame rates are unchanged - - [bugfix] Fix image sequence inputs when using OpenCV 5.0 - -#### Packaging - - - [feature] Add `scenedetect-core`, a new library-only package with minimal dependencies (`numpy` only): it does not depend on any specific OpenCV variant, allowing downstream projects to choose their own (e.g. `opencv-contrib-python`), and does not include the CLI dependencies or the `scenedetect` command [#558](https://github.com/Breakthrough/PySceneDetect/issues/558). Convenience extras `scenedetect-core[opencv]` and `scenedetect-core[opencv-headless]` are provided - - [general] `scenedetect` and `scenedetect-headless` are unchanged: they continue to ship the full program (library + CLI) with `opencv-python` / `opencv-python-headless` respectively. All three packages provide the same `scenedetect` module (install or depend only one) - - [feature] Official Docker images are now published to the GitHub Container Registry with the full CLI, all backends, and external tools (ffmpeg, mkvmerge) included, thanks [@FNGarvin](https://github.com/FNGarvin) [#537](https://github.com/Breakthrough/PySceneDetect/pull/537) - - Example usage (process a video in the current directory): -```bash -docker run --rm -v "$(pwd):/files" ghcr.io/breakthrough/pyscenedetect -i /files/video.mp4 detect-adaptive split-video -o /files -``` - -#### General - - - [general] Benchmark results are now published on the website ([scenedetect.com/benchmarks](https://www.scenedetect.com/benchmarks/)), including accuracy at default settings and parameter sweep curves for each detector +## PySceneDetect 0.7.2 (TBD) diff --git a/website/pages/download.md b/website/pages/download.md index 17b80fd8..d2b8f99e 100644 --- a/website/pages/download.md +++ b/website/pages/download.md @@ -26,10 +26,10 @@ All three provide the same `scenedetect` Python module -- install only one of th ## Windows Build (64-bit Only)  
-

Latest Release: v0.7

-

  Release Date:  May 3, 2026

-  Installer  (recommended)      -  Portable .zip      +

Latest Release: v0.7.1

+

  Release Date:  July 2026

+  Installer  (recommended)      +  Portable .zip        Getting Started
@@ -49,7 +49,7 @@ docker run --rm -v "$(pwd):/files" ghcr.io/breakthrough/pyscenedetect \ -i /files/video.mp4 detect-adaptive split-video -o /files ``` -The `latest` tag (the default when no tag is given) points to the most recent recommended build, and the `main` tag tracks the development branch. Starting with the next release, version tags (e.g. `0.7.1`) will also be published. `podman` can be used in place of `docker` in the commands above. +The `latest` tag (the default when no tag is given) points to the most recent recommended build, the `main` tag tracks the development branch, and version tags (e.g. `0.7.1`) point to specific releases. `podman` can be used in place of `docker` in the commands above. ## Post Installation diff --git a/website/pages/index.md b/website/pages/index.md index 946dccd5..e09063f4 100644 --- a/website/pages/index.md +++ b/website/pages/index.md @@ -3,7 +3,7 @@ PySceneDetect
-

  Latest Release: v0.7 (May 3, 2026)

+

  Latest Release: v0.7.1 (July 2026)

  Download        Changelog        Documentation        Getting Started