diff --git a/input.conf b/input.conf new file mode 100644 index 0000000..dab521d --- /dev/null +++ b/input.conf @@ -0,0 +1 @@ +D ab-loop-dump-cache "/tmp/clip.ts" # Dump AB loop diff --git a/scripts/youtube-quality.lua b/scripts/youtube-quality.lua deleted file mode 100644 index b587f37..0000000 --- a/scripts/youtube-quality.lua +++ /dev/null @@ -1,275 +0,0 @@ --- youtube-quality.lua --- --- Change youtube video quality on the fly. --- --- Diplays a menu that lets you switch to different ytdl-format settings while --- you're in the middle of a video (just like you were using the web player). --- --- Bound to ctrl-f by default. - -local mp = require 'mp' -local utils = require 'mp.utils' -local msg = require 'mp.msg' -local assdraw = require 'mp.assdraw' - -local opts = { - --key bindings - toggle_menu_binding = "ctrl+f", - up_binding = "UP", - down_binding = "DOWN", - select_binding = "ENTER", - - --formatting / cursors - selected_and_active = "▶ - ", - selected_and_inactive = "● - ", - unselected_and_active = "▷ - ", - unselected_and_inactive = "○ - ", - - --font size scales by window, if false requires larger font and padding sizes - scale_playlist_by_window=false, - - --playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua - --example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1 - --read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags - --undeclared tags will use default osd settings - --these styles will be used for the whole playlist. More specific styling will need to be hacked in - -- - --(a monospaced font is recommended but not required) - style_ass_tags = "{\\fnmonospace}", - - --paddings for top left corner - text_padding_x = 5, - text_padding_y = 5, - - --other - menu_timeout = 10, - - --use youtube-dl to fetch a list of available formats (overrides quality_strings) - fetch_formats = true, - - --default menu entries - quality_strings=[[ - [ - {"4320p" : "bestvideo[height<=?4320p]+bestaudio/best"}, - {"2160p" : "bestvideo[height<=?2160]+bestaudio/best"}, - {"1440p" : "bestvideo[height<=?1440]+bestaudio/best"}, - {"1080p" : "bestvideo[height<=?1080]+bestaudio/best"}, - {"720p" : "bestvideo[height<=?720]+bestaudio/best"}, - {"480p" : "bestvideo[height<=?480]+bestaudio/best"}, - {"360p" : "bestvideo[height<=?360]+bestaudio/best"}, - {"240p" : "bestvideo[height<=?240]+bestaudio/best"}, - {"144p" : "bestvideo[height<=?144]+bestaudio/best"} - ] - ]], -} -(require 'mp.options').read_options(opts, "youtube-quality") -opts.quality_strings = utils.parse_json(opts.quality_strings) - -local destroyer = nil - - -function show_menu() - local selected = 1 - local active = 0 - local current_ytdl_format = mp.get_property("ytdl-format") - msg.verbose("current ytdl-format: "..current_ytdl_format) - local num_options = 0 - local options = {} - - - if opts.fetch_formats then - options, num_options = download_formats() - end - - if next(options) == nil then - for i,v in ipairs(opts.quality_strings) do - num_options = num_options + 1 - for k,v2 in pairs(v) do - options[i] = {label = k, format=v2} - if v2 == current_ytdl_format then - active = i - selected = active - end - end - end - end - - --set the cursor to the currently format - for i,v in ipairs(options) do - if v.format == current_ytdl_format then - active = i - selected = active - break - end - end - - function selected_move(amt) - selected = selected + amt - if selected < 1 then selected = num_options - elseif selected > num_options then selected = 1 end - timeout:kill() - timeout:resume() - draw_menu() - end - function choose_prefix(i) - if i == selected and i == active then return opts.selected_and_active - elseif i == selected then return opts.selected_and_inactive end - - if i ~= selected and i == active then return opts.unselected_and_active - elseif i ~= selected then return opts.unselected_and_inactive end - return "> " --shouldn't get here. - end - - function draw_menu() - local ass = assdraw.ass_new() - - ass:pos(opts.text_padding_x, opts.text_padding_y) - ass:append(opts.style_ass_tags) - - for i,v in ipairs(options) do - ass:append(choose_prefix(i)..v.label.."\\N") - end - - local w, h = mp.get_osd_size() - if opts.scale_playlist_by_window then w,h = 0, 0 end - mp.set_osd_ass(w, h, ass.text) - end - - function destroy() - timeout:kill() - mp.set_osd_ass(0,0,"") - mp.remove_key_binding("move_up") - mp.remove_key_binding("move_down") - mp.remove_key_binding("select") - mp.remove_key_binding("escape") - destroyer = nil - end - timeout = mp.add_periodic_timer(opts.menu_timeout, destroy) - destroyer = destroy - - mp.add_forced_key_binding(opts.up_binding, "move_up", function() selected_move(-1) end, {repeatable=true}) - mp.add_forced_key_binding(opts.down_binding, "move_down", function() selected_move(1) end, {repeatable=true}) - mp.add_forced_key_binding(opts.select_binding, "select", function() - destroy() - mp.set_property("ytdl-format", options[selected].format) - reload_resume() - end) - mp.add_forced_key_binding(opts.toggle_menu_binding, "escape", destroy) - - draw_menu() - return -end - -local ytdl = { - path = "youtube-dl", - searched = false, - blacklisted = {} -} - -format_cache={} -function download_formats() - local function exec(args) - local ret = utils.subprocess({args = args}) - return ret.status, ret.stdout, ret - end - - local function table_size(t) - s = 0 - for i,v in ipairs(t) do - s = s+1 - end - return s - end - - local url = mp.get_property("path") - - url = string.gsub(url, "ytdl://", "") -- Strip possible ytdl:// prefix. - - -- don't fetch the format list if we already have it - if format_cache[url] ~= nil then - local res = format_cache[url] - return res, table_size(res) - end - mp.osd_message("fetching available formats with youtube-dl...", 60) - - if not (ytdl.searched) then - local ytdl_mcd = mp.find_config_file("youtube-dl") - if not (ytdl_mcd == nil) then - msg.verbose("found youtube-dl at: " .. ytdl_mcd) - ytdl.path = ytdl_mcd - end - ytdl.searched = true - end - - local command = {ytdl.path, "--no-warnings", "--no-playlist", "-J"} - table.insert(command, url) - local es, json, result = exec(command) - - if (es < 0) or (json == nil) or (json == "") then - mp.osd_message("fetching formats failed...", 1) - msg.error("failed to get format list: " .. err) - return {}, 0 - end - - local json, err = utils.parse_json(json) - - if (json == nil) then - mp.osd_message("fetching formats failed...", 1) - msg.error("failed to parse JSON data: " .. err) - return {}, 0 - end - - res = {} - msg.verbose("youtube-dl succeeded!") - for i,v in ipairs(json.formats) do - if v.vcodec ~= "none" then - local fps = v.fps and v.fps.."fps" or "" - local resolution = string.format("%sx%s", v.width, v.height) - local l = string.format("%-9s %-5s (%-4s / %s)", resolution, fps, v.ext, v.vcodec) - local f = string.format("%s+bestaudio/best", v.format_id) - table.insert(res, {label=l, format=f, width=v.width }) - end - end - - table.sort(res, function(a, b) return a.width > b.width end) - - mp.osd_message("", 0) - format_cache[url] = res - return res, table_size(res) -end - - --- register script message to show menu -mp.register_script_message("toggle-quality-menu", -function() - if destroyer ~= nil then - destroyer() - else - show_menu() - end -end) - --- keybind to launch menu -mp.add_key_binding(opts.toggle_menu_binding, "quality-menu", show_menu) - --- special thanks to reload.lua (https://github.com/4e6/mpv-reload/) -function reload_resume() - local playlist_pos = mp.get_property_number("playlist-pos") - local reload_duration = mp.get_property_native("duration") - local time_pos = mp.get_property("time-pos") - - mp.set_property_number("playlist-pos", playlist_pos) - - -- Tries to determine live stream vs. pre-recordered VOD. VOD has non-zero - -- duration property. When reloading VOD, to keep the current time position - -- we should provide offset from the start. Stream doesn't have fixed start. - -- Decent choice would be to reload stream from it's current 'live' positon. - -- That's the reason we don't pass the offset when reloading streams. - if reload_duration and reload_duration > 0 then - local function seeker() - mp.commandv("seek", time_pos, "absolute") - mp.unregister_event(seeker) - end - mp.register_event("file-loaded", seeker) - end -end