Files
mpv-config/scripts/uosc_danmaku/sites/mgtv.lua
T
2026-08-15 17:50:48 +02:00

146 lines
4.8 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
local msg = require('mp.msg')
local utils = require('mp.utils')
local user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'
-- 解析多种 time 表示为秒数(支持数字、带小数、HH:MM:SS、MM:SS
local function parse_mgtv_time(time_str)
if time_str == nil then return 0 end
if type(time_str) == 'number' then return time_str end
local s = tostring(time_str):gsub('^%s*(.-)%s*$', '%1')
local n = tonumber(s)
if n then return n end
local h, m, sec = s:match('^(%d+):(%d+):([%d%.]+)$')
if h and m and sec then
return tonumber(h) * 3600 + tonumber(m) * 60 + tonumber(sec)
end
local mm, ss = s:match('^(%d+):([%d%.]+)$')
if mm and ss then
return tonumber(mm) * 60 + tonumber(ss)
end
return 0
end
-- 生成分段请求列表(每段以 ms 为单位的起点)
local function generate_mgtv_segments(api_base, total_seconds, step_ms)
local segments = {}
local end_time_ms = math.floor(total_seconds * 1000)
for i = 0, math.max(0, end_time_ms - 1), step_ms do
table.insert(segments, api_base .. tostring(i))
end
return segments
end
-- 构建通用 curl 请求参数
local function build_mgtv_curl_args(target_url)
local args = {
'curl', '-s', '-L', '--compressed',
'--user-agent', user_agent,
'-H', 'Accept: application/json',
target_url,
}
return args
end
-- 解析单个分段返回并把弹幕追加到 output_table
local function parse_mgtv_segment(out, output_table)
if not out then return end
local j = utils.parse_json(out)
if not j or not j.data or not j.data.items then return end
for _, item in ipairs(j.data.items) do
local t_ms = tonumber(item.time) or 0
local time_s = t_ms / 1000
local content = item.content or ''
local mode = 1
local color = 16777215
local c_param = string.format('%.2f,%d,%d,25,,,', time_s, color, mode)
table.insert(output_table, { c = c_param, m = content })
end
end
local function extract_mgtv_ids(path)
if not path then return nil, nil end
-- 常见格式: /b/<cid>/<vid>.html
local cid, vid = path:match('/b/(%d+)/([%w%._-]+)%.html')
if cid and vid then
vid = vid:match('([^.]+)') or vid
return cid, vid
end
-- 回退:取最后两个 path segment
local segs = {}
for seg in path:gmatch('/([^/]+)') do table.insert(segs, seg) end
if #segs >= 2 then
cid = segs[#segs - 1]
vid = segs[#segs]
vid = vid and vid:match('([^.]+)') or nil
return cid, vid
end
return nil, nil
end
-- 为 芒果TV 加载弹幕
function load_danmaku_for_mgtv(path, callback)
callback = callback or function() end
local url = path or mp.get_property('stream-open-filename', '')
if not url or url == '' then
msg.error('mgtv: 无效的 url')
return
end
local cid, vid = extract_mgtv_ids(url)
if not cid or not vid then
msg.error('mgtv: 无法解析 cid/vid: ' .. tostring(url))
return
end
local info_api = 'https://pcweb.api.mgtv.com/video/info?cid=' .. cid .. '&vid=' .. vid
local api_danmaku_base = 'https://galaxy.bz.mgtv.com/rdbarrage?vid=' .. vid .. '&cid=' .. cid .. '&time='
local args = build_mgtv_curl_args(info_api)
call_cmd_async(args, function(err, out)
if err then
msg.error('mgtv: 请求 video/info 失败: ' .. tostring(err))
callback(false)
return
end
local data = utils.parse_json(out)
if not data or data.code ~= 200 or not data.data or not data.data.info then
msg.info('mgtv: video/info 返回无效')
callback(false)
return
end
local time_str = data.data.info.time
local total_seconds = parse_mgtv_time(time_str)
local step = 60 * 1000
local segments = generate_mgtv_segments(api_danmaku_base, total_seconds, step)
if #segments == 0 then
msg.info('mgtv: 未生成任何弹幕分段请求')
callback(false)
return
end
local output_table = {}
local function per_response_cb(server, err, out)
if err then
msg.debug('mgtv segment request failed: ' .. tostring(server) .. ' err: ' .. tostring(err))
return
end
parse_mgtv_segment(out, output_table)
end
local function final_cb()
local ok = #output_table > 0
local final_json_str = utils.format_json(output_table)
save_danmaku_json(url, final_json_str)
load_danmaku(true)
callback(ok)
end
parallel_requests(segments, build_mgtv_curl_args, per_response_cb, final_cb, { concurrency = 6, per_request_timeout = 10 })
end)
end