-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathslicing.lua
145 lines (130 loc) · 4.11 KB
/
slicing.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
local msg = require "mp.msg"
local utils = require "mp.utils"
local options = require "mp.options"
local cut_pos = nil
local copy_audio = true
local o = {
target_dir = "~",
vcodec = "rawvideo",
acodec = "pcm_s16le",
prevf = "",
vf = "format=yuv444p16$hqvf,scale=in_color_matrix=$matrix,format=bgr24",
hqvf = "",
postvf = "",
opts = "",
ext = "avi",
command_template = [[
ffmpeg -v warning -y -stats
-ss $shift -i "$in" -t $duration
-c:v $vcodec -c:a $acodec $audio
-vf $prevf$vf$postvf $opts "$out.$ext"
]],
}
options.read_options(o)
function timestamp(duration)
local hours = duration / 3600
local minutes = duration % 3600 / 60
local seconds = duration % 60
return string.format("%02d:%02d:%02.03f", hours, minutes, seconds)
end
function osd(str)
return mp.osd_message(str, 3)
end
function get_homedir()
-- It would be better to do platform detection instead of fallback but
-- it's not that easy in Lua.
return os.getenv("HOME") or os.getenv("USERPROFILE") or ""
end
function log(str)
local logpath = utils.join_path(
o.target_dir:gsub("~", get_homedir()),
"mpv_slicing.log")
f = io.open(logpath, "a")
f:write(string.format("# %s\n%s\n",
os.date("%Y-%m-%d %H:%M:%S"),
str))
f:close()
end
function escape(str)
-- FIXME(Kagami): This escaping is NOT enough, see e.g.
-- https://stackoverflow.com/a/31413730
-- Consider using `utils.subprocess` instead.
return str:gsub("\\", "\\\\"):gsub('"', '\\"')
end
function trim(str)
return str:gsub("^%s+", ""):gsub("%s+$", "")
end
function get_csp()
local csp = mp.get_property("colormatrix")
if csp == "bt.601" then return "bt601"
elseif csp == "bt.709" then return "bt709"
elseif csp == "smpte-240m" then return "smpte240m"
else
local err = "Unknown colorspace: " .. csp
osd(err)
error(err)
end
end
function get_outname(shift, endpos)
local name = mp.get_property("filename")
local dotidx = name:reverse():find(".", 1, true)
if dotidx then name = name:sub(1, -dotidx-1) end
name = name:gsub(" ", "_")
name = name:gsub(":", "-")
name = name .. string.format(".%s-%s", timestamp(shift), timestamp(endpos))
return name
end
function cut(shift, endpos)
local cmd = trim(o.command_template:gsub("%s+", " "))
local inpath = escape(utils.join_path(
utils.getcwd(),
mp.get_property("stream-path")))
local outpath = escape(utils.join_path(
o.target_dir:gsub("~", get_homedir()),
get_outname(shift, endpos)))
cmd = cmd:gsub("$shift", shift)
cmd = cmd:gsub("$duration", endpos - shift)
cmd = cmd:gsub("$vcodec", o.vcodec)
cmd = cmd:gsub("$acodec", o.acodec)
cmd = cmd:gsub("$audio", copy_audio and "" or "-an")
cmd = cmd:gsub("$prevf", o.prevf)
cmd = cmd:gsub("$vf", o.vf)
cmd = cmd:gsub("$hqvf", o.hqvf)
cmd = cmd:gsub("$postvf", o.postvf)
cmd = cmd:gsub("$matrix", get_csp())
cmd = cmd:gsub("$opts", o.opts)
-- Beware that input/out filename may contain replacing patterns.
cmd = cmd:gsub("$ext", o.ext)
cmd = cmd:gsub("$out", outpath)
cmd = cmd:gsub("$in", inpath, 1)
msg.info(cmd)
log(cmd)
os.execute(cmd)
end
function toggle_mark()
local pos = mp.get_property_number("time-pos")
if cut_pos then
local shift, endpos = cut_pos, pos
if shift > endpos then
shift, endpos = endpos, shift
end
if shift == endpos then
osd("Cut fragment is empty")
else
cut_pos = nil
osd(string.format("Cut fragment: %s - %s",
timestamp(shift),
timestamp(endpos)))
cut(shift, endpos)
end
else
cut_pos = pos
osd(string.format("Marked %s as start position", timestamp(pos)))
end
end
function toggle_audio()
copy_audio = not copy_audio
osd("Audio capturing is " .. (copy_audio and "enabled" or "disabled"))
end
mp.add_key_binding("c", "slicing_mark", toggle_mark)
mp.add_key_binding("a", "slicing_audio", toggle_audio)