Skip to content

Instantly share code, notes, and snippets.

@SpaghettiBorgar
Created April 5, 2020 18:42
Show Gist options
  • Save SpaghettiBorgar/06fe8afd6e0a5fe3a3015780929ea828 to your computer and use it in GitHub Desktop.
Save SpaghettiBorgar/06fe8afd6e0a5fe3a3015780929ea828 to your computer and use it in GitHub Desktop.
mpv script to quickly create gifs, video clips, and sound clips
-- Create animated GIFs with mpv
-- Requires ffmpeg, gifski, exiftool, and vorbis-tools.
-- Based on github.com/Scheliux/mpv-gif-generator
-- Usage: "g" to set start frame, "G" to set end frame,
-- "Ctrl+g" to create gif
-- "Ctrl+v" to create video clip
-- "Ctrl+a" to create audio clip
-- Metadata about the filename and timestamps will be written in the comment tag
local msg = require 'mp.msg'
home = os.getenv("HOME")
-- Quality Settings
gif_fps = 12
gif_width = 540
gif_quality = 90
gif_folder = home.."/mpv/gifs/"
vid_crf = 20
vid_width = -1
vid_folder = home.."/mpv/vid/"
snd_bitrate = 128
snd_folder = home.."/mpv/snd/"
gif_filters=string.format("fps=%s,scale=%s:-1:flags=lanczos", gif_fps, gif_width)
vid_filters=string.format("scale=%s:-1:flags=lanczos", vid_width)
start_time = -1
end_time = -1
mode = "gif"
function make()
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
local type = ""
if mode=="gif" then
type = "GIF"
elseif mode=="vid" then
type = "Video Clip"
elseif mode=="snd" then
type = "Sound Clip"
end
mp.osd_message("Creating "..type)
function esc(s)
return s:gsub("'", "'\\''")
end
local position = start_time_l
local duration = end_time_l - start_time_l
local path = mp.get_property("path")
local directory = get_containing_path(path)
local filename = mp.get_property("filename/no-ext")
local extension = ""
local directory = ""
if mode=="gif" then
extension = "gif"
directory = gif_folder
elseif mode=="vid" then
extension = "mp4"
directory = vid_folder
elseif mode=="snd" then
extension = "ogg"
directory = snd_folder
end
os.execute("mkdir -p "..directory)
for i=0,999 do
local fn = string.format('%s_%03d.%s', directory..filename, i, extension)
if not file_exists(fn) then
outfile = fn
break
end
end
if not outfile then
mp.osd_message('No available filenames!')
return
end
if mode == "gif" then
framenames = "/tmp/mpv/%04d.png"
os.execute("mkdir -p /tmp/mpv && rm /tmp/mpv/*")
os.execute(string.format("ffmpeg -ss %s -t %s -i '%s' -lavfi '%s' -y '%s'", position, duration, esc(path), gif_filters, framenames))
os.execute(string.format("gifski --fps %s --quality %s /tmp/mpv/* -o '%s'", gif_fps, gif_quality, esc(outfile)))
elseif mode == "vid" then
os.execute(string.format("ffmpeg -ss %s -i '%s' -t %s -lavfi '%s' -async 1 -crf %s -y '%s'", position, esc(path), duration, vid_filters, vid_crf, esc(outfile)))
elseif mode == "snd" then
os.execute(string.format("ffmpeg -ss %s -t %s -i '%s' -vn -c:a libvorbis -ab %sk -y '%s'", position, duration, esc(path), snd_bitrate, esc(outfile)))
end
if file_exists(outfile) then
if mode == "snd" then
os.execute(string.format("vorbiscomment -wRt comment='%s %s %s' '%s'", esc(filename), position, duration, esc(outfile)))
else
os.execute(string.format("exiftool -overwrite_original_in_place -comment='%s %s %s' '%s'", esc(filename), position, duration, esc(outfile)))
end
msg.info(type.." created.")
mp.osd_message(type.." created.")
else
msg.info("Failed to create "..type)
mp.osd_message("Failed to create "..type)
end
end
function make_gif()
mode = "gif"
make()
end
function make_vid()
mode = "vid"
make()
end
function make_snd()
mode = "snd"
make()
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
function get_containing_path(str,sep)
sep=sep or package.config:sub(1,1)
return str:match("(.*"..sep..")")
end
mp.add_key_binding("g", "set_gif_start", set_gif_start)
mp.add_key_binding("G", "set_gif_end", set_gif_end)
mp.add_key_binding("Ctrl+g", "make_gif", make_gif)
mp.add_key_binding("Ctrl+v", "make_vid", make_vid)
mp.add_key_binding("Ctrl+a", "make_snd", make_snd)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment