Skip to content

Commit

Permalink
Added mpv-gif script
Browse files Browse the repository at this point in the history
  • Loading branch information
noelsimbolon committed Jan 23, 2022
1 parent 62e178a commit b3599d8
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 9 deletions.
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ for the options in `mpv.conf` and `input.conf`.
## Preview
[![preview.png](https://i.postimg.cc/D030DGqD/preview.png)](https://postimg.cc/XGxnBp1c)

## Installation and Usage (in Windows)
## Installation (on Windows)

Here are the steps to install mpv and to use my configuration files in Windows:
Here are the steps to install mpv and to use my configuration files on Windows:
* Download the latest 64bit mpv Windows build by shinchiro from [mpv.io/installation](https://mpv.io/installation/) or directly from [here](https://sourceforge.net/projects/mpv-player-windows/files/) and extract it wherever you please. This is now your mpv folder
* Run `mpv-install.bat`, which is located in `installer` folder, with administrator priviledges by right-clicking and selecting Run as administrator
* Download the ZIP file from [this repo's latest release](https://github.com/noelsimbolon/mpv-config/releases/latest) and extract it to your mpv folder. Make sure the configuration folder name is `portable_config` (this is important) and is located at the same directory as `mpv.exe`
* To make `discord.lua` work, open `discord.conf`, which is located in `portable_config/script-opts` folder, with a text editor and specify the `binary_path` which is the full path to `mpv-discord.exe`. For example `binary_path=C:\Your\mpv\folder\path\portable_config\bin\mpv-discord.exe`
* (Optional) Make your own mpv configuration. You can do that by modifying my configuration files and/or making your own from scratch. Check out the [useful links](#useful-links) section for mpv configuration guides.
* Download the ZIP file from this repo's [latest release](https://github.com/noelsimbolon/mpv-config/releases/latest) and extract it to your mpv folder. Make sure the configuration folder name is `portable_config` (this is important) and is located at the same directory as `mpv.exe`
* To make some scripts work, you need to modify them from the release a little bit:
* For `discord.lua` to work, open `discord.conf`, which is located in `portable_config/script-opts` folder, with a text editor and specify the `binary_path` which is the full path to `mpv-discord.exe`. For example `binary_path="C:\YOUR\MPV\FOLDER\PATH\portable_config\bin\mpv-discord.exe"`
* (Optional) By default, the `mpv-gif.lua` script saves GIFs to `C:/Program Files/mpv/gifs`. To modify this, open `gif.conf`, which is located in `portable_config/script-opts` folder, with a text editor and specify the `dir`, which is output directory for GIFs, as you please. For example `dir="C:/Users/USERNAME/Pictures/mpv-gifs"`.
* (Optional) Make your own mpv configuration. You can do that by modifying my configuration files and/or making your own from scratch or modifying others' configurations. Check out the [useful links](#useful-links) section for mpv configuration guides.
* You are now a proud user of the best media player

After following the steps above (without the optional step), your mpv folder should have this structure:
Expand Down Expand Up @@ -50,19 +52,21 @@ After following the steps above (without the optional step), your mpv folder sho
│ │
│ ├── script-opts # Contains configuration files for scripts
│ │ ├── discord.conf
│ │ ├── gif.conf
│ │ └── osc.conf
│ │
│ ├── scripts
│ │ ├── audio_visualizer.lua
│ │ ├── audio_visualizer.lua # Script to visualize audio playback when playing audio files
│ │ ├── autoload.lua
│ │ ├── cycle-commands.lua
│ │ ├── cycle-profile.lua
│ │ ├── discord.lua
│ │ ├── mordenx.lua
│ │ ├── discord.lua # Script for Discord rich presence
│ │ ├── mordenx.lua # Script for modern OSC UI
│ │ ├── mpv-gif.lua # Script to create GIFs
│ │ └── playlistmanager.lua
│ │
│ ├── shaders # Contains external shaders
│ │ ├── cache # This folder might not show at first
│ │ ├── cache # Cause of gpu-shader-cache-dir='~~/shaders/cache' in mpv.conf (might not show at first)
│ │ │ └── ...
│ │ ├── FSRCNNX_x2_16-0-4-1.glsl
│ │ ├── KrigBilateral.glsl
Expand Down
1 change: 1 addition & 0 deletions input.conf
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,4 @@ l cycle-values sub-ass-override "yes" "force" "no" # https://mpv.io

# SCRIPTS
# ~ script-message cycle-commands "apply-profile HDR ; show-text 'HDR profile applied'" "apply-profile HDR restore ; show-text 'HDR profile restored'"
# b, B, ctrl+b, and ctrl+B are occupied by mpv-gif.lua script
10 changes: 10 additions & 0 deletions script-opts/gif.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# ========== CONFIGURATION FILE FOR MPV-GIF.LUA ==========

# Sets the output directory
dir=

# Sets the resolution of the output GIFs
rez=1920

# Sets the framerate of the output gifs. Default is 15. Don't go too overboard or the filesize will balloon
fps=23
190 changes: 190 additions & 0 deletions scripts/mpv-gif.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
-- 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 Windows–it 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

mp.add_key_binding("b", "set_gif_start", set_gif_start)
mp.add_key_binding("B", "set_gif_end", set_gif_end)
mp.add_key_binding("Ctrl+b", "make_gif", make_gif)
mp.add_key_binding("Ctrl+B", "make_gif_with_subtitles", make_gif_with_subtitles)

0 comments on commit b3599d8

Please sign in to comment.