您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
拦截m3u8请求并移除其中插入的广告ts片段
// ==UserScript== // @name Remove Ad from M3U8 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 拦截m3u8请求并移除其中插入的广告ts片段 // @author // @match *://*/* // @grant none // ==/UserScript== (function() { 'use strict'; let processingM3U8 = false; async function fixAdM3u8Ai(m3u8_url, headers = null){ let ts = new Date().getTime(); let option = headers ? {headers: headers} : {}; function b(s1, s2) { let i = 0; while (i < s1.length) { if (s1[i] !== s2[i]) { break } i++ } return i; } function reverseString(str) { return str.split('').reverse().join(''); } //log('播放的地址:' + m3u8_url); const m3u8_response = await fetch(m3u8_url, option); let m3u8 =await m3u8_response.text(); //log('m3u8处理前:' + m3u8); m3u8 = m3u8.trim().split('\n').map(it => it.startsWith('#') ? it : urljoin(m3u8_url, it)).join('\n'); //log('m3u8处理后:============:' + m3u8); // 获取嵌套m3u8地址 m3u8 = m3u8.replace(/\n\n/gi, '\n'); //删除多余的换行符 let last_url = m3u8.split('\n').slice(-1)[0]; if (last_url.length < 5) { last_url = m3u8.split('\n').slice(-2)[0]; } if (last_url.includes('.m3u8') && last_url !== m3u8_url) { m3u8_url = urljoin(m3u8_url, last_url); // console.log('嵌套的m3u8_url:' + m3u8_url); const m3u8_nest_response = await fetch(m3u8_url, option); m3u8 = await m3u8_nest_response.text(); } //log('----处理有广告的地址----'); let s = m3u8.trim().split('\n').filter(it => it.trim()).join('\n'); let ss = s.split('\n'); //找出第一条播放地址 //let firststr = ss.find(x => !x.startsWith('#')); let firststr = ''; let maxl = 0;//最大相同字符 let kk = 0; let kkk = 2; let secondstr = ''; for (let i = 0; i < ss.length; i++) { let s = ss[i]; if (!s.startsWith("#")) { if (kk == 0) firststr = s; if (kk == 1) maxl = b(firststr, s); if (kk > 1) { if (maxl > b(firststr, s)) { if (secondstr.length < 5) secondstr = s; kkk = kkk + 2; } else { maxl = b(firststr, s); kkk++; } } kk++; if (kk >= 20) break; } } if (kkk > 30) firststr = secondstr; let firststrlen = firststr != null ? firststr.length : null //log('字符串长度:' + firststrlen); let ml = Math.round(ss.length / 2).toString().length; //取数据的长度的位数 //log('数据条数的长度:' + ml); //找出最后一条播放地址 let maxc = 0; let laststr = ss.toReversed().find((x) => { if (!x.startsWith('#')) { let k = b(reverseString(firststr), reverseString(x)); maxl = b(firststr, x); maxc++; if (firststrlen - maxl <= ml + k || maxc > 10) { return true; } } return false; }); // console.log('最后一条切片:' + laststr); //log('最小相同字符长度:' + maxl); let ad_urls = []; for (let i = 0; i < ss.length; i++) { let s = ss[i]; if (!s.startsWith('#')) { if (b(firststr, s) < maxl) { ad_urls.push(s); // 广告地址加入列表 ss.splice(i - 1, 2); i = i - 2; } else { ss[i] = urljoin(m3u8_url, s); } } else { ss[i] = s.replace(/URI=\"(.*)\"/, 'URI="' + urljoin(m3u8_url, '$1') + '"'); } } // console.log('处理的m3u8地址:' + m3u8_url); // console.log('----广告地址----'); console.log(ad_urls); m3u8 = ss.join('\n'); //log('处理完成'); //console.log('处理耗时:' + (new Date().getTime() - ts).toString()); return m3u8; } function resolve (from, to){ const resolvedUrl = new URL(to, new URL(from, 'resolve://')); if (resolvedUrl.protocol === 'resolve:') { const { pathname, search, hash } = resolvedUrl; return pathname + search + hash; } return resolvedUrl.href; }; function urljoin (fromPath, nowPath){ fromPath = fromPath || ''; nowPath = nowPath || ''; return resolve(fromPath, nowPath); }; function playm3u8(urlm3,playerElement) { if (Hls.isSupported()) { var hls = new Hls(); hls.loadSource(urlm3); hls.attachMedia(playerElement); //video.play(); hls.on(Hls.Events.MANIFEST_PARSED, function () { playerElement.play(); }); hls.on(Hls.Events.ERROR, (event, data) => { //console.log("1222"); console.log(event, data); // 监听出错事件 }); } } function replacePlayerSource(playerElement, newSource) { // 假设播放器使用 <video> 或类似标签 if (playerElement) { playm3u8(newSource,playerElement) } else { console.warn('Player element not found.'); } } const originalXhrOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { if (url.endsWith('.m3u8')) { this.addEventListener('load', async function() { if (!processingM3U8 && (this.responseType === '' || this.responseType === 'text')) { processingM3U8 = true; const m3u8_content = await fixAdM3u8Ai(url); processingM3U8 = false; // 创建 Blob 并生成 URL const blob = new Blob([m3u8_content], { type: 'text/plain' }); const newM3u8Url = URL.createObjectURL(blob); // 替换播放器源 const player = document.querySelector('video'); // 根据实际情况调整选择器 replacePlayerSource(player,newM3u8Url); } }); } originalXhrOpen.apply(this, arguments); }; })();