flake/flakes/home-manager/guanranwang/common/dotfiles/config/mpv/scripts/mpv-gif.lua
2023-09-19 08:17:43 +08:00

191 lines
5.4 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Original by Ruin0x11
-- Ported to Windows by Scheliux, Dragoner7
-- Create animated GIFs with mpv
-- Requires ffmpeg.
-- Adapted from http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html
-- Usage: "b" to set start frame, "B" to set end frame, "Ctrl+b" to create.
require 'mp.options'
local msg = require 'mp.msg'
local options = {
dir = "C:/Program Files/mpv/gifs",
rez = 600,
fps = 15,
}
read_options(options, "gif")
local fps
-- Check for invalid fps values
-- Can you believe Lua doesn't have a proper ternary operator in the year of our lord 2020?
if options.fps ~= nil and options.fps >= 1 and options.fps < 30 then
fps = options.fps
else
fps = 15
end
-- Set this to the filters to pass into ffmpeg's -vf option.
-- filters="fps=24,scale=320:-1:flags=spline"
filters=string.format("fps=%s,scale='trunc(ih*dar/2)*2:trunc(ih/2)*2',setsar=1/1,scale=%s:-1:flags=spline", fps, options.rez) --change spline to lanczos depending on preference
-- Setup output directory
output_directory=string.gsub(options.dir, '\"', '')
start_time = -1
end_time = -1
palette="%TEMP%palette.png"
-- The roundabout way has to be used due to a some weird
-- behavior with %TEMP% on the subtitles= parameter in ffmpeg
-- on Windowsit needs to be quadruple backslashed
subs = "C:/Users/%USERNAME%/AppData/Local/Temp/subs.srt"
function make_gif_with_subtitles()
make_gif_internal(true)
end
function make_gif()
make_gif_internal(false)
end
function table_length(t)
local count = 0
for _ in pairs(t) do count = count + 1 end
return count
end
function make_gif_internal(burn_subtitles)
local start_time_l = start_time
local end_time_l = end_time
if start_time_l == -1 or end_time_l == -1 or start_time_l >= end_time_l then
mp.osd_message("Invalid start/end time.")
return
end
mp.osd_message("Creating GIF.")
-- shell escape
function esc(s)
return string.gsub(s, '"', '"\\""')
end
function esc_for_sub(s)
s = string.gsub(s, [[\]], [[/]])
s = string.gsub(s, '"', '"\\""')
s = string.gsub(s, ":", [[\\:]])
s = string.gsub(s, "'", [[\\']])
return s
end
local pathname = mp.get_property("path", "")
local trim_filters = esc(filters)
local position = start_time_l
local duration = end_time_l - start_time_l
if burn_subtitles then
-- Determine currently active sub track
local i = 0
local tracks_count = mp.get_property_number("track-list/count")
local subs_array = {}
-- check for subtitle tracks
while i < tracks_count do
local type = mp.get_property(string.format("track-list/%d/type", i))
local selected = mp.get_property(string.format("track-list/%d/selected", i))
-- if it's a sub track, save it
if type == "sub" then
local length = table_length(subs_array)
subs_array[length] = selected == "yes"
end
i = i + 1
end
if table_length(subs_array) > 0 then
local correct_track = 0
-- iterate through saved subtitle tracks until the correct one is found
for index, is_selected in pairs(subs_array) do
if (is_selected) then
correct_track = index
end
end
trim_filters = trim_filters .. string.format(",subtitles=%s:si=%s", esc_for_sub(pathname), correct_track)
end
end
-- first, create the palette
args = string.format('ffmpeg -v warning -ss %s -t %s -i "%s" -vf "%s,palettegen" -y "%s"', position, duration, esc(pathname), esc(trim_filters), esc(palette))
msg.debug(args)
os.execute(args)
-- then, make the gif
local filename = mp.get_property("filename/no-ext")
local file_path = output_directory .. "/" .. filename
-- increment filename
for i=0,999 do
local fn = string.format('%s_%03d.gif',file_path,i)
if not file_exists(fn) then
gifname = fn
break
end
end
if not gifname then
mp.osd_message('No available filenames!')
return
end
local copyts = ""
if burn_subtitles then
copyts = "-copyts"
end
args = string.format('ffmpeg -v warning -ss %s %s -t %s -i "%s" -i "%s" -lavfi "%s [x]; [x][1:v] paletteuse" -y "%s"', position, copyts, duration, esc(pathname), esc(palette), esc(trim_filters), esc(gifname))
os.execute(args)
local ok, err, code = os.rename(gifname, gifname)
if ok then
msg.info("GIF created: " .. gifname)
mp.osd_message("GIF created: " .. gifname)
else
mp.osd_message("Error creating file, check CLI for more info.")
end
end
function set_gif_start()
start_time = mp.get_property_number("time-pos", -1)
mp.osd_message("GIF Start: " .. start_time)
end
function set_gif_end()
end_time = mp.get_property_number("time-pos", -1)
mp.osd_message("GIF End: " .. end_time)
end
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
-- all keybindings here are set to nil on purpose 'cause I modified the keybindings (in input.conf)
mp.add_key_binding(nil, "set_gif_start", set_gif_start)
mp.add_key_binding(nil, "set_gif_end", set_gif_end)
mp.add_key_binding(nil, "make_gif", make_gif)
mp.add_key_binding(nil, "make_gif_with_subtitles", make_gif_with_subtitles) -- making GIFs with subtitles doesn't seem to work