-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvcut.lua
More file actions
132 lines (123 loc) · 4.33 KB
/
vcut.lua
File metadata and controls
132 lines (123 loc) · 4.33 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
-- Set true to save to an mp4 container, only way for precise cutting that's actually lossless. May cause A/V desync for some players, including web players.
PRECISE = true
START_TIME = nil
local function print(s)
mp.msg.info(s)
mp.osd_message(s,3)
end
-- Generate the timestamp string placed in the output filename, yes this needed to be half the code lol.
local function generate_timestring(ts_start, ts_stop)
local separator = "-"
local seconds_start = math.ceil(ts_start)
local seconds_stop = math.floor(ts_stop)
local timestring = string.format("%02d",seconds_start)
if seconds_start > 60 then
local minutes_start = math.floor(seconds_start / 60)
minutes_start = math.floor(seconds_start / 60)
seconds_start = seconds_start % 60
timestring = string.format("%02d",minutes_start) .. separator .. string.format("%02d",seconds_start)
if minutes_start > 60 then
local hours_start = math.floor(minutes_start / 60)
minutes_start = minutes_start % 60
timestring = string.format("%02d",hours_start) .. separator .. string.format("%02d",minutes_start) .. separator .. string.format("%02d",seconds_start)
end
end
if seconds_stop > 60 then
local minutes_stop = math.floor(seconds_stop / 60)
seconds_stop = seconds_stop % 60
timestring = timestring .. "_To_" .. string.format("%02d",minutes_stop) .. separator .. string.format("%02d",seconds_stop)
if minutes_stop > 60 then
local hours_stop = math.floor(minutes_stop / 60)
minutes_stop = minutes_stop % 60
timestring = timestring .. "_To_" .. string.format("%02d",hours_stop) .. separator .. string.format("%02d",minutes_stop) .. separator .. string.format("%02d",seconds_stop)
end
else
timestring = timestring .. "_To_" .. string.format("%02d",seconds_stop)
end
return timestring
end
function file_exists(name)
local f = io.open(name, "r")
return f ~= nil
end
local function cut(ts_start,ts_stop)
local timestring = generate_timestring(ts_start, ts_stop)
local file = mp.get_property_native("path")
local filename = mp.get_property_native("filename/no-ext")
local extension = mp.get_property_native("filename"):match("^.+(%..+)$") -- No longer needed, we now convert to mp4 because it supports setting a starting timestamp without encoding.
local subcodec = "copy"
local outdir = file:match("(.*[/\\\\])")
local outfile = filename .. "-From_" .. timestring
local cutcmd = {}
local message = ""
local one_frame = 0,0458333333333
if mp.get_property_native("container-fps") ~= nil then
one_frame = 1.1 / mp.get_property_native("container-fps")
end
if PRECISE then
extension = ".mp4"
subcodec = "mov_text"
webformat = "--merge-output-format mp4"
end
if io.open(file, "r") ~= nil then
outfile = outfile .. extension
print("Cutting...")
cutcmd = {
"ffmpeg",
"-nostdin", "-y",
"-loglevel", "error",
"-ss", tostring(ts_start),
"-to", tostring(ts_stop - one_frame), -- Because there's often an extra frame, we remove the last frame from the cut.
"-i", file,
"-c:a", "copy",
"-c:v", "copy",
"-c:s", subcodec,
"-movflags", "+faststart",
outdir .. outfile
}
message = "Cut: " .. string.format("%.2f",ts_stop - ts_start) .. " Seconds\nSaved to:" .. outdir .. outfile
else
print("Downloading...")
cutcmd = {
"yt-dlp", "--force-overwrites",
"-f", "bestvideo*+bestaudio/best",
"--download-sections", "*" .. tostring(ts_start) .. "-" .. tostring(ts_stop),
"-S", "proto:https", -- Not using this can cause issues.
file
}
if PRECISE then
cutcmd[#cutcmd+1]="--merge-output-format"
cutcmd[#cutcmd+1]="mp4"
end
message = "Cut: " .. string.format("%.2f",ts_stop - ts_start) .. " Seconds\nSaved to:" .. mp.get_property("working-directory")
end
mp.command_native_async({
name = "subprocess",
args = cutcmd ,
playback_only = false,
}, function() print(message) end)
end
local function place_timestamp()
local time = mp.get_property_number("time-pos")
if not START_TIME then
print("Cut timestamp placed: " .. string.format("%.2f",time))
START_TIME = time
return
end
if time > START_TIME then
cut(START_TIME, time)
START_TIME = nil
else
print("Invalid cut")
START_TIME = nil
end
end
local function cancel_cut()
if START_TIME then
START_TIME = nil
print("Cut cancelled")
end
end
mp.add_key_binding(nil, "cut", place_timestamp)
mp.add_key_binding(nil, "cancel_cut", cancel_cut)
mp.msg.info("VIDEO-CUTTER LOADED")