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 Sep 30, 2024
1 parent 85d69f7 commit 9be43ba
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 3 deletions.
8 changes: 8 additions & 0 deletions scenedetect.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,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
4 changes: 2 additions & 2 deletions scenedetect/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ def main():
logger.info("Stopped.")
if __debug__:
raise
except BaseException as ex:
except Exception as ex:
if __debug__:
raise
else:
logger.critical("Unhandled exception:", exc_info=ex)
logger.critical("ERROR: Unhandled exception:", exc_info=ex)
raise SystemExit(1) from None


Expand Down
3 changes: 3 additions & 0 deletions scenedetect/_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,14 +1064,17 @@ def list_scenes_command(
scene_list_name_format = ctx.config.get_value("list-scenes", "filename", filename)
list_scenes_args = {
"cut_format": TimecodeFormat[ctx.config.get_value("list-scenes", "cut-format").upper()],
"col_separator": ctx.config.get_value("list-scenes", "col-separator"),
"display_scenes": ctx.config.get_value("list-scenes", "display-scenes"),
"display_cuts": ctx.config.get_value("list-scenes", "display-cuts"),
"row_separator": ctx.config.get_value("list-scenes", "row-separator"),
"scene_list_output": not no_output_file,
"scene_list_name_format": scene_list_name_format,
"skip_cuts": skip_cuts or ctx.config.get_value("list-scenes", "skip-cuts"),
"output_dir": scene_list_dir,
"quiet": quiet or ctx.config.get_value("list-scenes", "quiet") or ctx.quiet_mode,
}
# 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 @@ -76,6 +76,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 @@ -96,6 +98,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,10 +303,12 @@ def format(self, timecode: FrameTimecode) -> str:
},
"list-scenes": {
"cut-format": "timecode",
"col-separator": ",",
"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
6 changes: 6 additions & 0 deletions website/pages/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Releases

## PySceneDetect 0.6

### 0.6.5 (TBD)

- [api] Add `col_separator` and `row_separator` args to `write_scene_list` function in `scenedetect.scene_manager`
- [cli] Add ability to configure CSV separators for rows/columns in config file [#423](https://github.com/Breakthrough/PySceneDetect/issues/423)


### 0.6.4 (June 10, 2024)

#### Release Notes
Expand Down

0 comments on commit 9be43ba

Please sign in to comment.