From 65b60a75eaecc7195d642a834325fd7664056ae3 Mon Sep 17 00:00:00 2001 From: sudacode Date: Sat, 15 Feb 2025 13:50:30 -0800 Subject: [PATCH] add yt-dlp preload submodule --- .gitmodules | 3 + mpv-youtube-queue | 2 +- mpv.conf | 54 +++++-- script-opts/mpv-youtube-queue.conf | 2 +- scripts/ytdl-preload.lua | 238 +---------------------------- ytdl-preload | 1 + 6 files changed, 50 insertions(+), 250 deletions(-) mode change 100644 => 120000 scripts/ytdl-preload.lua create mode 160000 ytdl-preload diff --git a/.gitmodules b/.gitmodules index 9b558c0..1e1b6b0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,3 +11,6 @@ [submodule "ModernZ"] path = ModernZ url = git@github.com:Samillion/ModernZ.git +[submodule "ytdl-preload"] + path = ytdl-preload + url = git@gist.github.com:17d90e3deeb35b5f75e55adb19098f58.git diff --git a/mpv-youtube-queue b/mpv-youtube-queue index 725ef8d..757804b 160000 --- a/mpv-youtube-queue +++ b/mpv-youtube-queue @@ -1 +1 @@ -Subproject commit 725ef8db36666dc10c7f9ab0870c761bc34e2741 +Subproject commit 757804b1921833c868dc28e72b35ccea6cbb764e diff --git a/mpv.conf b/mpv.conf index 885797b..4f98803 100644 --- a/mpv.conf +++ b/mpv.conf @@ -106,12 +106,12 @@ user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Geck cache=yes # # Use extra large RAM cache (needs cache=yes to make it useful). -#demuxer-max-bytes=500M -#demuxer-max-back-bytes=100M +demuxer-max-bytes=500M +demuxer-max-back-bytes=100M # # Disable the behavior that the player will pause if the cache goes below a # certain fill size. -#cache-pause=no +cache-pause=no # # Store cache payload on the hard disk instead of in RAM. (This may negatively # impact performance unless used for slow input such as network.) @@ -144,37 +144,69 @@ cache=yes #[eye-cancer] #sharpen=5 -profile=svp sub-font=JetBrainsMono Nerd Font sub-font-size=50 osd-font=JetBrainsMono Nerd Font +border=no geometry=50% volume=50 # speed-step=0.05 audio-spdif=ac3,eac3,dts-hd,truehd -glsl-shaders="~~/shaders/Anime4K_Clamp_Highlights.glsl:~~/shaders/Anime4K_Restore_CNN_VL.glsl:~~/shaders/Anime4K_Upscale_CNN_x2_VL.glsl:~~/shaders/Anime4K_AutoDownscalePre_x2.glsl:~~/shaders/Anime4K_AutoDownscalePre_x4.glsl:~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl" +# glsl-shaders="~~/shaders/Anime4K_Clamp_Highlights.glsl:~~/shaders/Anime4K_Restore_CNN_VL.glsl:~~/shaders/Anime4K_Upscale_CNN_x2_VL.glsl:~~/shaders/Anime4K_AutoDownscalePre_x2.glsl:~~/shaders/Anime4K_AutoDownscalePre_x4.glsl:~~/shaders/Anime4K_Upscale_CNN_x2_M.glsl" +# glsl-shaders="~~/shaders/FSR.glsl:~~/shaders/NVScaler.glsl:~~/shaders/CAS-scaled.glsl" +glsl-shaders="~~/shaders/FSR.glsl" # Can fix stuttering in some cases, in other cases probably causes it. Try it if you experience stuttering. opengl-early-flush=no +video-sync=display-resample osc=no -interpolation -tscale=oversample -# hwdec=auto-copy -hwdec=auto ytdl-raw-options=ignore-config=,sub-lang=en,write-auto-sub= ytdl-format=bestvideo+bestaudio/best # get subtitles for videos automatically # sub-auto=fuzzy -slang=en +slang=en,eng # disable subtitles by default = no sid=no # keep-open input-ipc-server=/tmp/mpvsocket +vo=gpu-next +profile=fast +# GPU OPTIONS +# hwdec=auto-safe +scale=bicubic +dscale=bicubic +cscale=bicubic +interpolation=yes +tscale=oversample +interpolation-preserve=no + +# CATPPUCCIN MACHIATTO +# Main mpv options +background-color='#24273a' +osd-back-color='#181926' +osd-border-color='#181926' +osd-color='#cad3f5' +osd-shadow-color='#24273a' + +# Stats script options +# Options are on separate lines for clarity +# Colors are in #BBGGRR format +script-opts-append=stats-border_color=30201e +script-opts-append=stats-font_color=f5d3ca +script-opts-append=stats-plot_bg_border_color=f8bdb7 +script-opts-append=stats-plot_bg_color=30201e +script-opts-append=stats-plot_color=f8bdb7 + +# External script options +# It is fine to leave these here even if one does not use these scripts because they are just ignored unless a script uses them + +# UOSC options +script-opts-append=uosc-color=foreground=b7bdf8,foreground_text=363a4f,background=24273a,background_text=cad3f5,curtain=1e2030,success=a6da95,error=ed8796 [svp] input-ipc-server=/tmp/mpvsocket # Receives input from SVP @@ -186,4 +218,4 @@ profile-cond=p["idle-active"] profile-restore=copy-equal title=' ' keepaspect=no -background=1 +# background=1 diff --git a/script-opts/mpv-youtube-queue.conf b/script-opts/mpv-youtube-queue.conf index 14f3305..2913e8a 100644 --- a/script-opts/mpv-youtube-queue.conf +++ b/script-opts/mpv-youtube-queue.conf @@ -17,7 +17,7 @@ save_full_queue=ctrl+S remove_from_queue=ctrl+x play_selected_video=ctrl+ENTER browser=firefox -clipboard_command=xclip -o +clipboard_command=wl-paste -p cursor_icon=➤ display_limit=10 download_directory=~/videos/YouTube diff --git a/scripts/ytdl-preload.lua b/scripts/ytdl-preload.lua deleted file mode 100644 index 4c43303..0000000 --- a/scripts/ytdl-preload.lua +++ /dev/null @@ -1,237 +0,0 @@ -local cachePath = "/tmp/ytdl-preload" -local nextIndex -local caught = true -local pop = false -local ytdl = "yt-dlp" -local utils = require 'mp.utils' - -local chapter_list = {} -local json = "" -local function exists(file) - local ok, err, code = os.rename(file, file) - if not ok then - if code == 13 then -- Permission denied, but it exists - return true - end - end - return ok, err -end --- from ytdl_hook -local function time_to_secs(time_string) - local ret - local a, b, c = time_string:match("(%d+):(%d%d?):(%d%d)") - if a ~= nil then - ret = (a * 3600 + b * 60 + c) - else - a, b = time_string:match("(%d%d?):(%d%d)") - if a ~= nil then ret = (a * 60 + b) end - end - return ret -end -local function extract_chapters(data, video_length) - local ret = {} - for line in data:gmatch("[^\r\n]+") do - local time = time_to_secs(line) - if time and (time < video_length) then - table.insert(ret, { time = time, title = line }) - end - end - table.sort(ret, function(a, b) return a.time < b.time end) - return ret -end -local function chapters() - if json.chapters then - for i = 1, #json.chapters do - local chapter = json.chapters[i] - local title = chapter.title or "" - if title == "" then - title = string.format('Chapter %02d', i) - end - table.insert(chapter_list, - { time = chapter.start_time, title = title }) - end - elseif not (json.description == nil) and not (json.duration == nil) then - chapter_list = extract_chapters(json.description, json.duration) - end -end --- end ytdl_hook -local title = "" -local function listener(event) - if not caught and event.prefix == mp.get_script_name() then - local destination = string.match(event.text, - "%[download%] Destination: (.+).mkv") or - string.match(event.text, - "%[download%] (.+).mkv has already been downloaded") - if destination and - string.find(destination, string.gsub(cachePath, '~/', '')) then - _, title = utils.split_path(destination) - local audio = "" - if exists(destination .. ".mka") then - audio = "audio-file=" .. destination .. '.mka,' - end - mp.commandv("loadfile", destination .. ".mkv", "append", - audio .. 'force-media-title="' .. - title:gsub("-" .. ("[%w_-]"):rep(11) .. "$", "") .. - '",demuxer-max-back-bytes=1MiB,demuxer-max-bytes=3MiB,ytdl=no') -- ,sub-file="..destination..".en.vtt") --in case they are not set up to autoload - mp.commandv("playlist_move", mp.get_property("playlist-count") - 1, - nextIndex) - mp.commandv("playlist_remove", nextIndex + 1) - mp.unregister_event(listener) - caught = true - title = "" - pop = true - end - end -end --- from ytdl_hook -mp.add_hook("on_preloaded", 10, function() - if string.find(mp.get_property("path"), cachePath) then - chapters() - if next(chapter_list) ~= nil then - mp.set_property_native("chapter-list", chapter_list) - chapter_list = {} - json = "" - end - end -end) --- end ytdl_hook -local function DL() - -- mp.add_timeout(1, function() - if tonumber(mp.get_property("playlist-pos-1")) > 0 and - mp.get_property("playlist-pos-1") ~= mp.get_property("playlist-count") then - nextIndex = tonumber(mp.get_property("playlist-pos")) + 1 - local nextFile = mp.get_property( - "playlist/" .. tostring(nextIndex) .. "/filename") - if nextFile and caught and nextFile:find("://", 0, false) then - caught = false - mp.enable_messages("info") - mp.register_event("log-message", listener) - local ytFormat = mp.get_property("ytdl-format") - local fVideo = string.match(ytFormat, '(.+)%+.+//?') or 'bestvideo' - local fAudio = string.match(ytFormat, '.+%+(.+)//?') or 'bestaudio' - - json = mp.command_native({ - name = "subprocess", - args = { ytdl, "--dump-single-json", nextFile }, - capture_stdout = true, - capture_stderr = true - }) - if json then - json = json.stdout - if json:find("audio only") then - mp.command_native_async({ - name = "subprocess", - args = { - ytdl, "-q", "-f", fAudio, "--restrict-filenames", - "--no-playlist", "--sub-lang", "en", "--write-sub", - "--no-part", "-o", - cachePath .. "/%(title)s-%(id)s.mka", nextFile - }, - playback_only = false - }, function() end) - else - if fVideo:find("bestvideo") then - fVideo = fVideo:gsub("bestvideo", "best") - end - end - json = utils.parse_json(json) - end - mp.command_native_async({ - name = "subprocess", - -- args = {ytdl, "-f", fVideo..'/best', "--restrict-filenames", "--no-part", "-N","2","-o", cachePath.."/%(title)s-%(id)s.mkv", nextFile}, - args = { - ytdl, "-f", fVideo .. '/best', "--restrict-filenames", - "--no-playlist", "--no-part", "-o", - cachePath .. "/%(title)s-%(id)s.mkv", nextFile - }, - playback_only = false - }, function() end) - end - end - -- end) -end - -local function clearCache() - if pop == true then - if package.config:sub(1, 1) ~= '/' then - os.execute('rd /s/q "' .. cachePath .. '"') - else - os.execute('rm -rd ' .. cachePath) - end - print('clear') - mp.command("quit") - end -end - -local skipInitial -mp.observe_property("playlist-count", "number", function() - if skipInitial then - DL() - else - skipInitial = true - end -end) - --- from ytdl_hook -local platform_is_windows = (package.config:sub(1, 1) == "\\") -local o = { - exclude = "", - try_ytdl_first = false, - use_manifests = false, - all_formats = false, - force_all_formats = true, - ytdl_path = "" -} -local paths_to_search = { "yt-dlp", "yt-dlp_x86", "youtube-dl" } -local options = require 'mp.options' -options.read_options(o, "ytdl_hook") - -local separator = platform_is_windows and ";" or ":" -if o.ytdl_path:match("[^" .. separator .. "]") then - paths_to_search = {} - for path in o.ytdl_path:gmatch("[^" .. separator .. "]+") do - table.insert(paths_to_search, path) - end -end - -local function exec(args) - local ret = mp.command_native({ - name = "subprocess", - args = args, - capture_stdout = true, - capture_stderr = true - }) - return ret.status, ret.stdout, ret, ret.killed_by_us -end - -local msg = require 'mp.msg' -local command = {} -for _, path in pairs(paths_to_search) do - -- search for youtube-dl in mpv's config dir - local exesuf = platform_is_windows and ".exe" or "" - local ytdl_cmd = mp.find_config_file(path .. exesuf) - if ytdl_cmd then - msg.verbose("Found youtube-dl at: " .. ytdl_cmd) - ytdl = ytdl_cmd - break - else - msg.verbose("No youtube-dl found with path " .. path .. exesuf .. - " in config directories") - -- search in PATH - command[1] = path - es, json, result, aborted = exec(command) - if result.error_string == "init" then - msg.verbose("youtube-dl with path " .. path .. exesuf .. - " not found in PATH or not enough permissions") - else - msg.verbose("Found youtube-dl with path " .. path .. exesuf .. - " in PATH") - ytdl = path - break - end - end -end --- end ytdl_hook - -mp.register_event("start-file", DL) -mp.register_event("shutdown", clearCache) diff --git a/scripts/ytdl-preload.lua b/scripts/ytdl-preload.lua new file mode 120000 index 0000000..1e56b4d --- /dev/null +++ b/scripts/ytdl-preload.lua @@ -0,0 +1 @@ +ytdl-preload/ytdl-preload.lua \ No newline at end of file diff --git a/ytdl-preload b/ytdl-preload new file mode 160000 index 0000000..39759ec --- /dev/null +++ b/ytdl-preload @@ -0,0 +1 @@ +Subproject commit 39759ecdc3a0855c8afac1dce028e499bfa4d9c1