776 lines
25 KiB
Lua
776 lines
25 KiB
Lua
VERSION = "2.2.0"
|
|
|
|
mp.commandv('script-message', 'uosc_danmaku-version', VERSION)
|
|
|
|
local msg = require('mp.msg')
|
|
local utils = require("mp.utils")
|
|
|
|
AES = require("modules/aes")
|
|
Base64 = require("modules/base64")
|
|
MD5 = require("modules/md5")
|
|
Sha256 = require("modules/hash")
|
|
|
|
require("modules/options")
|
|
require("modules/utils")
|
|
require("modules/parse")
|
|
require("modules/guess")
|
|
require('modules/render')
|
|
require('modules/menu')
|
|
require("modules/update")
|
|
|
|
require("apis/dandanplay")
|
|
require('apis/extra')
|
|
|
|
require("sites/bilibili")
|
|
require("sites/bahamut")
|
|
require("sites/iqiyi")
|
|
require("sites/mgtv")
|
|
require("sites/tencentvideo")
|
|
require("sites/youku")
|
|
|
|
DANMAKU_PATH = os.getenv("TEMP") or "/tmp/"
|
|
HISTORY_PATH = mp.command_native({"expand-path", options.history_path})
|
|
PID = utils.getpid()
|
|
DANMAKU = {sources = {}, count = 1}
|
|
ENABLED, COMMENTS, DELAY = false, nil, 0
|
|
DELAY_PROPERTY = string.format("user-data/%s/danmaku-delay", mp.get_script_name())
|
|
mp.set_property_native(DELAY_PROPERTY, 0)
|
|
HAS_DANMAKU = string.format("user-data/%s/has-danmaku", mp.get_script_name())
|
|
mp.set_property_bool(HAS_DANMAKU, false)
|
|
DANMAKU_SWITCH_ON = string.format("user-data/%s/danmaku-switch-on", mp.get_script_name())
|
|
mp.set_property_bool(DANMAKU_SWITCH_ON, false)
|
|
DANMAKU_COUNT = string.format("user-data/%s/danmaku-count", mp.get_script_name())
|
|
mp.set_property_native(DANMAKU_COUNT, 0)
|
|
KEY = table_to_zero_indexed({
|
|
0x00,0x01,0x02,0x03,0x04,
|
|
0x05,0x06,0x07,0x08,0x09,
|
|
0x0a,0x0b,0x0c,0x0d,0x0e,
|
|
0x0f,0x10,0x11,0x12,0x13,
|
|
0x14,0x15,0x16,0x17,0x18,
|
|
0x19,0x1a,0x1b,0x1c,0x1d,
|
|
0x1e,0x1f
|
|
})
|
|
|
|
PLATFORM = (function()
|
|
local platform = mp.get_property_native("platform")
|
|
if platform then
|
|
if itable_index_of({ "windows", "darwin" }, platform) then
|
|
return platform
|
|
end
|
|
else
|
|
if os.getenv("windir") ~= nil then
|
|
return "windows"
|
|
end
|
|
local homedir = os.getenv("HOME")
|
|
if homedir ~= nil and string.sub(homedir, 1, 6) == "/Users" then
|
|
return "darwin"
|
|
end
|
|
end
|
|
return "linux"
|
|
end)()
|
|
|
|
local rebuild_convert_timer = nil
|
|
|
|
function get_danmaku_visibility()
|
|
local history_json = read_file(HISTORY_PATH)
|
|
local history
|
|
if history_json ~= nil then
|
|
history = utils.parse_json(history_json) or {}
|
|
local flag = history["show_danmaku"]
|
|
if flag == nil then
|
|
history["show_danmaku"] = false
|
|
write_json_file(HISTORY_PATH, history)
|
|
else
|
|
return flag
|
|
end
|
|
else
|
|
history = {}
|
|
history["show_danmaku"] = false
|
|
write_json_file(HISTORY_PATH, history)
|
|
end
|
|
return false
|
|
end
|
|
|
|
function set_danmaku_visibility(flag)
|
|
local history = {}
|
|
local history_json = read_file(HISTORY_PATH)
|
|
if history_json ~= nil then
|
|
history = utils.parse_json(history_json) or {}
|
|
end
|
|
history["show_danmaku"] = flag
|
|
write_json_file(HISTORY_PATH, history)
|
|
end
|
|
|
|
function set_danmaku_button()
|
|
if get_danmaku_visibility() then
|
|
toggle_danmaku_switch("on")
|
|
end
|
|
end
|
|
|
|
function show_loaded(init)
|
|
if DANMAKU.anime and DANMAKU.episode then
|
|
show_message("匹配内容:" .. DANMAKU.anime .. "-" .. DANMAKU.episode .. "\\N弹幕加载成功,共计" .. #COMMENTS .. "条弹幕", 3)
|
|
if init then
|
|
msg.info(DANMAKU.anime .. "-" .. DANMAKU.episode .. " 弹幕加载成功,共计" .. #COMMENTS .. "条弹幕")
|
|
end
|
|
else
|
|
show_message("弹幕加载成功,共计" .. #COMMENTS .. "条弹幕", 3)
|
|
end
|
|
mp.set_property_native(DANMAKU_COUNT, #COMMENTS)
|
|
end
|
|
|
|
-- 获取指定时间的延迟
|
|
-- 返回该时间点之前所有延迟段的总和
|
|
function get_delay_for_time(delay_segments, time)
|
|
if not delay_segments or #delay_segments == 0 then return 0 end
|
|
|
|
local segs = {}
|
|
for i = 1, #delay_segments do segs[i] = delay_segments[i] end
|
|
table.sort(segs, function(a, b) return a.start < b.start end)
|
|
|
|
local applied_delay = 0
|
|
for i = 1, #segs do
|
|
local seg = segs[i]
|
|
local delay = tonumber(seg.delay)
|
|
if time >= seg.start and delay then
|
|
applied_delay = applied_delay + delay
|
|
else
|
|
break
|
|
end
|
|
end
|
|
return applied_delay
|
|
end
|
|
|
|
local function merge_delay_segments(segments)
|
|
if not segments or #segments == 0 then return {} end
|
|
|
|
local NEAREST_THRESHOLD = 10 -- 最邻近段合并阈值
|
|
local MERGE_THRESHOLD = 30 -- 跨段合并阈值
|
|
local EPSILON = 1e-6 -- 判断接近 0 的阈值
|
|
|
|
table.sort(segments, function(a, b) return a.start < b.start end)
|
|
|
|
local partially_merged = {}
|
|
local i = 1
|
|
while i <= #segments do
|
|
local cur = segments[i]
|
|
local next_seg = segments[i + 1]
|
|
|
|
if next_seg and (next_seg.start - cur.start) <= NEAREST_THRESHOLD then
|
|
local combined_delay = tonumber(cur.delay) + tonumber(next_seg.delay)
|
|
if math.abs(combined_delay) > EPSILON then
|
|
table.insert(partially_merged, {
|
|
start = cur.start,
|
|
delay = combined_delay
|
|
})
|
|
end
|
|
i = i + 2
|
|
else
|
|
if math.abs(tonumber(cur.delay)) > EPSILON then
|
|
table.insert(partially_merged, cur)
|
|
end
|
|
i = i + 1
|
|
end
|
|
end
|
|
|
|
local merged = {}
|
|
for _, seg in ipairs(partially_merged) do
|
|
local merged_flag = false
|
|
for idx, m in ipairs(merged) do
|
|
if math.abs(seg.start - m.start) <= MERGE_THRESHOLD then
|
|
m.delay = tonumber(m.delay) + tonumber(seg.delay)
|
|
if math.abs(m.delay) <= EPSILON then
|
|
table.remove(merged, idx)
|
|
end
|
|
merged_flag = true
|
|
break
|
|
end
|
|
end
|
|
if not merged_flag then
|
|
if math.abs(tonumber(seg.delay)) > EPSILON then
|
|
table.insert(merged, {
|
|
start = seg.start,
|
|
delay = seg.delay
|
|
})
|
|
end
|
|
end
|
|
end
|
|
|
|
table.sort(merged, function(a, b) return a.start < b.start end)
|
|
return merged
|
|
end
|
|
|
|
function parse_delay_input(text)
|
|
if not text then return nil end
|
|
local s = tostring(text):gsub("%s+", "")
|
|
if s == "" then return nil end
|
|
-- XmYs 格式,允许负号在分钟部分
|
|
local m, sec = string.match(s, "^(%-?%d+)m(%d+)s$")
|
|
if m and sec then
|
|
m = tonumber(m)
|
|
sec = tonumber(sec)
|
|
if not m or not sec then return nil end
|
|
if m < 0 then sec = -sec end
|
|
return m * 60 + sec
|
|
end
|
|
-- 普通数字(整数或小数),支持负数
|
|
local n = tonumber(s)
|
|
if n ~= nil then return n end
|
|
return nil
|
|
end
|
|
|
|
local function set_danmaku_delay(dly, time, specific_source)
|
|
if specific_source then
|
|
local source = DANMAKU.sources[specific_source]
|
|
if source and source.data and not source.blocked then
|
|
source.delay_segments = source.delay_segments or {}
|
|
if dly == 0 then
|
|
source.delay_segments = {}
|
|
elseif time then
|
|
table.insert(source.delay_segments, {start = time, delay = dly})
|
|
else
|
|
table.insert(source.delay_segments, {start = 0, delay = dly})
|
|
end
|
|
source.delay = nil
|
|
source.delay_segments = merge_delay_segments(source.delay_segments)
|
|
add_source_to_history(specific_source, source)
|
|
end
|
|
else
|
|
for url, source in pairs(DANMAKU.sources) do
|
|
if source.data and not source.blocked then
|
|
source.delay_segments = source.delay_segments or {}
|
|
if dly == 0 then
|
|
source.delay_segments = {}
|
|
elseif time then
|
|
table.insert(source.delay_segments, {start = time, delay = dly})
|
|
else
|
|
table.insert(source.delay_segments, {start = 0, delay = dly})
|
|
end
|
|
|
|
source.delay = nil
|
|
source.delay_segments = merge_delay_segments(source.delay_segments)
|
|
add_source_to_history(url, source)
|
|
end
|
|
end
|
|
end
|
|
|
|
if not specific_source then
|
|
if dly == 0 then
|
|
DELAY = 0
|
|
else
|
|
DELAY = DELAY + dly
|
|
end
|
|
end
|
|
|
|
if ENABLED and COMMENTS ~= nil then
|
|
render()
|
|
end
|
|
|
|
-- 防抖:批量重建 ASS 事件并渲染,避免频繁变更导致重复重建
|
|
if rebuild_convert_timer then
|
|
rebuild_convert_timer:kill()
|
|
rebuild_convert_timer = nil
|
|
end
|
|
rebuild_convert_timer = mp.add_timeout(0.1, function()
|
|
if convert_danmaku_to_ass_events then
|
|
convert_danmaku_to_ass_events(true)
|
|
end
|
|
render()
|
|
rebuild_convert_timer = nil
|
|
end)
|
|
|
|
if specific_source then
|
|
local source = DANMAKU.sources[specific_source]
|
|
local source_delay = get_delay_for_time(source and source.delay_segments, time or 0)
|
|
show_message('设置弹幕源延迟: ' .. string.format("%.1f", source_delay + 1e-10) .. ' s')
|
|
else
|
|
show_message('设置弹幕延迟: ' .. string.format("%.1f", DELAY + 1e-10) .. ' s')
|
|
mp.set_property_native(DELAY_PROPERTY, DELAY)
|
|
end
|
|
end
|
|
|
|
local function clear_source()
|
|
local path = mp.get_property("path")
|
|
local history_json = read_file(HISTORY_PATH)
|
|
|
|
if not path or not history_json then return end
|
|
|
|
local history = utils.parse_json(history_json) or {}
|
|
if history[path] == nil then return end
|
|
|
|
history[path] = nil
|
|
write_json_file(HISTORY_PATH, history)
|
|
|
|
for url, source in pairs(DANMAKU.sources) do
|
|
if source.from == "user_custom" then
|
|
DANMAKU.sources[url] = nil
|
|
end
|
|
end
|
|
|
|
load_danmaku(false)
|
|
|
|
show_message("已重置当前视频所有弹幕源更改", 3)
|
|
msg.verbose("已重置当前视频所有弹幕源更改")
|
|
end
|
|
|
|
function write_history(episodeid, api_server)
|
|
local history = {}
|
|
local path = mp.get_property("path")
|
|
local dir = get_parent_directory(path)
|
|
local fname = mp.get_property('filename/no-ext')
|
|
local episodeNumber = 0
|
|
if episodeid then
|
|
episodeNumber = tonumber(episodeid) % 1000
|
|
elseif DANMAKU.extra then
|
|
episodeNumber = DANMAKU.extra.episodenum
|
|
end
|
|
|
|
if is_protocol(path) then
|
|
local title, season_num, episod_num = parse_title()
|
|
if title and episod_num then
|
|
if season_num then
|
|
dir = title .." Season".. season_num
|
|
else
|
|
dir = title
|
|
end
|
|
fname = url_decode(mp.get_property("media-title"))
|
|
episodeNumber = episod_num
|
|
end
|
|
end
|
|
|
|
if dir ~= nil then
|
|
local history_json = read_file(HISTORY_PATH)
|
|
if history_json ~= nil then
|
|
history = utils.parse_json(history_json) or {}
|
|
end
|
|
history[dir] = {}
|
|
history[dir].fname = fname
|
|
history[dir].source = DANMAKU.source
|
|
history[dir].animeTitle = DANMAKU.anime
|
|
history[dir].episodeTitle = DANMAKU.episode
|
|
history[dir].episodeNumber = episodeNumber
|
|
if episodeid then
|
|
history[dir].episodeId = episodeid
|
|
elseif DANMAKU.extra then
|
|
history[dir].extra = DANMAKU.extra
|
|
end
|
|
if api_server then
|
|
history[dir].api_server = api_server
|
|
end
|
|
write_json_file(HISTORY_PATH, history)
|
|
end
|
|
end
|
|
|
|
function remove_source_from_history(rm_source)
|
|
local history_json = read_file(HISTORY_PATH)
|
|
local path = mp.get_property("path")
|
|
|
|
if is_protocol(path) then
|
|
path = remove_query(path)
|
|
end
|
|
|
|
if history_json then
|
|
local history = utils.parse_json(history_json) or {}
|
|
|
|
if history[path] ~= nil and history[path]["sources"] ~= nil then
|
|
for source in pairs(history[path]["sources"]) do
|
|
if source == rm_source then
|
|
history[path]["sources"][source] = nil
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
write_json_file(HISTORY_PATH, history)
|
|
end
|
|
end
|
|
|
|
function add_source_to_history(add_url, add_source)
|
|
local history_json = read_file(HISTORY_PATH)
|
|
local path = mp.get_property("path")
|
|
|
|
if is_protocol(path) then
|
|
path = remove_query(path)
|
|
end
|
|
|
|
local history = {}
|
|
if history_json then
|
|
history = utils.parse_json(history_json) or {}
|
|
end
|
|
|
|
history[path] = history[path] or {}
|
|
history[path]["sources"] = history[path]["sources"] or {}
|
|
history[path]["sources"][add_url] = history[path]["sources"][add_url] or {}
|
|
|
|
local record = history[path]["sources"][add_url]
|
|
record.from = add_source.from or "user_custom"
|
|
record.blocked = add_source.blocked or false
|
|
|
|
local delay_segments = shallow_copy(add_source.delay_segments or {})
|
|
if #delay_segments > 0 then
|
|
record.delay_segments = merge_delay_segments(delay_segments)
|
|
if #record.delay_segments == 0 then
|
|
record.delay_segments = nil
|
|
end
|
|
else
|
|
record.delay_segments = nil
|
|
end
|
|
|
|
record.delay = nil
|
|
write_json_file(HISTORY_PATH, history)
|
|
end
|
|
|
|
function read_danmaku_source_record(path)
|
|
if is_protocol(path) then
|
|
path = remove_query(path)
|
|
end
|
|
|
|
local history_json = read_file(HISTORY_PATH)
|
|
if not history_json then return end
|
|
|
|
local history = utils.parse_json(history_json) or {}
|
|
local record = history[path]
|
|
|
|
if not record or not record.sources then return end
|
|
|
|
local sources = record.sources
|
|
local upgraded_sources = {}
|
|
|
|
if is_nested_table(sources) then
|
|
for source, data in pairs(sources) do
|
|
local from = data.from or "user_custom"
|
|
local blocked = data.blocked or false
|
|
local delay_segments = shallow_copy(data.delay_segments or {})
|
|
if data.delay ~= nil then
|
|
for i = #delay_segments, 1, -1 do
|
|
if delay_segments[i].start == 0 then
|
|
table.remove(delay_segments, i)
|
|
end
|
|
end
|
|
table.insert(delay_segments, 1, { start = 0, delay = tonumber(data.delay) })
|
|
end
|
|
if #delay_segments > 0 then
|
|
delay_segments = merge_delay_segments(delay_segments)
|
|
else
|
|
delay_segments = nil
|
|
end
|
|
|
|
DANMAKU.sources[source] = {
|
|
from = from,
|
|
blocked = blocked,
|
|
delay_segments = delay_segments,
|
|
from_history = true,
|
|
}
|
|
end
|
|
else
|
|
for _, raw in ipairs(sources) do
|
|
local source = raw
|
|
local blocked = false
|
|
local from = raw:match("<(.-)>")
|
|
local delay = raw:match("{{(.-)}}")
|
|
|
|
source = source:gsub("<.->", ""):gsub("{{.-}}", "")
|
|
|
|
if source:match("^%-") then
|
|
source = source:sub(2)
|
|
blocked = true
|
|
from = from or "api_server"
|
|
end
|
|
|
|
local delay_segments = nil
|
|
if delay ~= nil then
|
|
delay_segments = {
|
|
{ start = 0, delay = tonumber(delay) }
|
|
}
|
|
end
|
|
|
|
DANMAKU.sources[source] = {
|
|
from = from or "user_custom",
|
|
blocked = blocked,
|
|
delay_segments = delay_segments,
|
|
from_history = true,
|
|
}
|
|
|
|
upgraded_sources[source] = shallow_copy(DANMAKU.sources[source])
|
|
end
|
|
|
|
if next(upgraded_sources) then
|
|
record.sources = upgraded_sources
|
|
write_json_file(HISTORY_PATH, history)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function get_save_danmaku_output(path, filename)
|
|
if not path or not filename then return nil end
|
|
|
|
local custom_dir = options.save_danmaku_path ~= "" and
|
|
mp.command_native({"expand-path", options.save_danmaku_path}) or nil
|
|
local is_url = is_protocol(path)
|
|
local mode = options.save_danmaku_path_mode
|
|
local dir = nil
|
|
|
|
if mode ~= "url" and mode ~= "all" then
|
|
mode = "local"
|
|
end
|
|
|
|
if custom_dir and (mode == "all" or (mode == "url" and is_url) or (mode == "local" and not is_url)) then
|
|
local output_name = sanitize_filename(filename)
|
|
if not is_url then
|
|
dir = get_parent_directory(path)
|
|
local _, parent_name = dir and utils.split_path(dir:sub(1, -2))
|
|
if parent_name and parent_name ~= "" then
|
|
output_name = sanitize_filename(parent_name .. "_" .. filename)
|
|
end
|
|
end
|
|
return utils.join_path(custom_dir, output_name .. ".xml")
|
|
end
|
|
|
|
if is_url then
|
|
return nil
|
|
end
|
|
|
|
dir = get_parent_directory(path)
|
|
if not dir then
|
|
return nil
|
|
end
|
|
return utils.join_path(dir, filename .. ".xml")
|
|
end
|
|
|
|
-- 视频播放时保存弹幕
|
|
function save_danmaku(not_forced)
|
|
local path = mp.get_property("path")
|
|
local filename = is_protocol(path) and mp.get_property("media-title") or mp.get_property('filename/no-ext')
|
|
local danmaku_out = get_save_danmaku_output(path, filename)
|
|
if not danmaku_out or (not file_exists(danmaku_out)
|
|
and not is_writable(danmaku_out)) then
|
|
show_message("此弹幕文件不支持保存至本地")
|
|
msg.warn("此弹幕文件不支持保存至本地")
|
|
else
|
|
if not_forced and file_exists(danmaku_out) then
|
|
show_message("已存在同名弹幕文件:" .. danmaku_out)
|
|
msg.info("已存在同名弹幕文件:" .. danmaku_out)
|
|
return
|
|
else
|
|
convert_danmaku_to_xml(danmaku_out)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- 加载弹幕
|
|
function load_danmaku(from_menu, no_osd)
|
|
if not ENABLED then return end
|
|
convert_danmaku_to_ass_events()
|
|
render_danmaku(from_menu, no_osd)
|
|
end
|
|
|
|
function load_danmaku_for_url(path)
|
|
if path:find('bilibili.com') or path:find('bilivideo.c[nom]+') then
|
|
load_danmaku_for_bilibili(path)
|
|
return
|
|
end
|
|
|
|
if path:find('bahamut.akamaized.net') then
|
|
load_danmaku_for_bahamut(path)
|
|
return
|
|
end
|
|
|
|
local title, season_num, episod_num = parse_title()
|
|
local filename = url_decode(mp.get_property("media-title"))
|
|
local episod_number = nil
|
|
if title and episod_num then
|
|
if season_num then
|
|
dir = title .." Season".. season_num
|
|
episod_number = episod_num
|
|
else
|
|
dir = title
|
|
end
|
|
auto_load_danmaku(path, dir, filename, episod_number)
|
|
addon_danmaku(dir, false)
|
|
return
|
|
end
|
|
get_danmaku_with_hash(filename, path)
|
|
addon_danmaku()
|
|
end
|
|
|
|
-- 自动加载上次匹配的弹幕
|
|
function auto_load_danmaku(path, dir, filename, number)
|
|
if dir ~= nil then
|
|
local history_json = read_file(HISTORY_PATH)
|
|
if history_json ~= nil then
|
|
local history = utils.parse_json(history_json) or {}
|
|
-- 1.判断父文件名是否存在
|
|
local history_dir = history[dir]
|
|
if history_dir ~= nil then
|
|
--2.如果存在,则获取number和id
|
|
DANMAKU.anime = history_dir.animeTitle
|
|
local episode_number = history_dir.episodeTitle and history_dir.episodeTitle:match("%d+")
|
|
local history_number = history_dir.episodeNumber
|
|
local history_id = history_dir.episodeId
|
|
local history_fname = history_dir.fname
|
|
local history_extra = history_dir.extra
|
|
local history_api_server = history_dir.api_server
|
|
local playing_number = nil
|
|
|
|
if history_fname then
|
|
if filename ~= history_fname then
|
|
if number then
|
|
playing_number = number
|
|
else
|
|
history_number, playing_number = get_episode_number(filename, history_fname)
|
|
end
|
|
else
|
|
playing_number = history_number
|
|
end
|
|
else
|
|
playing_number = get_episode_number(filename)
|
|
end
|
|
if playing_number ~= nil then
|
|
local x = playing_number - history_number --获取集数差值
|
|
DANMAKU.episode = episode_number and string.format("第%s话", episode_number + x) or history_dir.episodeTitle
|
|
DANMAKU.api_server = history_api_server or nil
|
|
show_message("自动加载上次匹配的弹幕", 3)
|
|
msg.verbose("自动加载上次匹配的弹幕")
|
|
if history_id then
|
|
local tmp_id = tostring(x + history_id)
|
|
set_episode_id(tmp_id)
|
|
elseif history_extra then
|
|
local episodenum = history_extra.episodenum + x
|
|
get_details(history_extra.class, history_extra.id, history_extra.site,
|
|
history_extra.title, history_extra.year, history_extra.number, episodenum)
|
|
end
|
|
else
|
|
get_danmaku_with_hash(filename, path)
|
|
end
|
|
else
|
|
get_danmaku_with_hash(filename, path)
|
|
end
|
|
else
|
|
get_danmaku_with_hash(filename, path)
|
|
end
|
|
end
|
|
end
|
|
|
|
function init(path)
|
|
if not path then return end
|
|
local dir = get_parent_directory(path)
|
|
local filename = mp.get_property('filename/no-ext')
|
|
local video = mp.get_property_native("current-tracks/video")
|
|
local duration = mp.get_property_number("duration", 0)
|
|
if not video or video["image"] or video["albumart"] or duration < 60 then
|
|
msg.info("不支持的播放内容(非视频)")
|
|
return
|
|
end
|
|
if is_protocol(path) then
|
|
load_danmaku_for_url(path)
|
|
end
|
|
if dir and filename then
|
|
local danmaku_xml = utils.join_path(dir, filename .. ".xml")
|
|
if file_exists(danmaku_xml) then
|
|
add_danmaku_source_local(danmaku_xml, true)
|
|
else
|
|
auto_load_danmaku(path, dir, filename)
|
|
addon_danmaku(dir, true)
|
|
end
|
|
end
|
|
end
|
|
|
|
mp.register_event("file-loaded", function()
|
|
local path = mp.get_property("path")
|
|
local dir = get_parent_directory(path)
|
|
local filename = mp.get_property('filename/no-ext')
|
|
local video = mp.get_property_native("current-tracks/video")
|
|
local fps = mp.get_property_number("container-fps", 0)
|
|
local duration = mp.get_property_number("duration", 0)
|
|
if not video or video["image"] or video["albumart"] or fps < 23 or duration < 60 then
|
|
return
|
|
end
|
|
|
|
read_danmaku_source_record(path)
|
|
|
|
if not get_danmaku_visibility() then
|
|
return
|
|
end
|
|
|
|
if options.autoload_for_url and is_protocol(path) then
|
|
ENABLED = true
|
|
load_danmaku_for_url(path)
|
|
end
|
|
|
|
if filename == nil or dir == nil then
|
|
return
|
|
end
|
|
local danmaku_xml = utils.join_path(dir, filename .. ".xml")
|
|
if options.autoload_local_danmaku then
|
|
if file_exists(danmaku_xml) then
|
|
ENABLED = true
|
|
add_danmaku_source_local(danmaku_xml)
|
|
return
|
|
end
|
|
end
|
|
|
|
if options.auto_load then
|
|
ENABLED = true
|
|
auto_load_danmaku(path, dir, filename)
|
|
addon_danmaku(dir, false)
|
|
return
|
|
end
|
|
|
|
if ENABLED and COMMENTS == nil and not is_async_running() then
|
|
init(path)
|
|
end
|
|
end)
|
|
|
|
-------------- 键位绑定 --------------
|
|
mp.add_key_binding(options.open_search_danmaku_menu_key, "open_search_danmaku_menu", function()
|
|
mp.commandv("script-message", "open_search_danmaku_menu")
|
|
end)
|
|
mp.add_key_binding(options.show_danmaku_keyboard_key, "show_danmaku_keyboard", function()
|
|
mp.commandv("script-message", "show_danmaku_keyboard")
|
|
end)
|
|
|
|
mp.register_script_message("danmaku-delay", function(...)
|
|
local commands = {...}
|
|
local delay_str, time_str = commands[1], commands[2]
|
|
local source_arg = commands[3]
|
|
local dly = parse_delay_input(delay_str)
|
|
local time = time_str and tonumber(time_str)
|
|
if type(dly) ~= "number" then
|
|
show_message("参数错误:缺少有效的延迟秒数", 3)
|
|
return
|
|
end
|
|
if source_arg and source_arg ~= "nil" then
|
|
set_danmaku_delay(dly, time, source_arg)
|
|
else
|
|
set_danmaku_delay(dly, time)
|
|
end
|
|
end)
|
|
|
|
mp.register_script_message("show_danmaku_keyboard", function()
|
|
ENABLED = not ENABLED
|
|
if ENABLED then
|
|
toggle_danmaku_switch("on")
|
|
|
|
if COMMENTS == nil then
|
|
show_message("加载弹幕初始化...", 3)
|
|
set_danmaku_visibility(true)
|
|
local path = mp.get_property("path")
|
|
init(path)
|
|
else
|
|
show_loaded()
|
|
show_danmaku_func()
|
|
end
|
|
else
|
|
show_message("关闭弹幕", 2)
|
|
toggle_danmaku_switch("off")
|
|
hide_danmaku_func()
|
|
end
|
|
end)
|
|
|
|
mp.register_script_message("check-update", check_for_update)
|
|
mp.register_script_message("clear-source", clear_source)
|
|
mp.register_script_message("immediately_save_danmaku", save_danmaku)
|
|
mp.register_script_message("open_source_delay_menu", open_delay_menu)
|
|
mp.register_script_message("open_search_danmaku_menu", open_input_menu)
|
|
mp.register_script_message("open_add_source_menu", open_add_menu)
|
|
mp.register_script_message("open_add_total_menu", open_add_total_menu) |