Export video clips with mpv
2024-07-22
mpv script to export the current A-B loop as a video clip using ffmpeg. Uses hardware acceleration (VAAPI) and stream copy for fast exports.
Add to ~/.config/mpv/input.conf:
Ctrl+2 script-message export-loop-clip
Save as ~/.config/mpv/scripts/export_clip.lua:
utils = require "mp.utils"
-- find available filename
function slow_start()
local basename = mp.get_property("filename"):gsub("%.([^%.]+)$", "")
local screenshot_folder = mp.get_property("screenshot-directory") or ""
function filename(idx)
return utils.join_path(
screenshot_folder,
basename .. '-' .. string.format("%04d",idx) .. '.mp4'
)
end
-- multiply
local inc = 1
while utils.file_info(filename(inc)) do
inc = inc * 2
end
-- narrowing
local lower_bound = math.floor(inc / 2)
while inc - lower_bound > 1 do
local mid = math.floor((inc + lower_bound) / 2)
local is_file = utils.file_info(filename(mid))
if is_file then
lower_bound = mid
else
inc = mid
end
end
return filename(inc)
end
function export_loop_clip()
local a = mp.get_property_number("ab-loop-a")
local b = mp.get_property_number("ab-loop-b")
local path = mp.get_property("path")
if a and b then
local outfile = slow_start()
local cmd = {
'ffmpeg',
'-hwaccel', 'vaapi',
'-hwaccel_output_format','vaapi',
'-ss', tostring(a),
'-i', path,
'-t', tostring(b-a),
'-c:v','copy',
'-c:a','copy',
'-v', 'error',
outfile
}
local args = { args = cmd }
local result = utils.subprocess(args)
if result["status"] == 0 then
mp.msg.info('save clip ' .. outfile)
mp.osd_message('save clip ' .. outfile)
else
mp.msg.info(result["error_string"] .. result["status"])
mp.osd_message("export loop clip error")
end
end
end
mp.register_script_message("export-loop-clip", export_loop_clip)
function set_ab_loop_a()
local pos = mp.get_property_number("time-pos")
mp.set_property_number("ab-loop-a", pos)
mp.osd_message('set A-B loop A: ' .. tostring(pos))
end
mp.register_script_message("set-ab-loop-a", set_ab_loop_a)
function set_ab_loop_b()
local pos = mp.get_property_number("time-pos")
mp.set_property_number("ab-loop-b", pos)
mp.osd_message('set A-B loop B: ' .. tostring(pos))
end
mp.register_script_message("set-ab-loop-b", set_ab_loop_b)
function seek_ab_loop_a()
local pos = mp.get_property_number("ab-loop-a")
if pos then
mp.set_property_number("time-pos", pos)
end
end
mp.register_script_message("seek-ab-loop-a", seek_ab_loop_a)
function seek_ab_loop_b()
local pos = mp.get_property_number("ab-loop-b")
if pos then
mp.set_property_number("time-pos", pos)
end
end
mp.register_script_message("seek-ab-loop-b", seek_ab_loop_b)
Usage: set A-B loop points with l key, then Ctrl+2 to export. Clips are saved to your screenshot directory.