🔧 Updates to configs for mpv

This commit is contained in:
z3rOR0ne 2024-06-22 17:42:28 -07:00
parent ab6733fe95
commit 8789ffc5e8
3 changed files with 3570 additions and 4191 deletions

View file

@ -0,0 +1,74 @@
# The thumbnail cache directory.
# On Windows this defaults to %TEMP%\mpv_thumbs_cache,
# and on other platforms to /tmp/mpv_thumbs_cache.
# The directory will be created automatically, but must be writeable!
# Use absolute paths, and take note that environment variables like %TEMP% are unsupported (despite the default)!
cache_directory=/tmp/my_mpv_thumbnails
# THIS IS NOT A WINDOWS PATH. COMMENT IT OUT OR ADJUST IT YOURSELF.
# Whether to generate thumbnails automatically on video load, without a keypress
# Defaults to yes
# autogenerate=[yes/no]
autogenerate=yes
# Only automatically thumbnail videos shorter than this (in seconds)
# You will have to press T (or your own keybind) to enable the thumbnail previews
# Set to 0 to disable the check, ie. thumbnail videos no matter how long they are
# Defaults to 3600 (one hour)
autogenerate_max_duration=3600
# Use mpv to generate thumbnail even if ffmpeg is found in PATH
# ffmpeg is slightly faster than mpv but lacks support for ordered chapters in MKVs,
# which can break the resulting thumbnails. You have been warned.
# Defaults to yes (don't use ffmpeg)
# prefer_mpv=[yes/no]
prefer_mpv=yes
# Explicitly disable subtitles on the mpv sub-calls
# mpv can and will by default render subtitles into the thumbnails.
# If this is not what you wish, set mpv_no_sub to yes
# Defaults to no
mpv_no_sub=yes
# Enable to disable the built-in keybind ("T") to add your own, see after the block
disable_keybinds=no
# The maximum dimensions of the thumbnails, in pixels
# Defaults to 200 and 200
thumbnail_width=200
thumbnail_height=200
# The thumbnail count target
# (This will result in a thumbnail every ~10 seconds for a 25 minute video)
thumbnail_count=150
# The above target count will be adjusted by the minimum and
# maximum time difference between thumbnails.
# The thumbnail_count will be used to calculate a target separation,
# and min/max_delta will be used to constrict it.
# In other words, thumbnails will be:
# - at least min_delta seconds apart (limiting the amount)
# - at most max_delta seconds apart (raising the amount if needed)
# Defaults to 5 and 90, values are seconds
min_delta=5
max_delta=90
# 120 seconds aka 2 minutes will add more thumbnails only when the video is over 5 hours long!
# Below are overrides for remote urls (you generally want less thumbnails, because it's slow!)
# Thumbnailing network paths will be done with mpv (leveraging youtube-dl)
# Allow thumbnailing network paths (naive check for "://")
# Defaults to no
# thumbnail_network=[yes/no]
thumbnail_network=no
# Override thumbnail count, min/max delta, as above
remote_thumbnail_count=60
remote_min_delta=15
remote_max_delta=120
# Try to grab the raw stream and disable ytdl for the mpv subcalls
# Much faster than passing the url to ytdl again, but may cause problems with some sites
# Defaults to yes
# remote_direct_stream=[yes/no]
remote_direct_stream=no

File diff suppressed because it is too large Load diff

View file

