From 39171a428542db4080756c66235c355480c1d75a Mon Sep 17 00:00:00 2001 From: Harley Date: Tue, 7 Jul 2026 23:55:20 -0400 Subject: [PATCH] Dynamic FPS: WebP/GIF inherit source fps (min 30) Replaces hardcoded WEBP_FPS=15/GIF_FPS=15 with source_fps() that reads mf-fps, video-params/fps, or estimated-vf-fps, flooring at 30. --- scripts/export-loop-webp.lua | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/scripts/export-loop-webp.lua b/scripts/export-loop-webp.lua index 81a0cf2..d2553ff 100644 --- a/scripts/export-loop-webp.lua +++ b/scripts/export-loop-webp.lua @@ -19,16 +19,26 @@ local OUTPUT_DIR = os.getenv("HOME") .. "/Videos/mpv-loops" local GIF_DIR = OUTPUT_DIR .. "/gif" local ENABLE_OSD_MSG = true --- WebP settings -local WEBP_FPS = 15 +-- Detect source frame rate (handles mf:// from webp-anim-bridge). +-- Returns at least 30fps. +local function source_fps() + local mf_fps = mp.get_property_number("mf-fps", 0) + if mf_fps and mf_fps > 0 then return math.max(30, mf_fps) end + local vfps = mp.get_property_number("video-params/fps", 0) + if vfps and vfps > 0 then return math.max(30, vfps) end + local efps = mp.get_property_number("estimated-vf-fps", 0) + if efps and efps > 0 then return math.max(30, efps) end + return 30 +end + +-- Config — FPS is now dynamic via source_fps(). Fallback minimum for mf:// only. local WEBP_QUALITY = 80 local WEBP_LOSSLESS = false local WEBP_MAX_WIDTH = 800 local WEBP_LOOP = 0 -- GIF settings -local GIF_FPS = 15 -local GIF_MAX_WIDTH = 800 -- bumped from 600 to match WebP +local GIF_MAX_WIDTH = 800 local GIF_DITHER = "bayer" local GIF_LOOP = 0 @@ -96,10 +106,11 @@ end -- Build the WebP vf string (fps + optional eq + zoom/pan crop) local function build_webp_vf(include_eq) + local fps = source_fps() local parts = {} local crop = zoom_pan_crop() if crop then table.insert(parts, crop) end - table.insert(parts, string.format("fps=%d", WEBP_FPS)) + table.insert(parts, string.format("fps=%d", fps)) if include_eq then local eq = build_eq_filter() if eq then table.insert(parts, eq) end @@ -109,10 +120,11 @@ end -- Build the GIF vf string (fps + optional eq + palettegen/paletteuse + zoom/pan crop) local function build_gif_vf(include_eq) + local fps = source_fps() local parts = {} local crop = zoom_pan_crop() if crop then table.insert(parts, crop) end - table.insert(parts, string.format("fps=%d", GIF_FPS)) + table.insert(parts, string.format("fps=%d", fps)) if include_eq then local eq = build_eq_filter() if eq then table.insert(parts, eq) end @@ -148,7 +160,7 @@ local function build_ffmpeg_seek_args(a, b) if pattern:sub(1, 5) == "mf://" then pattern = pattern:sub(6) end - local mf_fps = mp.get_property_number("mf-fps", 10) + local mf_fps = source_fps() table.insert(args, "-framerate"); table.insert(args, tostring(mf_fps)) table.insert(args, "-start_number"); table.insert(args, "0") table.insert(args, "-i"); table.insert(args, pattern)