您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自用,拦截和过滤 m3u8(解析/采集资源) 的切片(插播)广告,同时在console打印过滤的行信息,不会误删。
// ==UserScript== // @name M3U8 Filter Ad Script // @namespace http://tampermonkey.net/ // @version 1.3.2 // @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-相关 if (i > 0 && lines[i - 1].startsWith('#EXT-X-')) { 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) { if (the_video_dom.src.indexOf('.mp4') > 0) { message.error('过滤失败!<br><br>播放视频格式是mp4 <br><br>不是m3u8,无法过滤!'); } else { 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(); })();