-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathchapterSplit.py
More file actions
executable file
·93 lines (89 loc) · 3.73 KB
/
chapterSplit.py
File metadata and controls
executable file
·93 lines (89 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/python3
import argparse
import json
import os
import subprocess
APP_DESCRIPTION = \
"""
A basic utility to extract chapters from any media format supported by ffmpeg
"""
CWD = os.path.abspath(os.path.curdir)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=APP_DESCRIPTION)
parser.add_argument(
"input_file", metavar="FILE",
help="Input file to be split"
)
parser.add_argument(
"-o", "--output-dir", metavar="DIR", default=CWD,
help="Output directory. Defaults to current directory"
)
parser.add_argument(
"-c", "--chapters", metavar="CHAPTERS", default=None, nargs="*", type=int,
help="List of chapters (counted from 0) to extract, " +
"separated with spaces. Defaults to all chapters. " +
"Negative values are counted from the end of the file."
)
parser.add_argument(
"-t", "--manual-chapters", metavar="TIME", default=None, nargs="*",
help="List of chapter durations separated with spaces. " +
"Overrides the chapter marks found in the input file. " +
"Accepts number of seconds or time in format: `HH:MM:SS.SSS` " +
"Can be used to extract chapters from a video with no chapter marks. " +
"Can be combined with `-c`"
)
args = parser.parse_args()
# Check supplied paths
if os.path.isfile(args.output_dir):
raise Exception("Output path cannot be a file")
if not os.path.exists(args.input_file):
raise Exception("Input path does not exist")
if not os.path.isfile(args.input_file):
raise Exception("Input path is not a file")
if not os.path.exists(args.output_dir):
os.makedirs(args.output_dir)
inputFileExtension = os.path.basename(args.input_file.split(".")[-1])
# Check if chapters are manually specified
if args.manual_chapters is None:
res = subprocess.run(["ffprobe", "-hide_banner", "-i", args.input_file,
"-print_format", "json", "-show_chapters"],
capture_output=True, text=True, check=True)
chapters = json.loads(res.stdout)["chapters"]
else:
mChapters = args.manual_chapters
for chapter in mChapters:
if ":" in chapter:
# Convert time to seconds
chapter2 = 0
length = len(chapter.split(":"))
if length != 3:
raise Exception("Invalid time format")
for i in range(length):
chapter2 += float(chapter.split(":")[i]) * 60 ** (2 - i)
mChapters[mChapters.index(chapter)] = chapter2
else:
mChapters[mChapters.index(chapter)] = float(chapter)
chapters = [{"start_time": "0", "end_time": mChapters[0], "tags": {
"title": "Chapter_1"}}]
for i in range(1, len(args.manual_chapters)):
chapters.append({
"start_time": chapters[-1]["end_time"],
"end_time": chapters[-1]["end_time"] + mChapters[i], "tags": {"title": "Chapter_" + str(i + 1)}
})
# Select chapters to extract if needed
if args.chapters is not None:
chapters = [chapters[index] for index in args.chapters]
for chapter in chapters:
subprocess.run(
[
"ffmpeg", "-hide_banner", "-i", args.input_file,
"-ss", str(chapter["start_time"]),
"-to", str(chapter["end_time"]),
"-c", "copy",
"-map", "0:v?",
"-map", "0:a?",
"-map", "0:s?",
os.path.join(args.output_dir,
chapter["tags"]["title"] + "." + inputFileExtension)
],
check=True)