Skip to content

Instantly share code, notes, and snippets.

@po5
Last active September 5, 2025 04:42
Show Gist options
  • Select an option

  • Save po5/2415cb39c94760ac8c2c7666a30bf02c to your computer and use it in GitHub Desktop.

Select an option

Save po5/2415cb39c94760ac8c2c7666a30bf02c to your computer and use it in GitHub Desktop.
-- autoload-archive-hook.lua
--
-- When playing a direct file from within an archive with e.g. 'archive://test.rar|/09.png', mpv doesn't fill the playlist.
-- This script does so transparently. It also supports nested and remote archives.
-- Path resolving adapted from https://github.com/po5/memo
mp.utils = require "mp.utils"
local data_protocols = {
edl = true,
data = true,
null = true,
memory = true,
hex = true,
fd = true,
fdclose = true,
mf = true
}
local stacked_protocols = {
ffmpeg = true,
lavf = true,
appending = true,
file = true,
archive = true,
slice = true
}
local device_protocols = {
bd = true,
br = true,
bluray = true,
cdda = true,
dvb = true,
dvd = true,
dvdnav = true
}
function path_info(full_path)
local function resolve(effective_path, save_path, display_path, last_protocol, achive_count)
local protocol_start, protocol_end, protocol = display_path:find("^(%a[%w.+-]-)://")
if protocol == "ytdl" then
elseif protocol and not stacked_protocols[protocol] then
local input_path, file_options
if device_protocols[protocol] then
display_path = display_path:sub(protocol_end + 1)
end
return display_path, save_path, effective_path, protocol, achive_count, file_options
end
if not protocol_end then
return display_path, save_path, effective_path, last_protocol, achive_count, nil
end
display_path = display_path:sub(protocol_end + 1)
if protocol == "archive" then
achive_count = achive_count + 1
local main_path, archive_path, filename = display_path:gsub("%%7C", "|"):match("(.-)(|.-[\\/])(.+)")
if not main_path then
local main_path = display_path:match("(.-)|")
effective_path = main_path or display_path
_, save_path, effective_path, protocol, achive_count, file_options = resolve(effective_path, save_path, display_path, protocol, achive_count)
effective_path = effective_path
save_path = "archive://" .. (save_path or effective_path)
if main_path then
save_path = save_path .. display_path:match("|(.-)")
end
else
display_path, save_path, _, protocol, achive_count, file_options = resolve(main_path, save_path, main_path, protocol, achive_count)
effective_path = display_path
save_path = save_path or effective_path
save_path = "archive://" .. save_path .. (save_path:find("archive://") and archive_path:gsub("|", "%%7C") or archive_path) .. filename
_, main_path = mp.utils.split_path(main_path)
_, filename = mp.utils.split_path(filename)
display_path = main_path .. ": " .. filename
end
elseif protocol == "slice" then
if effective_path then
effective_path = effective_path:match(".-@(.*)") or effective_path
end
display_path = display_path:match(".-@(.*)") or display_path
end
return resolve(effective_path, save_path, display_path, protocol, achive_count)
end
local display_path, save_path, effective_path, effective_protocol, achive_count, file_options = resolve(nil, nil, full_path, nil, 0)
effective_path = effective_path or display_path
save_path = save_path or effective_path
return display_path, save_path, effective_path, effective_protocol, achive_count, file_options
end
local target_entry = nil
mp.add_hook("on_load", 50, function ()
local url = mp.get_property("stream-open-filename", "")
local display_path, save_path, effective_path, effective_protocol, achive_count, file_options = path_info(url)
if achive_count > 0 and achive_count < 3 then
local playlist_count = mp.get_property_native("playlist-count", 1)
if target_entry and playlist_count > 1 then
local playlist = mp.get_property_native("playlist", {})
for i = 1, #playlist do
local playlist_file = playlist[i].filename
if playlist_file == target_entry then
target_entry = nil
mp.set_property_native("playlist-pos-1", i)
return
end
end
target_entry = nil
elseif playlist_count == 1 and not target_entry then
target_entry = save_path
mp.set_property("stream-open-filename", effective_path)
end
else
target_entry = nil
end
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment