Last active
September 5, 2025 04:42
-
-
Save po5/2415cb39c94760ac8c2c7666a30bf02c to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| -- 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