Skip to content

Instantly share code, notes, and snippets.

@RRvW
Last active September 27, 2017 05:04
Show Gist options
  • Save RRvW/e83804bee80bddb59491 to your computer and use it in GitHub Desktop.
Save RRvW/e83804bee80bddb59491 to your computer and use it in GitHub Desktop.
MPV webm/h264/gif convert script
-- 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