remove torrserver support
This commit is contained in:
@@ -16,4 +16,3 @@
|
|||||||
| ---------- | ------------------------------------- | ---------------------------------------------- |
|
| ---------- | ------------------------------------- | ---------------------------------------------- |
|
||||||
| alass | 字幕自动同步(autosubsync 脚本) | `paru -S alass` |
|
| alass | 字幕自动同步(autosubsync 脚本) | `paru -S alass` |
|
||||||
| ffsubsync | 字幕自动同步(alass 的替代) | `pip install ffsubsync` |
|
| ffsubsync | 字幕自动同步(alass 的替代) | `pip install ffsubsync` |
|
||||||
| TorrServer | 种子流媒体播放(mpv-torrserver 脚本) | [GitHub](https://github.com/YouROK/TorrServer) |
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ icc/ # ICC 色彩配置文件
|
|||||||
- **字幕**:自动加载、编码检测(GB18030)、在线搜索(assrt)、自动同步(autosubsync)
|
- **字幕**:自动加载、编码检测(GB18030)、在线搜索(assrt)、自动同步(autosubsync)
|
||||||
- **音频**:96kHz 重采样、独占模式、多声道自动下混调节、ReplayGain
|
- **音频**:96kHz 重采样、独占模式、多声道自动下混调节、ReplayGain
|
||||||
- **播放管理**:历史记录(simplehistory)、进度保存、文件浏览器、播放列表管理
|
- **播放管理**:历史记录(simplehistory)、进度保存、文件浏览器、播放列表管理
|
||||||
- **网络**:yt-dlp 集成、浏览器 Cookie、自动缓存优化、TorrServer 支持
|
- **网络**:yt-dlp 集成、浏览器 Cookie、自动缓存优化
|
||||||
- **更新**:按 M 键通过 manager.lua 从 git 自动更新所有脚本和着色器
|
- **更新**:按 M 键通过 manager.lua 从 git 自动更新所有脚本和着色器
|
||||||
|
|
||||||
## 着色器方案
|
## 着色器方案
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ CTRL+l script-message-to simplehistory history-resume
|
|||||||
CTRL+c set clipboard/text ${path};show-text "已复制文件路径" #menu: 打开 > 复制 > 复制文件路径
|
CTRL+c set clipboard/text ${path};show-text "已复制文件路径" #menu: 打开 > 复制 > 复制文件路径
|
||||||
CTRL+ALT+c set clipboard/text ${filename};show-text "已复制文件名" #menu: 打开 > 复制 > 复制文件名
|
CTRL+ALT+c set clipboard/text ${filename};show-text "已复制文件名" #menu: 打开 > 复制 > 复制文件名
|
||||||
# ignore #menu: 打开 > ---
|
# ignore #menu: 打开 > ---
|
||||||
# script-message-to webtorrent toggle-info;show-text '' #menu: 打开 > Youtube-dl > 开/关 磁链 OSD
|
|
||||||
CTRL+F script-message-to quality_menu video_formats_toggle #menu: 打开 > Youtube-dl > 开/关 ytdl 视频选择菜单
|
CTRL+F script-message-to quality_menu video_formats_toggle #menu: 打开 > Youtube-dl > 开/关 ytdl 视频选择菜单
|
||||||
ALT+F script-message-to quality_menu audio_formats_toggle #menu: 打开 > Youtube-dl > 开/关 ytdl 音频选择菜单
|
ALT+F script-message-to quality_menu audio_formats_toggle #menu: 打开 > Youtube-dl > 开/关 ytdl 音频选择菜单
|
||||||
# script-message-to quality_menu reload #menu: 打开 > Youtube-dl > ytdl 重新加载
|
# script-message-to quality_menu reload #menu: 打开 > Youtube-dl > ytdl 重新加载
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
##指定 TorrServer HTTP 地址,示例为默认值
|
|
||||||
server=http://localhost:8090
|
|
||||||
##指定是否启用 TorrServer 初始化。默认值:no
|
|
||||||
#! 仅当 TorrServer 位于同一台设备上且未设置自启动时,才需要启用此选项
|
|
||||||
torrserver_init=no
|
|
||||||
##指定 TorrServer 路径,示例为默认值。可以为相对路径(已设置环境变量)或绝对路径
|
|
||||||
##需自行安装 TorrServer,详见:https://github.com/YouROK/TorrServer
|
|
||||||
#! 仅当 torrserver_init=yes 时,才需要设置此选项
|
|
||||||
torrserver_path=TorrServer
|
|
||||||
##指定是否查找可能的外部轨道(音轨、字幕)。默认值:yes
|
|
||||||
search_for_external_tracks=yes
|
|
||||||
@@ -1,224 +0,0 @@
|
|||||||
-- Install [Torrserver](https://github.com/YouROK/TorrServer)
|
|
||||||
-- then add "script-opts-append=mpv_torrserver-server=http://[TorrServer ip]:[port]" to mpv.conf
|
|
||||||
local utils = require 'mp.utils'
|
|
||||||
|
|
||||||
local opts = {
|
|
||||||
server = "http://localhost:8090",
|
|
||||||
torrserver_init = false,
|
|
||||||
torrserver_path = "TorrServer",
|
|
||||||
search_for_external_tracks = true
|
|
||||||
}
|
|
||||||
|
|
||||||
(require 'mp.options').read_options(opts)
|
|
||||||
local luacurl_available, cURL = pcall(require, 'cURL')
|
|
||||||
|
|
||||||
local is_windows = package.config:sub(1, 1) == "\\" -- detect path separator, windows uses backslashes
|
|
||||||
|
|
||||||
local function find_executable(name)
|
|
||||||
local os_path = os.getenv("PATH") or ""
|
|
||||||
local fallback_path = utils.join_path("/usr/bin", name)
|
|
||||||
local exec_path
|
|
||||||
for path in os_path:gmatch("[^:]+") do
|
|
||||||
exec_path = utils.join_path(path, name)
|
|
||||||
local meta, meta_error = utils.file_info(exec_path)
|
|
||||||
if meta and meta.is_file then
|
|
||||||
return exec_path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not is_windows then return fallback_path end
|
|
||||||
return name -- fallback to just the name, hoping it's in PATH
|
|
||||||
end
|
|
||||||
|
|
||||||
local function init()
|
|
||||||
local exec_path = find_executable(opts.torrserver_path)
|
|
||||||
local windows_args = { 'powershell', '-NoProfile', '-Command', exec_path }
|
|
||||||
local unix_args = { '/bin/bash', '-c', exec_path }
|
|
||||||
local args = is_windows and windows_args or unix_args
|
|
||||||
local res = mp.command_native_async({ name = "subprocess", capture_stdout = true, playback_only = false, args = args })
|
|
||||||
if res.status == 0 then
|
|
||||||
mp.msg.error("TorrServer failed to start: ")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local char_to_hex = function(c)
|
|
||||||
return string.format("%%%02X", string.byte(c))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function urlencode(url)
|
|
||||||
if url == nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
url = url:gsub("\n", "\r\n")
|
|
||||||
url = url:gsub("([^%w ])", char_to_hex)
|
|
||||||
url = url:gsub(" ", "+")
|
|
||||||
return url
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_magnet_info(url)
|
|
||||||
local info_url = opts.server .. "/stream?stat&link=" .. urlencode(url)
|
|
||||||
local res
|
|
||||||
if not (luacurl_available) then
|
|
||||||
-- if Lua-cURL is not available on this system
|
|
||||||
local curl_cmd = {
|
|
||||||
"curl",
|
|
||||||
"-L",
|
|
||||||
"--silent",
|
|
||||||
"--max-time", "10",
|
|
||||||
info_url
|
|
||||||
}
|
|
||||||
local cmd = mp.command_native {
|
|
||||||
name = "subprocess",
|
|
||||||
capture_stdout = true,
|
|
||||||
playback_only = false,
|
|
||||||
args = curl_cmd
|
|
||||||
}
|
|
||||||
res = cmd.stdout
|
|
||||||
else
|
|
||||||
-- otherwise use Lua-cURL (binding to libcurl)
|
|
||||||
local buf = {}
|
|
||||||
local c = cURL.easy_init()
|
|
||||||
c:setopt_followlocation(1)
|
|
||||||
c:setopt_url(info_url)
|
|
||||||
c:setopt_writefunction(function(chunk)
|
|
||||||
table.insert(buf, chunk);
|
|
||||||
return true;
|
|
||||||
end)
|
|
||||||
c:perform()
|
|
||||||
res = table.concat(buf)
|
|
||||||
end
|
|
||||||
if res and res ~= "" then
|
|
||||||
return (require 'mp.utils').parse_json(res)
|
|
||||||
else
|
|
||||||
return nil, "no info response (timeout?)"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function edlencode(url)
|
|
||||||
return "%" .. string.len(url) .. "%" .. url
|
|
||||||
end
|
|
||||||
|
|
||||||
local function guess_type_by_extension(ext)
|
|
||||||
if ext == "mkv" or ext == "mp4" or ext == "avi" or ext == "wmv" or ext == "vob" or ext == "m2ts" or ext == "ogm" then
|
|
||||||
return "video"
|
|
||||||
end
|
|
||||||
if ext == "mka" or ext == "mp3" or ext == "aac" or ext == "flac" or ext == "ogg" or ext == "wma" or ext == "mpg"
|
|
||||||
or ext == "wav" or ext == "wv" or ext == "opus" or ext == "ac3" then
|
|
||||||
return "audio"
|
|
||||||
end
|
|
||||||
if ext == "ass" or ext == "srt" or ext == "vtt" then
|
|
||||||
return "sub"
|
|
||||||
end
|
|
||||||
return "other";
|
|
||||||
end
|
|
||||||
|
|
||||||
local function string_replace(str, match, replace)
|
|
||||||
local s, e = string.find(str, match, 1, true)
|
|
||||||
if s == nil or e == nil then
|
|
||||||
return str
|
|
||||||
end
|
|
||||||
return string.sub(str, 1, s - 1) .. replace .. string.sub(str, e + 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- https://github.com/mpv-player/mpv/blob/master/DOCS/edl-mpv.rst
|
|
||||||
local function generate_m3u(magnet_uri, files)
|
|
||||||
for _, fileinfo in ipairs(files) do
|
|
||||||
-- strip top directory
|
|
||||||
if fileinfo.path:find("/", 1, true) then
|
|
||||||
fileinfo.fullpath = string.sub(fileinfo.path, fileinfo.path:find("/", 1, true) + 1)
|
|
||||||
else
|
|
||||||
fileinfo.fullpath = fileinfo.path
|
|
||||||
end
|
|
||||||
fileinfo.path = {}
|
|
||||||
for w in fileinfo.fullpath:gmatch("([^/]+)") do table.insert(fileinfo.path, w) end
|
|
||||||
local ext = string.match(fileinfo.path[#fileinfo.path], "%.(%w+)$")
|
|
||||||
fileinfo.type = guess_type_by_extension(ext)
|
|
||||||
end
|
|
||||||
table.sort(files, function(a, b)
|
|
||||||
-- make top-level files appear first in the playlist
|
|
||||||
if (#a.path == 1 or #b.path == 1) and #a.path ~= #b.path then
|
|
||||||
return #a.path < #b.path
|
|
||||||
end
|
|
||||||
-- make videos first
|
|
||||||
if (a.type == "video" or b.type == "video") and a.type ~= b.type then
|
|
||||||
return a.type == "video"
|
|
||||||
end
|
|
||||||
-- otherwise sort by path
|
|
||||||
return a.fullpath < b.fullpath
|
|
||||||
end);
|
|
||||||
|
|
||||||
local infohash = magnet_uri:match("^magnet:%?xt=urn:bt[im]h:(%w+)") or urlencode(magnet_uri)
|
|
||||||
|
|
||||||
local playlist = { '#EXTM3U' }
|
|
||||||
|
|
||||||
for _, fileinfo in ipairs(files) do
|
|
||||||
if fileinfo.processed ~= true then
|
|
||||||
table.insert(playlist, '#EXTINF:0,' .. fileinfo.fullpath)
|
|
||||||
local basename = string.match(fileinfo.path[#fileinfo.path], '^(.+)%.%w+$')
|
|
||||||
|
|
||||||
local url = opts.server .. "/stream/" .. urlencode(fileinfo.fullpath) .."?play&index=" .. fileinfo.id .. "&link=" .. infohash
|
|
||||||
local hdr = { "!new_stream", "!no_clip",
|
|
||||||
--"!track_meta,title=" .. edlencode(basename),
|
|
||||||
edlencode(url)
|
|
||||||
}
|
|
||||||
local edl = "edl://" .. table.concat(hdr, ";") .. ";"
|
|
||||||
local external_tracks = 0
|
|
||||||
|
|
||||||
fileinfo.processed = true
|
|
||||||
if opts.search_for_external_tracks and basename ~= nil and fileinfo.type == "video" then
|
|
||||||
mp.msg.info("!" .. basename)
|
|
||||||
|
|
||||||
for _, fileinfo2 in ipairs(files) do
|
|
||||||
if #fileinfo2.path > 0 and
|
|
||||||
fileinfo2.type ~= "other" and
|
|
||||||
fileinfo2.processed ~= true and
|
|
||||||
string.find(fileinfo2.path[#fileinfo2.path], basename, 1, true) ~= nil
|
|
||||||
then
|
|
||||||
mp.msg.info("->" .. fileinfo2.fullpath)
|
|
||||||
local title = string_replace(fileinfo2.fullpath, basename, "%")
|
|
||||||
local url = opts.server .. "/stream/" .. urlencode(fileinfo2.fullpath).."?play&index=" .. fileinfo2.id .. "&link=" .. infohash
|
|
||||||
local hdr = { "!new_stream", "!no_clip", "!no_chapters",
|
|
||||||
"!delay_open,media_type=" .. fileinfo2.type,
|
|
||||||
"!track_meta,title=" .. edlencode(title),
|
|
||||||
edlencode(url)
|
|
||||||
}
|
|
||||||
edl = edl .. table.concat(hdr, ";") .. ";"
|
|
||||||
fileinfo2.processed = true
|
|
||||||
external_tracks = external_tracks + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if external_tracks == 0 then -- dont use edl
|
|
||||||
table.insert(playlist, url)
|
|
||||||
else
|
|
||||||
table.insert(playlist, edl)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return table.concat(playlist, '\n')
|
|
||||||
end
|
|
||||||
|
|
||||||
mp.add_hook("on_load", 5, function()
|
|
||||||
local url = mp.get_property("stream-open-filename")
|
|
||||||
if url:find("^magnet:") == 1 or (url:find("^https?://") == 1 and url:find("%.torrent$") ~= nil) then
|
|
||||||
mp.set_property_bool("file-local-options/ytdl", false)
|
|
||||||
if opts.torrserver_init then init() end
|
|
||||||
local magnet_info, err = get_magnet_info(url)
|
|
||||||
if type(magnet_info) == "table" then
|
|
||||||
if magnet_info.file_stats then
|
|
||||||
-- torrent has multiple files. open as playlist
|
|
||||||
mp.set_property("stream-open-filename", "memory://" .. generate_m3u(url, magnet_info.file_stats))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
-- if not a playlist and has a name
|
|
||||||
if magnet_info.name then
|
|
||||||
mp.set_property("stream-open-filename", "memory://#EXTM3U\n" ..
|
|
||||||
"#EXTINF:0," .. magnet_info.name .. "\n" ..
|
|
||||||
opts.server .. "/stream?play&index=1&link=" .. urlencode(url))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
mp.msg.warn("error: " .. err)
|
|
||||||
end
|
|
||||||
mp.set_property("stream-open-filename", opts.server .. "/stream?m3u&link=" .. urlencode(url))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
Reference in New Issue
Block a user