-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcut-video-mod.lua
265 lines (233 loc) · 10 KB
/
cut-video-mod.lua
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
-- Original script: https://github.com/samhippo/mpv-scripts/blob/master/cut-video.lua
-- This is an improved version of cut-video.lua by samhippo. Some of the new features are: export GIFs; burn subtitles; show milliseconds in output filename; preserve cut points after generating clip; and some more minor chages.
-- To use all the new features you'll need to add some new settings to your mpv.conf and input.conf, but since I'm too lazy detail everything, I'm just sharing below what I'm currently using in my conf files:
-- input.conf:
-- Shift+PGUP script-message cut-left
-- Shift+PGDWN script-message cut-right
-- Ctrl+Shift+PGUP script-message cut-start
-- Ctrl+Shift+PGDWN script-message cut-end
-- Shift+PGUP {cut-video-long} script-message cut-left-long
-- Shift+PGDWN {cut-video-long} script-message cut-right-long
-- Ctrl+Shift+PGUP {cut-video-long} script-message cut-start-long
-- Ctrl+Shift+PGDWN {cut-video-long} script-message cut-end-long
-- Shift+ENTER script-message cut-finish "mkv" "-c copy -map 0" ; show-text "Generating MKV file (copy)"
-- Shift+ENTER {mp4} script-message cut-finish "mp4" "-c copy -map 0" ; show-text "Generating MP4 file (copy)"
-- Ctrl+ENTER script-message cut-finish "mp4" "-c:v libx264 -crf 18 -c:a aac -b:a 512k -map_chapters -1" ; show-text "Generating MP4 file (reencode)"
-- Alt+ENTER script-message cut-finish-gif "gif" "-filter_complex scale=1280:-1:flags=lanczos,split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse" ; show-text "Generating GIF file"
-- CtrL+Alt+ENTER script-message cut-finish-subs "mp4" "-c:v libx264 -crf 18 -c:a aac -b:a 512k" ; show-text "Burning subs"
-- Ctrl+Shift+ENTER script-message cut-finish "mkv" "-c:v libx264 -crf 18 -c:a aac -b:a 512k -map 0 -map_chapters -1" ; show-text "Generating MKV file (reencode)"
--
--
-- mpv.conf:
-- [long-video]
-- profile-cond=duration >= 3600 and mp.command('enable-section cut-video-long')
-- profile-restore=copy-equal
--
-- [not-long-video]
-- profile-cond=not(duration >= 3600) and mp.command('disable-section cut-video-long')
--
-- [mp4]
-- profile-cond=path:find('.mp4') and mp.command('enable-section mp4')
-- profile-restore=copy-equal
-- [not-mp4]
-- profile-cond=not(path:find('.mp4')) and mp.command('disable-section mp4')
-- profile-restore=copy-equal
local start_time_formated = nil
local start_time_seconds = nil
local end_time_formated = nil
local end_time_seconds = nil
local is_processing = false
local utils = require "mp.utils"
local ov = mp.create_osd_overlay("ass-events")
function fn_cut_finish(p1,p2)
if(start_time_seconds == nil or end_time_seconds == nil) then
mp.osd_message("Time not set")
else
local video_args = '-c copy'
local output_format = mp.get_property("filename"):match("[^.]+$")
if((p1 == nil and p2 == nil) or (p1 == '' and p2 == '')) then
else
if(p1 == nil or p1 == '') then
else
output_format = p1
end
if(p2 == nil or p2 == '') then
video_args = ''
else
video_args = p2
end
end
local output_directory, _ = utils.split_path(mp.get_property("path"))
local output_filename = mp.get_property("filename/no-ext").."_"..string.gsub(start_time_formated,":",".").." – "..string.gsub(end_time_formated,":",".").."."..output_format
local output_path = utils.join_path(output_directory, output_filename)
local args = {"ffmpeg", "-ss", tostring(start_time_seconds), "-i", tostring(mp.get_property("path")), "-to", tostring(end_time_seconds-start_time_seconds)}
for token in string.gmatch(video_args, "[^%s]+") do
table.insert(args,token)
end
table.insert(args,output_path)
--utils.subprocess_detached({args = args, playback_only = false})
is_processing = true
ov.data = "\n{\\an4}{\\b1}{\\fs20}{\\1c&H00FFFF&}".."Processing..."
ov:update()
local r = mp.command_native({
name = "subprocess",
playback_only = false,
capture_stdout = true,
detach = false,
args = args,
})
print("result: " .. r.stdout)
is_processing = false
ov:remove()
end
end
function fn_cut_finish_gif(p1,p2)
if(start_time_seconds == nil or end_time_seconds == nil) then
mp.osd_message("Time not set")
else
local video_args = '-c copy'
local output_format = mp.get_property("filename"):match("[^.]+$")
if((p1 == nil and p2 == nil) or (p1 == '' and p2 == '')) then
else
if(p1 == nil or p1 == '') then
else
output_format = p1
end
if(p2 == nil or p2 == '') then
video_args = ''
else
video_args = p2
end
end
local output_directory, _ = utils.split_path(mp.get_property("path"))
local output_filename = mp.get_property("filename/no-ext").."_"..string.gsub(start_time_formated,":",".").." – "..string.gsub(end_time_formated,":",".").."."..output_format
local output_path = utils.join_path(output_directory, output_filename)
local args = {'ffmpeg', '-ss', tostring(start_time_seconds), "-to", tostring(end_time_seconds), "-i", tostring(mp.get_property("path"))}
for token in string.gmatch(video_args, "[^%s]+") do
table.insert(args,token)
end
table.insert(args,output_path)
--utils.subprocess_detached({args = args, playback_only = false})
is_processing = true
ov.data = "\n{\\an4}{\\b1}{\\fs20}{\\1c&H00FFFF&}".."Processing..."
ov:update()
local r = mp.command_native({
name = "subprocess",
playback_only = false,
capture_stdout = true,
detach = false,
args = args,
})
print("result: " .. r.stdout)
is_processing = false
ov:remove()
end
end
-- Due to FFmpeg limitations, this function will only work if mpv's working-directory is also the directory of the playing video. All you need to do is open the file directly from the File Explorer.
function fn_cut_finish_subs(p1,p2)
if(start_time_seconds == nil or end_time_seconds == nil) then
mp.osd_message("Time not set")
else
local video_args = '-c copy'
local output_format = mp.get_property("filename"):match("[^.]+$")
if((p1 == nil and p2 == nil) or (p1 == '' and p2 == '')) then
else
if(p1 == nil or p1 == '') then
else
output_format = p1
end
if(p2 == nil or p2 == '') then
video_args = ''
else
video_args = p2
end
end
local output_directory, _ = utils.split_path(mp.get_property("path"))
local output_filename = mp.get_property("filename/no-ext").."_"..string.gsub(start_time_formated,":",".").." – "..string.gsub(end_time_formated,":",".").." (Hardsub)".."."..output_format
local output_path = utils.join_path(output_directory, output_filename)
local args = {"ffmpeg", "-ss", tostring(start_time_seconds), "-to", tostring(end_time_seconds), "-copyts", "-i", tostring(mp.get_property("path")), "-ss", tostring(start_time_seconds), "-filter_complex", "subtitles='"..mp.get_property("filename").."':si="..math.floor(mp.get_property("sid")-1)}
for token in string.gmatch(video_args, "[^%s]+") do
table.insert(args,token)
end
table.insert(args,output_path)
--utils.subprocess_detached({args = args, playback_only = false})
is_processing = true
ov.data = "\n{\\an4}{\\b1}{\\fs20}{\\1c&H00FFFF&}".."Processing..."
ov:update()
local r = mp.command_native({
name = "subprocess",
playback_only = false,
capture_stdout = true,
detach = false,
args = args,
})
print("result: " .. r.stdout)
is_processing = false
ov:remove()
end
end
function fn_cut_start()
start_time_seconds = 0
start_time_formated = mp.get_property_osd('time-start/full'):sub(4)
mp.msg.info("START TIME: "..start_time_seconds)
showOnScreen()
end
function fn_cut_end()
end_time_seconds = mp.get_property_number("duration")
end_time_formated = mp.get_property_osd('duration/full'):sub(4)
mp.msg.info("END TIME: "..start_time_seconds)
showOnScreen()
end
function fn_cut_left()
start_time_seconds = mp.get_property_number("time-pos")
start_time_formated = mp.get_property_osd('time-pos/full'):sub(4)
mp.msg.info("START TIME: "..start_time_seconds)
showOnScreen()
end
function fn_cut_right()
end_time_seconds = mp.get_property_number("time-pos")
end_time_formated = mp.get_property_osd('time-pos/full'):sub(4)
mp.msg.info("END TIME: "..end_time_seconds)
showOnScreen()
end
function fn_cut_start_long()
start_time_seconds = 0
start_time_formated = mp.get_property_osd('time-start/full')
mp.msg.info("START TIME: "..start_time_seconds)
showOnScreen()
end
function fn_cut_end_long()
end_time_seconds = mp.get_property_number("duration")
end_time_formated = mp.get_property_osd('duration/full')
mp.msg.info("END TIME: "..start_time_seconds)
showOnScreen()
end
function fn_cut_left_long()
start_time_seconds = mp.get_property_number("time-pos")
start_time_formated = mp.get_property_osd('time-pos/full')
mp.msg.info("START TIME: "..start_time_seconds)
showOnScreen()
end
function fn_cut_right_long()
end_time_seconds = mp.get_property_number("time-pos")
end_time_formated = mp.get_property_osd('time-pos/full')
mp.msg.info("END TIME: "..end_time_seconds)
showOnScreen()
end
function showOnScreen()
local st = (start_time_formated == nil and '' or start_time_formated)
local et = (end_time_formated == nil and '' or end_time_formated)
ov.data = "{\\an4}{\\b1}{\\fs20}{\\1c&H00FFFF&}".."Start: "..st.."\n{\\an4}{\\b1}{\\fs20}{\\1c&H00FFFF&}".."End: "..et
ov:update()
end
mp.register_script_message('cut-start', fn_cut_start)
mp.register_script_message('cut-end', fn_cut_end)
mp.register_script_message('cut-left', fn_cut_left)
mp.register_script_message('cut-right', fn_cut_right)
mp.register_script_message('cut-start-long', fn_cut_start_long)
mp.register_script_message('cut-end-long', fn_cut_end_long)
mp.register_script_message('cut-left-long', fn_cut_left_long)
mp.register_script_message('cut-right-long', fn_cut_right_long)
mp.register_script_message('cut-finish', fn_cut_finish)
mp.register_script_message('cut-finish-gif', fn_cut_finish_gif)
mp.register_script_message('cut-finish-subs', fn_cut_finish_subs)