Last active
September 27, 2017 05:04
-
-
Save RRvW/e83804bee80bddb59491 to your computer and use it in GitHub Desktop.
MPV webm/h264/gif convert script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- README: | |
-- original version by Zehkul and others https://gist.github.com/Zehkul/25ea7ae77b30af959be0 | |
-- convert script for mpv, just throw it into ~/.mpv/scripts/ | |
-- needs: yad, libnotify and at least mpv 0.4 | |
-- press alt + w to make a webm/gif/h264 clip | |
local msg = require 'mp.msg' | |
local opt = require 'mp.options' | |
local mputils = require 'mp.utils' | |
-- default options, convert_script.conf is read | |
local options = { | |
bitrate_multiplier = 0.975, -- to make sure the file won’t go over the target file size, set it to 1 if you don’t care | |
output_directory = '$HOME/Videos', | |
use_pwd_instead = false, -- overrides output_directory | |
threads = 4, | |
ffmpeg = 'ffmpeg', -- location of ffmpeg | |
} | |
read_options(options, "convert_script") | |
----------------- | |
-- Main script -- | |
----------------- | |
function convert_script_hotkey_call() | |
set_mouse_area = true | |
width = mp.get_property("dwidth") | |
height = mp.get_property("dheight") | |
mp.set_mouse_area(0, 0, width, height, "draw_rectangle") | |
mp.set_osd_ass(width, height, "") | |
if timepos1 then | |
timepos2 = mp.get_property("time-pos") | |
timepos2_humanreadable = mp.get_property_osd("time-pos") | |
if tonumber(timepos1) > tonumber(timepos2) then | |
length = timepos1-timepos2 | |
start = timepos2 | |
start_humanreadable = timepos2_humanreadable | |
end_humanreadable = timepos1_humanreadable | |
msg.info("End frame set") | |
elseif tonumber(timepos2) > tonumber(timepos1) then | |
length = timepos2-timepos1 | |
start = timepos1 | |
start_humanreadable = timepos1_humanreadable | |
end_humanreadable = timepos2_humanreadable | |
msg.info("End frame set") | |
else | |
msg.error("Both frames are the same, ignoring the second one") | |
mp.osd_message("Both frames are the same, ignoring the second one") | |
timepos2 = nil | |
return | |
end | |
timepos1 = nil | |
mp.enable_key_bindings("draw_rectangle") | |
call_gui() | |
else | |
timepos1 = mp.get_property("time-pos") | |
timepos1_humanreadable = mp.get_property_osd("time-pos") | |
msg.info("Start frame set") | |
mp.osd_message("Start frame set") | |
end | |
end | |
------------ | |
-- Encode -- | |
------------ | |
function encode(codec,scale,audio,subs) | |
local ext_table = { | |
["webm"] = "webm", | |
["x264"] = "mkv", | |
["gif"] = "gif", | |
} | |
local ffmpeg_com_table = { | |
["webm"] = "-f webm ", | |
["x264"] = "-f matroska -c:v libx264 -preset slow", | |
["gif"] = "-f gif -r 24", | |
} | |
set_mouse_area = nil | |
if rect_width == nil or rect_width == 0 then | |
crop = "" | |
else | |
rect_width = round(rect_width) - (math.mod(round(rect_width), 2)) | |
rect_height = round(rect_height) - (math.mod(round(rect_height), 2)) | |
crop = rect_width .. ":" .. rect_height .. ":" .. round(rect_x1) .. ":" .. round(rect_y1) | |
if not aspect_first then | |
aspect_first = rect_width / rect_height | |
width_first = rect_width | |
height_first = rect_height | |
end | |
rect_width, rect_height = nil | |
end | |
local ffmpeg = options.ffmpeg | |
local video = mp.get_property("path") | |
video = string.gsub(video, "'", "'\\''") | |
local sid = mp.get_property("sid") | |
local sub_visibility = mp.get_property("sub-visibility") | |
local vf = mp.get_property("vf") | |
if string.len(vf) > 0 then | |
vf = vf .. "," | |
end | |
local sub_file_table = mp.get_property_native("options/sub-file") | |
local sub_file = "" | |
for index, param in pairs(sub_file_table) do | |
sub_file = sub_file .. " --sub-file='" .. string.gsub(tostring(param), "'", "'\\''") .. "'" | |
end | |
local sub_auto = mp.get_property("options/sub-auto") | |
local sub_delay = mp.get_property("sub-delay") | |
local colormatrix_input_range = mp.get_property_native("colormatrix-input-range") | |
local outdir | |
if options.use_pwd_instead then | |
local pwd = os.getenv("PWD") | |
outdir = pwd | |
else | |
outdir = options.output_directory | |
end | |
if outdir:reverse():sub(1,1) ~= "/" then | |
outdir = outdir .. "/" --Make sure it ends with a slash | |
end | |
local filename_ext = mp.get_property_osd("filename") | |
local filename = string.gsub(filename_ext, "%....$","") | |
local path = mp.get_property("path", "") | |
local dir, fil = mputils.split_path(path) | |
if dir:reverse():sub(1,1) ~= "/" then | |
dir = dir .. "/" --Make sure it ends with a slash (ocd) | |
end | |
local file_in = dir .. fil | |
local file_out = outdir .. filename .. " [" .. start_humanreadable .. "-" .. end_humanreadable .. "]." .. ext_table[codec] | |
file_in = string.gsub(file_in, "'", "'\\''") | |
file_out = string.gsub(file_out, "'", "'\\''") | |
local gen_command = ffmpeg .. ' -ss ' .. start .. ' -i \'' .. file_in .. '\' -t ' .. length .. ' -b:v ' .. bitrate .. ' -vf scale=' .. scale .. ':-1 -quality good -cpu-used 0 ' .. audio .. ' ' .. subs .. ' ' | |
local pass1_command = gen_command .. ffmpeg_com_table[codec] .. " -pass 1 -y /dev/null " | |
local pass2_command = gen_command .. ffmpeg_com_table[codec] .. " -pass 2 " .. "'" .. file_out .. "'" | |
local full_command = '( ' .. pass1_command .. ' && ' .. pass2_command .. [[ ) && notify-send 'Encode done!']] | |
msg.info(full_command) | |
os.execute([[bash -c "]] .. full_command .. [["]]) | |
end | |
--------- | |
-- GUI -- | |
--------- | |
function call_gui () | |
mp.resume_all() | |
local handle = io.popen('yad --title="Convert Script" --center --form --separator="\n" --field="Select codec:CB" "webm!x264!gif" --field="Resize to:NUM" "720" --field="Don’t resize at all:CHK" "false" --field="Include audio:CHK" "false" --field="Include subs:CHK" "false" --field="Target file size (kB):NUM" "3000" --button="gtk-cancel:2" --button="gtk-ok:0" && echo "$?"') | |
local yad = handle:read("*a") | |
handle:close() | |
if yad == "" then | |
return | |
end | |
local yad_table = {} | |
local i = 0 | |
for k in string.gmatch(yad, "[%a%d]+") do | |
i = i + 1 | |
yad_table[i] = k | |
end | |
local codec = yad_table[1] | |
local scale,audio,subs | |
if (yad_table[4] == "FALSE") then | |
scale = yad_table[2] | |
else | |
scale = "-1" | |
end | |
if yad_table[5] == "FALSE" then | |
audio = '-an' | |
else | |
audio = "" | |
end | |
if yad_table[6] == "FALSE" then | |
subs = '-sn' | |
else | |
subs = "" | |
end | |
--bitrate = yad_table[7] | |
bitrate = math.floor(yad_table[7]*1024*8/length*options.bitrate_multiplier) | |
mp.disable_key_bindings("draw_rectangle") | |
mp.set_osd_ass(width, height, "") | |
if yad_table[9] == "0" then | |
msg.info("Starting Encode") | |
encode(codec,scale,audio,subs) | |
end | |
end | |
mp.add_key_binding("alt+w", "convert_script", convert_script_hotkey_call) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment