// ==UserScript==
// @name M3U8 Filter Ad Script
// @namespace http://tampermonkey.net/
// @version 1.3.0
// @description 自用,拦截和过滤 m3u8(解析/采集资源) 的切片(插播)广告,同时在console打印过滤的行信息,不会误删。
// @author ltxlong
// @match *://*/*
// @run-at document-start
// @grant unsafeWindow
// @grant GM_getResourceText
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @require https://unpkg.com/sweetalert2@11/dist/sweetalert2.min.js
// @resource Swal https://unpkg.com/sweetalert2@11/dist/sweetalert2.min.css
// @resource SwalDark https://unpkg.com/@sweetalert2/theme-dark@5/dark.min.css
// @license MIT
// ==/UserScript==
(function() {
'use strict';
let ts_name_len = 0; // ts前缀长度
let ts_name_len_extend = 1; // 容错
let first_extinf_row = '';
let the_extinf_judge_row_n = 0;
let the_same_extinf_name_n = 0;
let the_extinf_benchmark_n = 5; // 基准
let prev_ts_name_index = -1; // 上个ts序列号
let first_ts_name_index = -1; // 首个ts序列号
let ts_type = 0; // 0:xxxx000数字递增.ts模式0 ;1:xxxxxxxxxx.ts模式1 ;2:***.ts模式2-暴力拆解
let the_ext_x_mode = 0; // 0:ext_x_discontinuity判断模式0 ;1:ext_x_discontinuity判断模式1
let the_current_host = unsafeWindow.location.hostname;
let script_whitelist_mode_flag = false; // 是否启用白名单模式,默认否,默认是匹配所有的网站
let the_current_host_in_whitelist_flag = false; // 当前域名是否在白名单,默认否
let show_toast_tip_flag = false; // 是否启用弹窗提示,默认否
let violent_filter_mode_flag = false; // 是否启用暴力拆解模式,默认否-自动判断模式
let filter_log_html = '';
let filter_done_flag = false;
function filter_log(...msg) {
const log_content = msg.join('</p><p>');
console.log('%c[m3u8_filter_ad]', 'font-weight: bold; color: white; background-color: #70b566b0; padding: 2px; border-radius: 2px;', ...msg);
filter_log_html += `
<p>
<span style="font-weight: bold; color: white; background-color: #70b566b0; padding: 2px; border-radius: 2px;">[m3u8_filter_ad]</span>
${log_content}
</p>
`;
}
let the_swalcss_color = "#ff679a";
let swalcss = `
.swal2-styled{transition: all 0.2s ease;}
.swal2-loader{display:none;align-items:center;justify-content:center;width:2.2em;height:2.2em;margin:0 1.875em;-webkit-animation:swal2-rotate-loading 1.5s linear 0s infinite normal;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border-width:.25em;border-style:solid;border-radius:100%;border-color:${the_swalcss_color} transparent }
.swal2-styled.swal2-confirm{border:0;border-radius:.25em;background:initial;background-color:${the_swalcss_color};color:#fff;font-size:1em}
.swal2-styled.swal2-confirm:hover,.swal2-styled.swal2-deny:hover{opacity:0.8;background-image:none!important}
.swal2-styled.swal2-confirm:focus{box-shadow:0 0 0 3px ${the_swalcss_color}80}
.swal2-styled.swal2-deny:focus{box-shadow:0 0 0 3px #dc374180}
.swal2-timer-progress-bar-container{position:absolute;right:0;bottom:0;left:0;grid-column:auto;overflow:hidden;border-bottom-right-radius:5px;border-bottom-left-radius:5px}
.swal2-timer-progress-bar{width:100%;height:.25em;background:${the_swalcss_color}33 }
.swal2-progress-steps .swal2-progress-step{z-index:20;flex-shrink:0;width:2em;height:2em;border-radius:2em;background:${the_swalcss_color};color:#fff;line-height:2em;text-align:center}
.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step{background:${the_swalcss_color} }
.swal2-progress-steps .swal2-progress-step-line{z-index:10;flex-shrink:0;width:2.5em;height:.4em;margin:0 -1px;background:${the_swalcss_color}}
.swal2-popup {padding:1.25em 0 1.25em;flex-direction:column}
.swal2-close {position:absolute;top:1px;right:1px;transition: all 0.2s ease;}
div:where(.swal2-container) .swal2-html-container{padding: 1.3em 1.3em 0.3em;}
div:where(.swal2-container) button:where(.swal2-close):hover {color:${the_swalcss_color}!important;font-size:60px!important}
div:where(.swal2-icon) .swal2-icon-content {font-family: sans-serif;}
.swal2-container {z-index: 1145141919810;}
`;
// 动态添加样式
function add_style(id, css) {
let try_add_style_n = 0;
let try_to_add_style = function() {
let the_style_dom = unsafeWindow.document.getElementById(id);
if (the_style_dom) the_style_dom.remove();
let the_style = unsafeWindow.document.createElement('style');
the_style.rel = 'stylesheet';
the_style.id = id;
the_style.innerHTML = css;
let the_target_element = unsafeWindow.document.body;
if (the_target_element) {
the_target_element.insertBefore(the_style, the_target_element.firstChild);
} else {
try_add_style_n++;
if (try_add_style_n < 50) {
setTimeout(try_to_add_style, 100);
}
}
};
try_to_add_style();
}
// 先监听颜色方案变化
unsafeWindow.matchMedia('(prefers-color-scheme: dark)').addListener(function (e) {
if (e.matches) {
// 切换到暗色主题
add_style('swal-pub-style', GM_getResourceText('SwalDark'));
} else {
// 切换到浅色主题
add_style('swal-pub-style', GM_getResourceText('Swal'));
}
add_style('Panlinker-SweetAlert2-User', swalcss);
});
// 再修改主题
if (unsafeWindow.matchMedia && unsafeWindow.matchMedia('(prefers-color-scheme: dark)').matches) {
// 切换到暗色主题
add_style('swal-pub-style', GM_getResourceText('SwalDark'));
} else {
// 切换到浅色主题
add_style('swal-pub-style', GM_getResourceText('Swal'));
}
add_style('Panlinker-SweetAlert2-User', swalcss);
// Toast 提示配置
let toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
showCloseButton: true,
didOpen: function (toast) {
toast.addEventListener('mouseenter', Swal.stopTimer);
toast.addEventListener('mouseleave', Swal.resumeTimer);
}
});
// Toast 简易调用
let message = {
success: function (text) {
toast.fire({ title: text, icon: 'success' });
},
error: function (text) {
toast.fire({ title: text, icon: 'error' });
},
warning: function (text) {
toast.fire({ title: text, icon: 'warning' });
},
info: function (text) {
toast.fire({ title: text, icon: 'info' });
},
question: function (text) {
toast.fire({ title: text, icon: 'question' });
}
};
function is_m3u8_file(url) {
return /\.m3u8($|\?)/.test(url);
}
function extract_number_before_ts(str) {
// 匹配 .ts 前面的数字
const match = str.match(/(\d+)\.ts/);
if (match) {
// 使用 parseInt 去掉前导 0
return parseInt(match[1], 10);
}
return null; // 如果不匹配,返回 null
}
function filter_lines(lines) {
let result = [];
if (violent_filter_mode_flag) {
filter_log('----------------------------暴力拆解模式--------------------------');
ts_type = 2; // ts命名模式
} else {
filter_log('----------------------------自动判断模式--------------------------');
let the_normal_int_ts_n = 0;
let the_diff_int_ts_n = 0;
let last_ts_name_len = 0;
// 初始化参数
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
// 初始化first_extinf_row
if (the_extinf_judge_row_n === 0 && line.startsWith('#EXTINF')) {
first_extinf_row = line;
the_extinf_judge_row_n++;
} else if (the_extinf_judge_row_n === 1 && line.startsWith('#EXTINF')) {
if (line !== first_extinf_row) {
first_extinf_row = '';
}
the_extinf_judge_row_n++;
}
// 判断ts模式
let the_ts_name_len = line.indexOf('.ts'); // ts前缀长度
if (the_ts_name_len > 0) {
if (the_extinf_judge_row_n === 1) {
ts_name_len = the_ts_name_len;
}
last_ts_name_len = the_ts_name_len;
let ts_name_index = extract_number_before_ts(line);
if (ts_name_index === null) {
if (the_extinf_judge_row_n === 1) {
ts_type = 1; // ts命名模式
} else if (the_extinf_judge_row_n === 2 && (ts_type === 1 || the_ts_name_len === ts_name_len)) {
ts_type = 1; // ts命名模式
filter_log('----------------------------识别ts模式1---------------------------');
break;
} else {
the_diff_int_ts_n++;
}
} else {
// 如果序号相隔等于1: 模式0
// 如果序号相隔大于1,或其他:模式2(暴力拆解)
if (the_normal_int_ts_n === 0) {
// 初始化ts序列号
prev_ts_name_index = ts_name_index;
first_ts_name_index = ts_name_index;
prev_ts_name_index = first_ts_name_index - 1;
}
if (the_ts_name_len !== ts_name_len) {
if (the_ts_name_len === last_ts_name_len + 1 && ts_name_index === prev_ts_name_index + 1) {
if (the_diff_int_ts_n) {
if (ts_name_index === prev_ts_name_index + 1) {
ts_type = 0; // ts命名模式
prev_ts_name_index = first_ts_name_index - 1;
filter_log('----------------------------识别ts模式0---------------------------')
break;
} else {
ts_type = 2; // ts命名模式
filter_log('----------------------------识别ts模式2---------------------------')
break;
}
}
the_normal_int_ts_n++;
prev_ts_name_index = ts_name_index;
} else {
the_diff_int_ts_n++;
}
} else {
if (the_diff_int_ts_n) {
if (ts_name_index === prev_ts_name_index + 1) {
ts_type = 0; // ts命名模式
prev_ts_name_index = first_ts_name_index - 1;
filter_log('----------------------------识别ts模式0---------------------------')
break;
} else {
ts_type = 2; // ts命名模式
filter_log('----------------------------识别ts模式2---------------------------')
break;
}
}
the_normal_int_ts_n++;
prev_ts_name_index = ts_name_index;
}
}
}
if (i === lines.length - 1) {
// 后缀不是ts,而是jpeg等等,或者以上规则判断不了的,或者没有广告切片的:直接暴力拆解过滤
ts_type = 2; // ts命名模式
filter_log('----------------------------进入暴力拆解模式---------------------------')
}
}
}
// 开始遍历过滤
for (let i = 0; i < lines.length; i++) {
let ts_index_check = false;
const line = lines[i];
if (ts_type === 0) {
if (line.startsWith('#EXT-X-DISCONTINUITY') && lines[i + 1] && lines[i + 2]) {
// 检查当前行是否跟 #EXT-X-PLAYLIST-TYPE相关
if (i > 0 && lines[i - 1].startsWith('#EXT-X-PLAYLIST-TYPE')) {
result.push(line);
continue;
} else {
let the_ts_name_len = lines[i + 2].indexOf('.ts'); // ts前缀长度
if (the_ts_name_len > 0) {
// 根据ts名字长度过滤
if (the_ts_name_len - ts_name_len > ts_name_len_extend) {
// 广告过滤
if (lines[i + 3] && lines[i + 3].startsWith('#EXT-X-DISCONTINUITY')) {
// 打印即将过滤的行
filter_log('过滤规则: #EXT-X-DISCONTINUITY-ts文件名长度-');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1], "\n", lines[i + 2], "\n", lines[i + 3]);
filter_log('------------------------------------------------------------------');
i += 3;
} else {
// 打印即将过滤的行
filter_log('过滤规则: #EXT-X-DISCONTINUITY-ts文件名长度');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1], "\n", lines[i + 2]);
filter_log('------------------------------------------------------------------');
i += 2;
}
continue;
} else {
ts_name_len = the_ts_name_len;
}
// 根据ts序列号过滤
let the_ts_name_index = extract_number_before_ts(lines[i + 2]);
if (the_ts_name_index !== prev_ts_name_index + 1) {
// 广告过滤
if (lines[i + 3] && lines[i + 3].startsWith('#EXT-X-DISCONTINUITY')) {
// 打印即将过滤的行
filter_log('过滤规则: #EXT-X-DISCONTINUITY-ts序列号-');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1], "\n", lines[i + 2], "\n", lines[i + 3]);
filter_log('------------------------------------------------------------------');
i += 3;
} else {
// 打印即将过滤的行
filter_log('过滤规则: #EXT-X-DISCONTINUITY-ts序列号');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1], "\n", lines[i + 2]);
filter_log('------------------------------------------------------------------');
i += 2;
}
continue;
}
}
}
}
if (line.startsWith('#EXTINF') && lines[i + 1]) {
let the_ts_name_len = lines[i + 1].indexOf('.ts'); // ts前缀长度
if (the_ts_name_len > 0) {
// 根据ts名字长度过滤
if (the_ts_name_len - ts_name_len > ts_name_len_extend) {
// 广告过滤
if (lines[i + 2] && lines[i + 2].startsWith('#EXT-X-DISCONTINUITY')) {
// 打印即将过滤的行
filter_log('过滤规则: #EXTINF-ts文件名长度-');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1], "\n", lines[i + 2]);
filter_log('------------------------------------------------------------------');
i += 2;
} else {
// 打印即将过滤的行
filter_log('过滤规则: #EXTINF-ts文件名长度');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1]);
filter_log('------------------------------------------------------------------');
i += 1;
}
continue;
} else {
ts_name_len = the_ts_name_len;
}
// 根据ts序列号过滤
let the_ts_name_index = extract_number_before_ts(lines[i + 1]);
if (the_ts_name_index === prev_ts_name_index + 1) {
prev_ts_name_index++;
} else {
// 广告过滤
if (lines[i + 2].startsWith('#EXT-X-DISCONTINUITY')) {
// 打印即将过滤的行
filter_log('过滤规则: #EXTINF-ts序列号-');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1], "\n", lines[i + 2]);
filter_log('------------------------------------------------------------------');
i += 2;
} else {
// 打印即将过滤的行
filter_log('过滤规则: #EXTINF-ts序列号');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1]);
filter_log('------------------------------------------------------------------');
i += 1;
}
continue;
}
}
}
} else if (ts_type === 1) {
if (line.startsWith('#EXTINF')) {
if (line === first_extinf_row && the_same_extinf_name_n <= the_extinf_benchmark_n && the_ext_x_mode === 0) {
the_same_extinf_name_n++;
} else {
the_ext_x_mode = 1;
}
if (the_same_extinf_name_n > the_extinf_benchmark_n) {
the_ext_x_mode = 1;
}
}
if (line.startsWith('#EXT-X-DISCONTINUITY')) {
// 检查当前行是否跟 #EXT-X-PLAYLIST-TYPE相关
if (i > 0 && lines[i - 1].startsWith('#EXT-X-PLAYLIST-TYPE')) {
result.push(line);
continue;
} else {
// 如果第 i+2 行是 .ts 文件,跳过当前行和接下来的两行
if (lines[i + 1] && lines[i + 1].startsWith('#EXTINF') && lines[i + 2] && lines[i + 2].indexOf('.ts') > 0) {
let the_ext_x_discontinuity_condition_flag = false;
if (the_ext_x_mode === 1) {
the_ext_x_discontinuity_condition_flag = lines[i + 1] !== first_extinf_row && the_same_extinf_name_n > the_extinf_benchmark_n;
}
// 进一步检测第 i+3 行是否也是 #EXT-X-DISCONTINUITY
if (lines[i + 3] && lines[i + 3].startsWith('#EXT-X-DISCONTINUITY') && the_ext_x_discontinuity_condition_flag) {
// 打印即将过滤的行
filter_log('过滤规则: #EXT-X-DISCONTINUITY-广告-#EXT-X-DISCONTINUITY过滤');
filter_log('过滤的行:', "\n", line, "\n", lines[i + 1], "\n", lines[i + 2], "\n", lines[i + 3]);
filter_log('------------------------------------------------------------------');
i += 3; // 跳过当前行和接下来的三行
} else {
// 打印即将过滤的行
filter_log('过滤规则: #EXT-X-DISCONTINUITY-单个标识过滤');
filter_log('过滤的行:', "\n", line);
filter_log('------------------------------------------------------------------');
}
continue;
}
}
}
} else {
// 暴力拆解
if (line.startsWith('#EXT-X-DISCONTINUITY')) {
// 检查当前行是否跟 #EXT-X-PLAYLIST-TYPE相关
if (i > 0 && lines[i - 1].startsWith('#EXT-X-PLAYLIST-TYPE')) {
result.push(line);
continue;
} else {
// 打印即将过滤的行
filter_log('过滤规则: #EXT-X-DISCONTINUITY-单个标识过滤');
filter_log('过滤的行:', "\n", line);
filter_log('------------------------------------------------------------------');
continue;
}
}
}
// 保留不需要过滤的行
result.push(line);
}
return result;
}
async function safely_process_m3u8(url, content) {
try {
const lines = content.split('\n');
const new_ines = filter_lines(lines);
return new_ines.join('\n');
} catch (e) {
filter_log(`处理 m3u8 文件时出错: ${url}`, e);
return content;
}
}
// 脚本菜单变量
let menu_item_violent = null;
let menu_item_mode = null;
let menu_item_host_join = null;
let menu_item_toast = null;
let menu_item_filter_tip = null;
function hookXHR() {
const OriginalXHR = unsafeWindow.XMLHttpRequest;
unsafeWindow.XMLHttpRequest = class extends OriginalXHR {
constructor() {
super();
this.addEventListener('readystatechange', async function () {
if (this.readyState === 4 && this.status === 200 && is_m3u8_file(this.responseURL)) {
filter_log('----------------------------hookXHR成功---------------------------');
const modifiedResponse = await safely_process_m3u8(this.responseURL, this.responseText);
Object.defineProperty(this, 'responseText', { value: modifiedResponse });
Object.defineProperty(this, 'response', { value: modifiedResponse });
if (show_toast_tip_flag) {
message.success('已成功过滤切片广告');
}
filter_done_flag = true;
GM_unregisterMenuCommand(menu_item_filter_tip);
check_menu_item_filter_tip();
}
}, false);
}
};
}
function initHook() {
hookXHR();
}
// 初始化菜单判断变量
violent_filter_mode_flag = GM_getValue('violent_filter_mode_flag', false);
script_whitelist_mode_flag = GM_getValue('script_whitelist_mode_flag', false);
the_current_host_in_whitelist_flag = GM_getValue(the_current_host, false);
show_toast_tip_flag = GM_getValue('show_toast_tip_flag', false);
function check_menu_item_violent() {
if (violent_filter_mode_flag) {
menu_item_violent = GM_registerMenuCommand('暴力拆解模式(可点击切换到自动判断过滤模式)', function() {
GM_setValue('violent_filter_mode_flag', false);
violent_filter_mode_flag = false;
message.success('已设置:<br><br>自动判断过滤模式!');
unsafeWindow.location.reload();
});
} else {
menu_item_violent = GM_registerMenuCommand('自动判断过滤模式(可点击切换到暴力拆解模式)', function() {
GM_setValue('violent_filter_mode_flag', true);
violent_filter_mode_flag = true;
message.success('已设置:<br><br>暴力拆解模式!');
unsafeWindow.location.reload();
});
}
}
function check_menu_item_mode() {
if (script_whitelist_mode_flag) {
menu_item_mode = GM_registerMenuCommand('现在是白名单模式(可点击切换到全匹配模式)', function() {
GM_setValue('script_whitelist_mode_flag', false);
script_whitelist_mode_flag = false;
message.success('已设置:<br><br>全匹配模式,即匹配所有网站!');
unsafeWindow.location.reload();
});
} else {
menu_item_mode = GM_registerMenuCommand('现在是全匹配模式(可点击切换到白名单模式)', function() {
GM_setValue('script_whitelist_mode_flag', true);
script_whitelist_mode_flag = true;
message.success('已设置:<br><br>白名单模式,即需要单个网站设置加入过滤名单!');
unsafeWindow.location.reload();
});
}
}
function check_menu_item_host_join() {
if (script_whitelist_mode_flag) {
if (the_current_host_in_whitelist_flag) {
initHook();
if (unsafeWindow.self === unsafeWindow.top) {
if (menu_item_host_join === null) {
filter_log('----------------------------脚本加载完成---------------------------');
filter_log('----------------------------还没 hookXHR---------------------------');
}
menu_item_host_join = GM_registerMenuCommand('本网站已开启过滤(可点击关闭广告过滤)', function() {
GM_setValue(the_current_host, false);
the_current_host_in_whitelist_flag = false;
message.success('已设置:<br><br>关闭本网站的广告过滤!');
unsafeWindow.location.reload();
});
}
} else {
if (unsafeWindow.self === unsafeWindow.top) {
if (menu_item_host_join === null) {
filter_log('----------------------------还没开启过滤---------------------------');
}
menu_item_host_join = GM_registerMenuCommand('本网站已关闭过滤(可点击开启广告过滤)', function() {
GM_setValue(the_current_host, true);
the_current_host_in_whitelist_flag = true;
message.success('已设置:<br><br>开启本网站的广告过滤!');
unsafeWindow.location.reload();
});
}
}
} else {
if (menu_item_host_join === null) {
filter_log('----------------------------脚本加载完成---------------------------');
filter_log('----------------------------还没 hookXHR---------------------------');
initHook();
}
}
}
function check_menu_item_toast() {
if (show_toast_tip_flag) {
if (unsafeWindow.self === unsafeWindow.top) {
menu_item_toast = GM_registerMenuCommand('已开启弹窗提示(可点击设置关闭)', function() {
GM_setValue('show_toast_tip_flag', false);
show_toast_tip_flag = false;
message.success('已设置:<br><br>关闭弹窗提示!');
add_menu_item_all();
});
}
} else {
if (unsafeWindow.self === unsafeWindow.top) {
menu_item_toast = GM_registerMenuCommand('已关闭弹窗提示(可点击设置开启)', function() {
GM_setValue('show_toast_tip_flag', true);
show_toast_tip_flag = true;
message.success('已设置:<br><br>开启弹窗提示!');
add_menu_item_all();
});
}
}
}
function register_menu_filter_done_tip() {
menu_item_filter_tip = GM_registerMenuCommand('提示:已成功过滤视频切片广告', function() {
Swal.fire({
title: '过滤日志',
type: 'info',
icon: 'info',
html: filter_log_html,
width: '50%',
showClass: {
popup: ''
},
hideClass: {
popup: ''
},
confirmButtonText: 'OK',
showCloseButton: true
});
});
}
function register_menu_filter_undone_tip() {
menu_item_filter_tip = GM_registerMenuCommand('提示:还没有过滤视频切片广告', function() {
Swal.fire({
type: 'info',
icon: 'info',
html: '过滤视频切片广告失败! <br><br> ctrl + F5 刷新试试 <br><br> 如果还不行,那说明:<br><br> 视频格式不是m3u8,无法过滤!',
showClass: {
popup: ''
},
hideClass: {
popup: ''
},
confirmButtonText: 'OK',
showCloseButton: true
});
});
}
function check_menu_item_filter_tip() {
if (filter_done_flag) {
register_menu_filter_done_tip();
} else {
if ((script_whitelist_mode_flag && the_current_host_in_whitelist_flag) || !script_whitelist_mode_flag) {
register_menu_filter_undone_tip();
}
}
}
function remove_menu_item_all() {
GM_unregisterMenuCommand(menu_item_violent);
GM_unregisterMenuCommand(menu_item_mode);
GM_unregisterMenuCommand(menu_item_host_join);
GM_unregisterMenuCommand(menu_item_toast);
}
function add_menu_item_all() {
remove_menu_item_all();
check_menu_item_violent();
check_menu_item_mode();
check_menu_item_host_join();
check_menu_item_toast();
}
add_menu_item_all();
function listen_video_load_meta() {
if ((script_whitelist_mode_flag && the_current_host_in_whitelist_flag) || !script_whitelist_mode_flag) {
let try_listen_video_meta_n = 0;
let try_to_add_listen_video_meta = function () {
let the_video_dom = unsafeWindow.document.querySelector('video');
if (the_video_dom) {
the_video_dom.addEventListener('loadedmetadata', () => {
setTimeout(function() {
if (!filter_done_flag) {
if (show_toast_tip_flag) {
message.warning('过滤失败!ctrl+F5 刷新试试,<br><br> 若还不行,说明播放视频格式<br>不是m3u8,无法过滤!');
}
GM_unregisterMenuCommand(menu_item_filter_tip);
check_menu_item_filter_tip();
}
}, 1000);
});
} else {
try_listen_video_meta_n++;
if (try_listen_video_meta_n < 50) {
setTimeout(try_to_add_listen_video_meta, 100);
}
}
}
try_to_add_listen_video_meta();
}
}
listen_video_load_meta();
})();