Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions scenedetect/output/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,10 @@ def write_scene_list(
# If required, output the cutting list as the first row (i.e. before the header row).
if include_cut_list:
csv_writer.writerow(
["Timecode List:", *cut_list]
if cut_list
else [start.get_timecode() for start, _ in scene_list[1:]]
[
"Timecode List:",
*(cut_list if cut_list else [start.get_timecode() for start, _ in scene_list[1:]]),
]
)
csv_writer.writerow(
[
Expand Down
10 changes: 10 additions & 0 deletions tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,16 @@ def test_write_scene_list_rejects_invalid_output_target():
write_scene_list(ty.cast(ty.Any, object()), scenes)


def test_write_scene_list_cut_list_row_without_cut_list():
"""The cut list row is labelled whether the cut list is passed in or derived from the scenes."""
scenes = _fake_scenes(_FPS_CFR, [(0, 30), (30, 60), (60, 90)])
derived, explicit = StringIO(), StringIO()
write_scene_list(derived, scenes)
write_scene_list(explicit, scenes, cut_list=[scenes[1][0], scenes[2][0]])
assert derived.getvalue().splitlines()[0] == "Timecode List:,00:00:01.000,00:00:02.000"
assert derived.getvalue() == explicit.getvalue()


def test_write_scene_list_edl(tmp_path: Path):
"""EDL output has title header, FCM line, and one event per scene in CMX 3600 format."""
scenes = _fake_scenes(_FPS_CFR, [(0, 30), (30, 60)])
Expand Down
1 change: 1 addition & 0 deletions website/pages/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -825,4 +825,5 @@ Development
- [feature] `VideoStream` has a new `close()` method to release the file handles and decoders a video holds, and can be used as a context manager (`with open_video(path) as video:`) to close it automatically. Calling `close()` more than once has no effect. Once an OpenCV, PyAV, MoviePy or concatenated stream is closed, `read()`, `seek()` and `reset()` raise `ValueError`, while properties describing the video (`path`, `name`, `frame_rate`, `duration`, `frame_size`, `aspect_ratio`) remain available. The default implementation does nothing, so existing `VideoStream` subclasses are unaffected, and `VideoCaptureAdapter` leaves the caller's `VideoCapture` open [#568](https://github.com/Breakthrough/PySceneDetect/issues/568)
- [bugfix] `VideoStreamConcat` no longer keeps its input videos open when they can't be concatenated (e.g. mismatched resolutions), and now closes each input explicitly once it is no longer needed instead of relying on garbage collection [#568](https://github.com/Breakthrough/PySceneDetect/issues/568)
- [bugfix] `split-video` with `-o` now logs the output folder instead of repeating the filename template [#595](https://github.com/Breakthrough/PySceneDetect/pull/595)
- [bugfix] `write_scene_list()` now starts the cut list row with `Timecode List:` when no `cut_list` is passed, as it does when one is passed and as `write_scene_list_html()` does
- [bugfix] Allow `-d`/`--downscale` on the CLI and `downscale` in the config file to be set to `0` for automatic downscaling
Loading