diff --git a/scenedetect/_cli/context.py b/scenedetect/_cli/context.py index 01b2b41f..721a941f 100644 --- a/scenedetect/_cli/context.py +++ b/scenedetect/_cli/context.py @@ -85,7 +85,8 @@ def __init__(self): self.scene_manager: SceneManager | None = None self.stats_manager: StatsManager | None = None self.save_images: bool = False # True if the save-images command was specified - self.save_images_result: ty.Any = (None, None) # Result of save-images used by save-html + # Result of save-images used by save-html: (image filenames, output directory). + self.save_images_result: tuple[dict[int, list[str]], str | None] | None = None # Input: self.video_stream: VideoStream | None = None diff --git a/tests/release/test_cli_permutations.py b/tests/release/test_cli_permutations.py index 9795b25c..1542d46c 100644 --- a/tests/release/test_cli_permutations.py +++ b/tests/release/test_cli_permutations.py @@ -198,8 +198,8 @@ def test_cli_save_qp_smoke(test_video_file, tmp_path): def test_cli_save_html_smoke(test_video_file, tmp_path): """save-html replaces the deprecated export-html and produces an HTML report. - Note: save-html lacks its own --output option and ignores the global -o, so the - file is routed via --filename with an absolute path. + Note: save-html lacks its own --output option, so the file is routed via --filename + with an absolute path. """ out_html = tmp_path / "scenes.html" result = _run( diff --git a/tests/test_cli.py b/tests/test_cli.py index b3066ef6..b96661c1 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -672,9 +672,16 @@ def test_cli_save_html(tmp_path: Path): """Test `save-html` command.""" base_command = "-i {VIDEO} -s {STATS} time {TIME} {DETECTOR} {COMMAND}" assert invoke_scenedetect(base_command, COMMAND="save-html", output_dir=tmp_path) == 0 + # The global -o option should also apply when no images are saved. assert ( - invoke_scenedetect(base_command, COMMAND="save-html --no-images", output_dir=tmp_path) == 0 + invoke_scenedetect( + base_command, + COMMAND="save-html --no-images --filename no-images.html", + output_dir=tmp_path, + ) + == 0 ) + assert (tmp_path / "no-images.html").exists() # Ensure we can still call the now deprecated export-html command. assert invoke_scenedetect(base_command, COMMAND="export-html", output_dir=tmp_path) == 0 # TODO: Check for existence of HTML & image files. diff --git a/website/pages/changelog.md b/website/pages/changelog.md index 368e2378..57aa57c9 100644 --- a/website/pages/changelog.md +++ b/website/pages/changelog.md @@ -8,6 +8,7 @@ - [bugfix] `$VIDEO_NAME` is now derived from the path component of URL inputs, ignoring the query string and fragment (e.g. `https://host/clip.mp4?token=1.2` -> `clip`). URLs with no path use the host. Previously the query string leaked into output filenames, which fails on Windows. [#197](https://github.com/Breakthrough/PySceneDetect/issues/197) - [bugfix] OTIO exports use the full source duration when provided, including from the CLI, instead of declaring a fixed 1,980-frame duration. The available range remains unspecified when the duration is unknown. Scene source ranges are unchanged. [#580](https://github.com/Breakthrough/PySceneDetect/pull/580) - [bugfix] The OpenCV backend keeps `position` on the last frame after reaching the end of a VFR video, so the last scene no longer ends early (or before it starts) [#561](https://github.com/Breakthrough/PySceneDetect/issues/561) + - [bugfix] `save-html --no-images` now writes to the global `-o`/`--output` directory instead of the working directory [#583](https://github.com/Breakthrough/PySceneDetect/pull/583) ### PySceneDetect 0.7.2 (October 11, 2026)