Skip to content

Commit

Permalink
[cli] Add ability to customize delimiters for CSV output (#423)
Browse files Browse the repository at this point in the history
  • Loading branch information
Breakthrough committed Nov 13, 2024
1 parent 2c55a55 commit 482c3ef
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 2 deletions.
8 changes: 8 additions & 0 deletions scenedetect.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,14 @@
# Display list of cut points generated from scene boundaries (yes/no).
#display-cuts = yes

# Separator to use between columns in output file. Must be single (escaped)
# ASCII character.
#col-separator = ,

# Separator to use between rows in output file. Must be (escaped) ASCII
# characters.
#row-separator = \n

# Format to use for list of cut points (frames, seconds, timecode).
#cut-format = timecode

Expand Down
3 changes: 3 additions & 0 deletions scenedetect/_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,7 @@ def list_scenes_command(
output_dir = ctx.config.get_value("list-scenes", "output", output)
name_format = ctx.config.get_value("list-scenes", "filename", filename)
list_scenes_args = {
"col_separator": ctx.config.get_value("list-scenes", "col-separator"),
"cut_format": ctx.config.get_value("list-scenes", "cut-format"),
"display_scenes": ctx.config.get_value("list-scenes", "display-scenes"),
"display_cuts": ctx.config.get_value("list-scenes", "display-cuts"),
Expand All @@ -1122,7 +1123,9 @@ def list_scenes_command(
"skip_cuts": ctx.config.get_value("list-scenes", "skip-cuts", skip_cuts),
"output_dir": output_dir,
"quiet": ctx.config.get_value("list-scenes", "quiet", quiet) or ctx.quiet_mode,
"row_separator": ctx.config.get_value("list-scenes", "row-separator"),
}
# TODO(#423): Need to validate that col_separator is a 1-character string after decoding.
ctx.add_command(cli_commands.list_scenes, list_scenes_args)


Expand Down
4 changes: 4 additions & 0 deletions scenedetect/_cli/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ def list_scenes(
display_scenes: bool,
display_cuts: bool,
cut_format: str,
col_separator: str,
row_separator: str,
):
"""Handles the `list-scenes` command."""
# Write scene list CSV to if required.
Expand All @@ -125,6 +127,8 @@ def list_scenes(
scene_list=scenes,
include_cut_list=not skip_cuts,
cut_list=cuts,
col_separator=col_separator.encode("utf-8").decode("unicode_escape"),
row_separator=row_separator.encode("utf-8").decode("unicode_escape"),
)
# Suppress output if requested.
if quiet:
Expand Down
2 changes: 2 additions & 0 deletions scenedetect/_cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,13 @@ def format(self, timecode: FrameTimecode) -> str:
"show": False,
},
"list-scenes": {
"col-separator": ",",
"cut-format": TimecodeFormat.TIMECODE,
"display-cuts": True,
"display-scenes": True,
"filename": "$VIDEO_NAME-Scenes.csv",
"output": None,
"row-separator": "\n",
"no-output-file": False,
"quiet": False,
"skip-cuts": False,
Expand Down
9 changes: 8 additions & 1 deletion scenedetect/scene_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ def write_scene_list(
scene_list: SceneList,
include_cut_list: bool = True,
cut_list: Optional[CutList] = None,
col_separator: str = ",",
row_separator: str = "\n",
) -> None:
"""Writes the given list of scenes to an output file handle in CSV format.
Expand All @@ -227,8 +229,13 @@ def write_scene_list(
cut_list: Optional list of FrameTimecode objects denoting the cut list (i.e. the frames
in the video that need to be split to generate individual scenes). If not specified,
the cut list is generated using the start times of each scene following the first one.
delimiter: Delimiter to use between values. Must be single character.
lineterminator: Line terminator to use between rows.
Raises:
TypeError: "delimiter" must be a 1-character string
"""
csv_writer = csv.writer(output_csv_file, lineterminator="\n")
csv_writer = csv.writer(output_csv_file, delimiter=col_separator, lineterminator=row_separator)
# If required, output the cutting list as the first row (i.e. before the header row).
if include_cut_list:
csv_writer.writerow(
Expand Down
4 changes: 3 additions & 1 deletion website/pages/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -596,4 +596,6 @@ Development
- [improvement] `save_to_csv` now works with paths from `pathlib`
- [bugfix] Fix `SyntaxWarning` due to incorrect escaping [#400](https://github.com/Breakthrough/PySceneDetect/issues/400)
- [bugfix] Fix `ContentDetector` crash when using callbacks [#416](https://github.com/Breakthrough/PySceneDetect/issues/416) [#420](https://github.com/Breakthrough/PySceneDetect/issues/420)

- [api] The `save_to_csv` function now works correctly with paths from the `pathlib` module
- [api] Add `col_separator` and `row_separator` args to `write_scene_list` function in `scenedetect.scene_manager`
- [feature] Add ability to configure CSV separators for rows/columns in config file [#423](https://github.com/Breakthrough/PySceneDetect/issues/423)

0 comments on commit 482c3ef

Please sign in to comment.