Last active
March 26, 2024 01:01
-
-
Save Ruin0x11/8fae0a9341b41015935f76f913b28d2a to your computer and use it in GitHub Desktop.
Create animated GIFs using mpv
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
-- Create animated GIFs with mpv | |
-- Requires ffmpeg. | |
-- Adapted from http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html | |
-- Usage: "g" to set start frame, "G" to set end frame, "Ctrl+g" to create. | |
local msg = require 'mp.msg' | |
-- Set this to the filters to pass into ffmpeg's -vf option. | |
-- filters="fps=24,scale=320:-1:flags=lanczos" | |
filters="fps=15,scale=540:-1:flags=lanczos" | |
start_time = -1 | |
end_time = -1 | |
palette="/tmp/palette.png" | |
function make_gif_with_subtitles() | |
make_gif_internal(true) | |
end | |
function make_gif() | |
make_gif_internal(false) | |
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 | |
local pathname = mp.get_property("working-directory", "") .. "/" .. mp.get_property("path", "") | |
local trim_filters = esc(filters) | |
if burn_subtitles then | |
-- TODO: get current subtitle | |
trim_filters = trim_filters .. string.format(",subtitles=%s", esc(pathname)) | |
end | |
local position = start_time_l | |
local duration = end_time_l - start_time_l | |
-- 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 | |
stream_path = mp.get_property("working-directory") .. "/" .. mp.get_property("path") | |
local working_path = get_containing_path(stream_path) | |
local filename = mp.get_property("filename/no-ext") | |
local file_path = working_path .. 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 | |
args = string.format("ffmpeg -v warning -ss %s -t %s -i '%s' -i '%s' -lavfi '%s [x]; [x][1:v] paletteuse' -y '%s'", position, duration, esc(pathname), esc(palette), esc(trim_filters), esc(gifname)) | |
os.execute(args) | |
msg.info("GIF created.") | |
mp.osd_message("GIF created.") | |
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+G", "make_gif_with_subtitles", make_gif_with_subtitles) |
So the problem here is relatively simple. The script assumes that the file opened is given as a relative path, which isn't true if mpv has been opened using the .application
files (i.e. double click on the video in the file browser).
The relatively simple solution for this is to add the following function:
function get_path()
local file_path = mp.get_property("path", "")
if not string.sub(file_path,1,1) == "/" then -- probably relative path
file_path = mp.get_property("working-directory", "") .. "/" .. file_path
end
return file_path
end
And replace the mentions of mp.get_property("working-directory") .. "/" .. mp.get_property("path")
(or similar) with get_path()
Here is the improved version: https://github.com/arandomliz/mpv-gif-generator
Also subtitles actually work and the commands are run safely with async
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Does it actually work on linux? It seems script shows message "GIF created" only, there is no gif file.