@ -13,26 +13,26 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
]]-- ]]
--
--[[ --[[
mpv_thumbnail_script.lua unknown - commit unknown (branch unknown) mpv_thumbnail_script.lua 0.4.2 - commit a2de250 (branch master)
https://github.com/TheAMM/mpv_thumbnail_script https://github.com/TheAMM/mpv_thumbnail_script
Built on 2023-11-14 05:54:49 Built on 2018-02-07 20:36:54
]]-- ]]
local assdraw = require 'mp.assdraw' --
local msg = require 'mp.msg' local assdraw = require("mp.assdraw")
local opt = require 'mp.options' local msg = require("mp.msg")
local utils = require 'mp.utils' local opt = require("mp.options")
local utils = require("mp.utils")
-- Determine if the platform is Windows -- -- Determine platform --
ON_WINDOWS = (package.config:sub(1,1) ~= '/') ON_WINDOWS = (package.config:sub(1, 1) ~= "/")
-- Determine if the platform is MacOS --
local uname = io.popen("uname -s"):read("*l")
ON_MAC = not ON_WINDOWS and (uname == "Mac" or uname == "Darwin")
-- Some helper functions needed to parse the options -- -- Some helper functions needed to parse the options --
function isempty(v) return not v or (v == "") or (v == 0) or (type(v) == "table" and not next(v)) end function isempty(v)
return (v == false) or (v == nil) or (v == "") or (v == 0) or (type(v) == "table" and next(v) == nil)
end
function divmod(a, b) function divmod(a, b)
return math.floor(a / b), a % b return math.floor(a / b), a % b
@ -45,7 +45,7 @@ end
function join_paths(...) function join_paths(...)
local sep = ON_WINDOWS and "\\" or "/" local sep = ON_WINDOWS and "\\" or "/"
local result = ""; local result = ""
for i, p in pairs({ ... }) do for i, p in pairs({ ... }) do
if p ~= "" then if p ~= "" then
if is_absolute_path(p) then if is_absolute_path(p) then
@ -61,9 +61,9 @@ end
-- /some/path/file.ext -> /some/path, file.ext -- /some/path/file.ext -> /some/path, file.ext
function split_path(path) function split_path(path)
local sep = ON_WINDOWS and "\\" or "/" local sep = ON_WINDOWS and "\\" or "/"
local first_index, last_index = path:find('^.*' .. sep) local first_index, last_index = path:find("^.*" .. sep)
if not last_index then if last_index == nil then
return "", path return "", path
else else
local dir = path:sub(0, last_index - 1) local dir = path:sub(0, last_index - 1)
@ -81,7 +81,9 @@ end
function Set(source) function Set(source)
local set = {} local set = {}
for _, l in ipairs(source) do set[l] = true end for _, l in ipairs(source) do
set[l] = true
end
return set return set
end end
@ -111,10 +113,10 @@ end
function file_exists(name) function file_exists(name)
local f = io.open(name, "rb") local f = io.open(name, "rb")
if f then if f ~= nil then
local ok, err, code = f:read(1) local ok, err, code = f:read(1)
io.close(f) io.close(f)
return not code return code == nil
else else
return false return false
end end
@ -122,7 +124,7 @@ end
function path_exists(name) function path_exists(name)
local f = io.open(name, "rb") local f = io.open(name, "rb")
if f then if f ~= nil then
io.close(f) io.close(f)
return true return true
else else
@ -166,7 +168,7 @@ local ExecutableFinder = { path_cache = {} }
function ExecutableFinder:get_executable_path(name, raw_name) function ExecutableFinder:get_executable_path(name, raw_name)
name = ON_WINDOWS and not raw_name and (name .. ".exe") or name name = ON_WINDOWS and not raw_name and (name .. ".exe") or name
if not self.path_cache[name] then if self.path_cache[name] == nil then
self.path_cache[name] = find_executable(name) or false self.path_cache[name] = find_executable(name) or false
end end
return self.path_cache[name] return self.path_cache[name]
@ -174,8 +176,8 @@ end
-- Format seconds to HH.MM.SS.sss -- Format seconds to HH.MM.SS.sss
function format_time(seconds, sep, decimals) function format_time(seconds, sep, decimals)
decimals = decimals or 3 decimals = decimals == nil and 3 or decimals
sep = sep or "." sep = sep and sep or "."
local s = seconds local s = seconds
local h, s = divmod(s, 60 * 60) local h, s = divmod(s, 60 * 60)
local m, s = divmod(s, 60) local m, s = divmod(s, 60)
@ -187,8 +189,8 @@ end
-- Format seconds to 1h 2m 3.4s -- Format seconds to 1h 2m 3.4s
function format_time_hms(seconds, sep, decimals, force_full) function format_time_hms(seconds, sep, decimals, force_full)
decimals = decimals or 1 decimals = decimals == nil and 1 or decimals
sep = sep or " " sep = sep ~= nil and sep or " "
local s = seconds local s = seconds
local h, s = divmod(s, 60 * 60) local h, s = divmod(s, 60 * 60)
@ -272,7 +274,6 @@ function create_temporary_file(base, mode, suffix)
return handle, filename return handle, filename
end end
function get_processor_count() function get_processor_count()
local proc_count local proc_count
@ -280,15 +281,17 @@ function get_processor_count()
proc_count = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) proc_count = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
else else
local cpuinfo_handle = io.open("/proc/cpuinfo") local cpuinfo_handle = io.open("/proc/cpuinfo")
if cpuinfo_handle then if cpuinfo_handle ~= nil then
local cpuinfo_contents = cpuinfo_handle:read("*a") local cpuinfo_contents = cpuinfo_handle:read("*a")
local _, replace_count = cpuinfo_contents:gsub('processor', '') local _, replace_count = cpuinfo_contents:gsub("processor", "")
proc_count = replace_count proc_count = replace_count
end end
end end
if proc_count and proc_count > 0 then if proc_count and proc_count > 0 then
return proc_count return proc_count
else
return nil
end end
end end
@ -302,7 +305,7 @@ function substitute_values(string, values)
end end
end end
local substituted = string:gsub('%%(.)', substitutor) local substituted = string:gsub("%%(.)", substitutor)
return substituted return substituted
end end
@ -344,7 +347,7 @@ function round_rect(ass, x0, y0, x1, y1, rtl, rtr, rbr, rbl)
end end
local SCRIPT_NAME = "mpv_thumbnail_script" local SCRIPT_NAME = "mpv_thumbnail_script"
local default_cache_base = ON_WINDOWS and os.getenv("TEMP") or (os.getenv("XDG_CACHE_HOME") or "/tmp/") local default_cache_base = ON_WINDOWS and os.getenv("TEMP") or "/tmp/"
local thumbnailer_options = { local thumbnailer_options = {
-- The thumbnail directory -- The thumbnail directory
@ -377,10 +380,6 @@ local thumbnailer_options = {
-- Add a "--profile=<mpv_profile>" to the mpv sub-call arguments -- Add a "--profile=<mpv_profile>" to the mpv sub-call arguments
-- Use "" to disable -- Use "" to disable
mpv_profile = "", mpv_profile = "",
-- Hardware decoding
mpv_hwdec = "no",
-- High precision seek
mpv_hr_seek = "yes",
-- Output debug logs to <thumbnail_path>.log, ala <cache_directory>/<video_filename>/000000.bgra.log -- Output debug logs to <thumbnail_path>.log, ala <cache_directory>/<video_filename>/000000.bgra.log
-- The logs are removed after successful encodes, unless you set mpv_keep_logs below -- The logs are removed after successful encodes, unless you set mpv_keep_logs below
mpv_logs = true, mpv_logs = true,
@ -450,14 +449,11 @@ local thumbnailer_options = {
-- 120 seconds aka 2 minutes will add more thumbnails when the video is over 5 hours! -- 120 seconds aka 2 minutes will add more thumbnails when the video is over 5 hours!
max_delta = 90, max_delta = 90,
-- Overrides for remote urls (you generally want less thumbnails!) -- Overrides for remote urls (you generally want less thumbnails!)
-- Thumbnailing network paths will be done with mpv -- Thumbnailing network paths will be done with mpv
-- Allow thumbnailing network paths (naive check for "://") -- Allow thumbnailing network paths (naive check for "://")
thumbnail_network = false, thumbnail_network = false,
-- Same as autogenerate_max_duration but for remote videos
remote_autogenerate_max_duration = 1200, -- 20 min
-- Override thumbnail count, min/max delta -- Override thumbnail count, min/max delta
remote_thumbnail_count = 60, remote_thumbnail_count = 60,
remote_min_delta = 15, remote_min_delta = 15,
@ -466,13 +462,6 @@ local thumbnailer_options = {
-- Try to grab the raw stream and disable ytdl for the mpv subcalls -- Try to grab the raw stream and disable ytdl for the mpv subcalls
-- Much faster than passing the url to ytdl again, but may cause problems with some sites -- Much faster than passing the url to ytdl again, but may cause problems with some sites
remote_direct_stream = true, remote_direct_stream = true,
-- Enable storyboards (requires yt-dlp in PATH). Currently only supports YouTube and Twitch VoDs
storyboard_enable = true,
-- Max thumbnails for storyboards. It only skips processing some of the downloaded thumbnails and doesn't make it much faster
storyboard_max_thumbnail_count = 800,
-- Most storyboard thumbnails are 160x90. Enabling this allows upscaling them up to thumbnail_height
storyboard_upscale = false,
} }
read_options(thumbnailer_options, SCRIPT_NAME) read_options(thumbnailer_options, SCRIPT_NAME)
@ -487,8 +476,8 @@ end
function create_thumbnail_mpv(file_path, timestamp, size, output_path, options) function create_thumbnail_mpv(file_path, timestamp, size, output_path, options)
options = options or {} options = options or {}
local ytdl_disabled = not options.enable_ytdl and (mp.get_property_native("ytdl") == false local ytdl_disabled = not options.enable_ytdl
or thumbnailer_options.remote_direct_stream) and (mp.get_property_native("ytdl") == false or thumbnailer_options.remote_direct_stream)
local header_fields_arg = nil local header_fields_arg = nil
local header_fields = mp.get_property_native("http-header-fields") local header_fields = mp.get_property_native("http-header-fields")
@ -504,10 +493,8 @@ function create_thumbnail_mpv(file_path, timestamp, size, output_path, options)
local log_arg = "--log-file=" .. output_path .. ".log" local log_arg = "--log-file=" .. output_path .. ".log"
local mpv_path = ON_MAC and "/opt/homebrew/bin/mpv" or "mpv" local mpv_command = skip_nil({
"mpv",
local mpv_command = skip_nil{
mpv_path,
-- Hide console output -- Hide console output
"--msg-level=all=no", "--msg-level=all=no",
@ -518,68 +505,63 @@ function create_thumbnail_mpv(file_path, timestamp, size, output_path, options)
-- Pass User-Agent and Referer - should do no harm even with ytdl active -- Pass User-Agent and Referer - should do no harm even with ytdl active
"--user-agent=" .. mp.get_property_native("user-agent"), "--user-agent=" .. mp.get_property_native("user-agent"),
"--referrer=" .. mp.get_property_native("referrer"), "--referrer=" .. mp.get_property_native("referrer"),
-- User set hardware decoding -- Disable hardware decoding
"--hwdec=" .. thumbnailer_options.mpv_hwdec, "--hwdec=no",
-- Insert --no-config, --profile=... and --log-file if enabled -- Insert --no-config, --profile=... and --log-file if enabled
(thumbnailer_options.mpv_no_config and "--no-config" or nil), (thumbnailer_options.mpv_no_config and "--no-config" or nil),
profile_arg, profile_arg,
(thumbnailer_options.mpv_logs and log_arg or nil), (thumbnailer_options.mpv_logs and log_arg or nil),
file_path,
"--start=" .. tostring(timestamp), "--start=" .. tostring(timestamp),
"--frames=1", "--frames=1",
"--hr-seek=" .. thumbnailer_options.mpv_hr_seek, "--hr-seek=yes",
"--no-audio", "--no-audio",
-- Optionally disable subtitles -- Optionally disable subtitles
(thumbnailer_options.mpv_no_sub and "--no-sub" or nil), (thumbnailer_options.mpv_no_sub and "--no-sub" or nil),
(options.relative_scale ("--vf=scale=%d:%d"):format(size.w, size.h),
and ("--vf=scale=iw*%d:ih*%d"):format(size.w, size.h)
or ("--vf=scale=%d:%d"):format(size.w, size.h)),
"--vf-add=format=bgra", "--vf-add=format=bgra",
"--of=rawvideo", "--of=rawvideo",
"--ovc=rawvideo", "--ovc=rawvideo",
("--o=%s"):format(output_path), -- "--o",
output_path,
"--", })
return utils.subprocess({ args = mpv_command })
file_path,
}
return mp.command_native{name="subprocess", args=mpv_command}
end end
function create_thumbnail_ffmpeg(file_path, timestamp, size, output_path)
function create_thumbnail_ffmpeg(file_path, timestamp, size, output_path, options)
options = options or {}
local ffmpeg_path = ON_MAC and "/opt/homebrew/bin/ffmpeg" or "ffmpeg"
local ffmpeg_command = { local ffmpeg_command = {
ffmpeg_path, "ffmpeg",
"-loglevel", "quiet", "-loglevel",
"quiet",
"-noaccurate_seek", "-noaccurate_seek",
"-ss", format_time(timestamp, ":"), "-ss",
"-i", file_path, format_time(timestamp, ":"),
"-i",
file_path,
"-frames:v", "1", "-frames:v",
"1",
"-an", "-an",
"-vf", "-vf",
(options.relative_scale ("scale=%d:%d"):format(size.w, size.h),
and ("scale=iw*%d:ih*%d"):format(size.w, size.h) "-c:v",
or ("scale=%d:%d"):format(size.w, size.h)), "rawvideo",
"-pix_fmt",
"bgra",
"-f",
"rawvideo",
"-c:v", "rawvideo", "-y",
"-pix_fmt", "bgra", output_path,
"-f", "rawvideo",
"-y", output_path,
} }
return mp.command_native{name="subprocess", args=ffmpeg_command} return utils.subprocess({ args = ffmpeg_command })
end end
function check_output(ret, output_path, is_mpv) function check_output(ret, output_path, is_mpv)
local log_path = output_path .. ".log" local log_path = output_path .. ".log"
local success = true local success = true
@ -587,6 +569,7 @@ function check_output(ret, output_path, is_mpv)
if ret.killed_by_us then if ret.killed_by_us then
return nil return nil
else else
print("ret.status :=>", ret.status)
if ret.error or ret.status ~= 0 then if ret.error or ret.status ~= 0 then
msg.error("Thumbnailing command failed!") msg.error("Thumbnailing command failed!")
msg.error("mpv process error:", ret.error) msg.error("mpv process error:", ret.error)
@ -595,12 +578,12 @@ function check_output(ret, output_path, is_mpv)
msg.error("Debug log:", log_path) msg.error("Debug log:", log_path)
end end
success = false -- success = false
end end
if not file_exists(output_path) then if not file_exists(log_path) then
msg.error("Output file missing!", output_path) msg.error("Output file missing!", output_path)
success = false -- success = false
end end
end end
@ -614,31 +597,6 @@ function check_output(ret, output_path, is_mpv)
return success return success
end end
-- split cols x N atlas in BGRA format into many thumbnail files
function split_atlas(atlas_path, cols, thumbnail_size, output_name)
local atlas = io.open(atlas_path, "rb")
local atlas_filesize = atlas:seek("end")
local atlas_pictures = math.floor(atlas_filesize / (4 * thumbnail_size.w * thumbnail_size.h))
local stride = 4 * thumbnail_size.w * math.min(cols, atlas_pictures)
for pic = 0, atlas_pictures-1 do
local x_start = (pic % cols) * thumbnail_size.w
local y_start = math.floor(pic / cols) * thumbnail_size.h
local filename = output_name(pic)
if filename then
local thumb_file = io.open(filename, "wb")
for line = 0, thumbnail_size.h - 1 do
atlas:seek("set", 4 * x_start + (y_start + line) * stride)
local data = atlas:read(thumbnail_size.w * 4)
if data then
thumb_file:write(data)
end
end
thumb_file:close()
end
end
atlas:close()
end
function do_worker_job(state_json_string, frames_json_string) function do_worker_job(state_json_string, frames_json_string)
msg.debug("Handling given job") msg.debug("Handling given job")
local thumb_state, err = utils.parse_json(state_json_string) local thumb_state, err = utils.parse_json(state_json_string)
@ -665,8 +623,8 @@ function do_worker_job(state_json_string, frames_json_string)
local file_duration = mp.get_property_native("duration") local file_duration = mp.get_property_native("duration")
local file_path = thumb_state.worker_input_path local file_path = thumb_state.worker_input_path
if thumb_state.is_remote and not thumb_state.storyboard then if thumb_state.is_remote then
if (thumbnail_func == create_thumbnail_ffmpeg) then if thumbnail_func == create_thumbnail_ffmpeg then
msg.warn("Thumbnailing remote path, falling back on mpv.") msg.warn("Thumbnailing remote path, falling back on mpv.")
end end
thumbnail_func = create_thumbnail_mpv thumbnail_func = create_thumbnail_mpv
@ -690,7 +648,7 @@ function do_worker_job(state_json_string, frames_json_string)
-- Check if the thumbnail already exists and is the correct size -- Check if the thumbnail already exists and is the correct size
local thumbnail_file = io.open(thumbnail_path, "rb") local thumbnail_file = io.open(thumbnail_path, "rb")
if not thumbnail_file then if thumbnail_file == nil then
need_thumbnail_generation = true need_thumbnail_generation = true
else else
local existing_thumbnail_filesize = thumbnail_file:seek("end") local existing_thumbnail_filesize = thumbnail_file:seek("end")
@ -703,35 +661,16 @@ function do_worker_job(state_json_string, frames_json_string)
end end
if need_thumbnail_generation then if need_thumbnail_generation then
local success local ret = thumbnail_func(
if thumb_state.storyboard then file_path,
-- get atlas and then split it into thumbnails timestamp,
local rows = thumb_state.storyboard.rows thumb_state.thumbnail_size,
local cols = thumb_state.storyboard.cols thumbnail_path,
local div = thumb_state.storyboard.divisor thumb_state.worker_extra
local atlas_idx = math.floor(thumb_idx * div /(cols*rows)) )
local atlas_path = thumb_state.thumbnail_template:format(atlas_idx) .. ".atlas" local success = check_output(ret, thumbnail_path, thumbnail_func == create_thumbnail_mpv)
local url = thumb_state.storyboard.fragments[atlas_idx+1].url
if not url then
url = thumb_state.storyboard.fragment_base_url .. "/" .. thumb_state.storyboard.fragments[atlas_idx+1].path
end
local ret = thumbnail_func(url, 0, { w=thumb_state.storyboard.scale, h=thumb_state.storyboard.scale }, atlas_path, { relative_scale=true })
success = check_output(ret, atlas_path, thumbnail_func == create_thumbnail_mpv)
if success then
split_atlas(atlas_path, cols, thumb_state.thumbnail_size, function(idx)
if (atlas_idx * cols * rows + idx) % div ~= 0 then
return nil
end
return thumb_state.thumbnail_template:format(math.floor((atlas_idx * cols * rows + idx) / div))
end)
os.remove(atlas_path)
end
else
local ret = thumbnail_func(file_path, timestamp, thumb_state.thumbnail_size, thumbnail_path, thumb_state.worker_extra)
success = check_output(ret, thumbnail_path, thumbnail_func == create_thumbnail_mpv)
end
if not success then if success == nil then
-- Killed by us, changing files, ignore -- Killed by us, changing files, ignore
msg.debug("Changing files, subprocess killed") msg.debug("Changing files, subprocess killed")
return true return true
@ -749,7 +688,7 @@ function do_worker_job(state_json_string, frames_json_string)
thumbnail_file = io.open(thumbnail_path, "rb") thumbnail_file = io.open(thumbnail_path, "rb")
-- Bail if we can't read the file (it should really exist by now, we checked this in check_output!) -- Bail if we can't read the file (it should really exist by now, we checked this in check_output!)
if not thumbnail_file then if thumbnail_file == nil then
msg.error("Thumbnail suddenly disappeared!") msg.error("Thumbnail suddenly disappeared!")
return true return true
end end
@ -761,9 +700,14 @@ function do_worker_job(state_json_string, frames_json_string)
-- Check if the file is big enough -- Check if the file is big enough
local missing_bytes = math.max(0, thumbnail_raw_size - thumbnail_file_size) local missing_bytes = math.max(0, thumbnail_raw_size - thumbnail_file_size)
if missing_bytes > 0 then if missing_bytes > 0 then
msg.warn(("Thumbnail missing %d bytes (expected %d, had %d), padding %s"):format( msg.warn(
missing_bytes, thumbnail_raw_size, thumbnail_file_size, thumbnail_path ("Thumbnail missing %d bytes (expected %d, had %d), padding %s"):format(
)) missing_bytes,
thumbnail_raw_size,
thumbnail_file_size,
thumbnail_path
)
)
-- Pad the file if it's missing content (eg. ffmpeg seek to file end) -- Pad the file if it's missing content (eg. ffmpeg seek to file end)
thumbnail_file = io.open(thumbnail_path, "ab") thumbnail_file = io.open(thumbnail_path, "ab")
thumbnail_file:write(string.rep(string.char(0), missing_bytes)) thumbnail_file:write(string.rep(string.char(0), missing_bytes))
@ -774,17 +718,21 @@ function do_worker_job(state_json_string, frames_json_string)
mp.commandv("script-message", "mpv_thumbnail_script-ready", tostring(thumbnail_index), thumbnail_path) mp.commandv("script-message", "mpv_thumbnail_script-ready", tostring(thumbnail_index), thumbnail_path)
end end
msg.debug(("Generating %d thumbnails @ %dx%d for %q"):format( msg.debug(
("Generating %d thumbnails @ %dx%d for %q"):format(
#thumbnail_indexes, #thumbnail_indexes,
thumb_state.thumbnail_size.w, thumb_state.thumbnail_size.w,
thumb_state.thumbnail_size.h, thumb_state.thumbnail_size.h,
file_path)) file_path
)
)
for i, thumbnail_index in ipairs(thumbnail_indexes) do for i, thumbnail_index in ipairs(thumbnail_indexes) do
local bail = generate_thumbnail_for_index(thumbnail_index) local bail = generate_thumbnail_for_index(thumbnail_index)
if bail then return end if bail then
return
end
end end
end end
-- Set up listeners and keybinds -- Set up listeners and keybinds
@ -792,7 +740,6 @@ end
-- Job listener -- Job listener
mp.register_script_message("mpv_thumbnail_script-job", do_worker_job) mp.register_script_message("mpv_thumbnail_script-job", do_worker_job)
-- Register this worker with the master script -- Register this worker with the master script
local register_timer = nil local register_timer = nil
local register_timeout = mp.get_time() + 1.5 local register_timeout = mp.get_time() + 1.5