add yt-dlp preload submodule
This commit is contained in:
parent
3c564c26b5
commit
65b60a75ea
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -11,3 +11,6 @@
|
|||||||
[submodule "ModernZ"]
|
[submodule "ModernZ"]
|
||||||
path = ModernZ
|
path = ModernZ
|
||||||
url = git@github.com:Samillion/ModernZ.git
|
url = git@github.com:Samillion/ModernZ.git
|
||||||
|
[submodule "ytdl-preload"]
|
||||||
|
path = ytdl-preload
|
||||||
|
url = git@gist.github.com:17d90e3deeb35b5f75e55adb19098f58.git
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 725ef8db36666dc10c7f9ab0870c761bc34e2741
|
Subproject commit 757804b1921833c868dc28e72b35ccea6cbb764e
|
54
mpv.conf
54
mpv.conf
@ -106,12 +106,12 @@ user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Geck
|
|||||||
cache=yes
|
cache=yes
|
||||||
#
|
#
|
||||||
# Use extra large RAM cache (needs cache=yes to make it useful).
|
# Use extra large RAM cache (needs cache=yes to make it useful).
|
||||||
#demuxer-max-bytes=500M
|
demuxer-max-bytes=500M
|
||||||
#demuxer-max-back-bytes=100M
|
demuxer-max-back-bytes=100M
|
||||||
#
|
#
|
||||||
# Disable the behavior that the player will pause if the cache goes below a
|
# Disable the behavior that the player will pause if the cache goes below a
|
||||||
# certain fill size.
|
# certain fill size.
|
||||||
#cache-pause=no
|
cache-pause=no
|
||||||
#
|
#
|
||||||
# Store cache payload on the hard disk instead of in RAM. (This may negatively
|
# Store cache payload on the hard disk instead of in RAM. (This may negatively
|
||||||
# impact performance unless used for slow input such as network.)
|
# impact performance unless used for slow input such as network.)
|
||||||
@ -144,37 +144,69 @@ cache=yes
|
|||||||
#[eye-cancer]
|
#[eye-cancer]
|
||||||
#sharpen=5
|
#sharpen=5
|
||||||
|
|
||||||
profile=svp
|
|
||||||
sub-font=JetBrainsMono Nerd Font
|
sub-font=JetBrainsMono Nerd Font
|
||||||
sub-font-size=50
|
sub-font-size=50
|
||||||
osd-font=JetBrainsMono Nerd Font
|
osd-font=JetBrainsMono Nerd Font
|
||||||
|
border=no
|
||||||
|
|
||||||
geometry=50%
|
geometry=50%
|
||||||
|
|
||||||
volume=50
|
volume=50
|
||||||
# speed-step=0.05
|
# speed-step=0.05
|
||||||
audio-spdif=ac3,eac3,dts-hd,truehd
|
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.
|
# Can fix stuttering in some cases, in other cases probably causes it. Try it if you experience stuttering.
|
||||||
opengl-early-flush=no
|
opengl-early-flush=no
|
||||||
|
|
||||||
|
video-sync=display-resample
|
||||||
osc=no
|
osc=no
|
||||||
|
|
||||||
interpolation
|
|
||||||
tscale=oversample
|
|
||||||
# hwdec=auto-copy
|
|
||||||
hwdec=auto
|
|
||||||
ytdl-raw-options=ignore-config=,sub-lang=en,write-auto-sub=
|
ytdl-raw-options=ignore-config=,sub-lang=en,write-auto-sub=
|
||||||
ytdl-format=bestvideo+bestaudio/best
|
ytdl-format=bestvideo+bestaudio/best
|
||||||
|
|
||||||
# get subtitles for videos automatically
|
# get subtitles for videos automatically
|
||||||
# sub-auto=fuzzy
|
# sub-auto=fuzzy
|
||||||
slang=en
|
slang=en,eng
|
||||||
# disable subtitles by default = no
|
# disable subtitles by default = no
|
||||||
sid=no
|
sid=no
|
||||||
# keep-open
|
# keep-open
|
||||||
input-ipc-server=/tmp/mpvsocket
|
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]
|
[svp]
|
||||||
input-ipc-server=/tmp/mpvsocket # Receives input from SVP
|
input-ipc-server=/tmp/mpvsocket # Receives input from SVP
|
||||||
@ -186,4 +218,4 @@ profile-cond=p["idle-active"]
|
|||||||
profile-restore=copy-equal
|
profile-restore=copy-equal
|
||||||
title=' '
|
title=' '
|
||||||
keepaspect=no
|
keepaspect=no
|
||||||
background=1
|
# background=1
|
||||||
|
@ -17,7 +17,7 @@ save_full_queue=ctrl+S
|
|||||||
remove_from_queue=ctrl+x
|
remove_from_queue=ctrl+x
|
||||||
play_selected_video=ctrl+ENTER
|
play_selected_video=ctrl+ENTER
|
||||||
browser=firefox
|
browser=firefox
|
||||||
clipboard_command=xclip -o
|
clipboard_command=wl-paste -p
|
||||||
cursor_icon=➤
|
cursor_icon=➤
|
||||||
display_limit=10
|
display_limit=10
|
||||||
download_directory=~/videos/YouTube
|
download_directory=~/videos/YouTube
|
||||||
|
@ -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)
|
|
1
scripts/ytdl-preload.lua
Symbolic link
1
scripts/ytdl-preload.lua
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
ytdl-preload/ytdl-preload.lua
|
1
ytdl-preload
Submodule
1
ytdl-preload
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 39759ecdc3a0855c8afac1dce028e499bfa4d9c1
|
Loading…
x
Reference in New Issue
Block a user