-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVideoChopper.py
More file actions
182 lines (137 loc) · 4.39 KB
/
VideoChopper.py
File metadata and controls
182 lines (137 loc) · 4.39 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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
"""
PROGRAM
VideoChopper.py
DESCRIPTION
Efficiently chops a video file into sections, based on an EDL file.
COPYRIGHT
(c) 2021 Robin Parmar <robin@robinparmar.com>. MIT License.
REQUIREMENTS
Python 3.6 or greater
FFmpeg recent build
Blackmagic DaVinci Resolve 16+ or some other EDL source
PROCESS
In Resolve, add Timeline markers to indicate where the source clip(s) should be split.
Be sure each of these has a unique name. The quick way to do this is to tap "M" to
add a marker and immediately tap "M" again to name. Or, use "shift-M" to edit an
existing marker. Ensure you have a marker to indicate the end of the final segment
you wish to create.
Render the entire file in the format required.
Export an EDL file by following these steps:
1. Go to the Media Pool.
2. Right-click on your Timeline to get the context menu.
3. Choose "Timelines" > "Export" > "Timeline Markers to EDL"
Edit the Configuration class below to correctly specify the input files.
A typical command looks like this:
ffmpeg -i input_file -ss 00:12.3 -to 00:24.6 -c copy -map 0 output_file
No transcoding occurs, ensuring the fastest possible speed.
However, clips may not be frame accurate, depending on the input file.
RESOURCES
Watch the tutorial video:
https://youtu.be/3suPx9r3kpI
HOME
https://github.com/robinparmar/python_VideoChopper
VERSION
1.01 4 May 2021 added video link and name change
1.00 2 May 2021
"""
import os
# convenient place to hold settings
class Configuration:
# name of EDL file
edl = "input.edl"
# name of input video file
input = "input.mov"
# output folder
output = "./result/"
# frame rate of input video file
fps = 24.
# do you want more ffmpeg output?
verbose = False
# execution starts here
def main():
# array of text lines from EDL file
content = []
# read file, accumulating lines with contents
print()
with open(cfg.edl) as f:
for line in f:
line = line.strip()
if len(line) > 0:
content.append(line)
# first two lines are junk
content = content[2:]
# collection of segments
segments = Collection(content)
segments.fix()
segments.run()
# list of Segment instances
class Collection:
collect = []
def __init__(self, content):
# temporary Segment instance
s = None
# flag tracks a data record, which is split over two lines
firstLine = True
# create instances
for line in content:
tokens = line.split()
if firstLine:
# create instance with start time, eg: "01:00:00:00"
s = Segment(tokens[4])
else:
# augment instance with name, eg: "|M:marker01"
s.addName(tokens[1])
self.collect.append(s)
firstLine = not firstLine
def fix(self):
# a segment ends where the next one begins
for i in range(len(self.collect)-1):
s1 = self.collect[i]
s2 = self.collect[i+1]
s1.addStop(s2.start)
self.collect[i] = s1
# we no longer need the last entry
self.collect.pop( len(self.collect)-1 )
def run(self):
# run system commands for entire collection
print()
print("dividing \"{}\" into segments:".format(cfg.input))
for s in self.collect:
s.dump()
os.system( s.makeCommand() )
print()
# an individual video segment
class Segment:
template = "ffmpeg {}-i {} -ss {} -to {} -c copy -map 0 {}{}{}"
quiet = "-hide_banner -loglevel error "
start = ""
stop = ""
name = ""
def __init__(self, start):
# trim prefix, eg. "01:00:00:00" -> "00:00:00"
self.start = self.convert( start[3:] )
def addStop(self, stop):
self.stop = stop
def addName(self, name):
# trim prefix, eg. "|M:marker01" -> "marker01"
self.name = name[3:]
def makeCommand(self):
extra = ""
if not cfg.verbose:
extra = self.quiet
ext = os.path.splitext(cfg.input)[1]
return self.template.format(extra, cfg.input, self.start, self.stop, cfg.output, self.name, ext)
def dump(self):
print( " {}: {}-{}".format(self.name, self.start, self.stop) )
def convert(self, s):
# convert time format to decimal, eg. "00:13:13" -> "00:13.54"
# calculation depends on the frame rate
parts = s.split(":")
if parts[2] == "00":
frac = "0"
else:
frac = str( float(parts[2]) * 100. / cfg.fps )[3:6]
return "{}:{}.{}".format(parts[0], parts[1], frac)
if __name__ == '__main__':
cfg = Configuration()
main()