上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

通过处理m3u8文件来实现去除网站的视频内置广告

[复制链接]
  • TA的每日心情

    5 天前
  • 签到天数: 247 天

    [LV.8]以坛为家I

    4

    主题

    20

    回帖

    179

    积分

    中级工程师

    积分
    179

    挑战者 lv2

    发表于 2024-6-13 20:14:37 | 显示全部楼层 | 阅读模式

    本帖最后由 yhzc2023 于 2024-6-13 20:23 编辑

    介绍m3u8格式

    M3U8是一种用于播放视频流的文件格式,它被广泛应用于互联网视频流媒体服务。简单来说,m3u8文件是一种文本文件,里面列出了视频的各个部分(通常是.ts文件)的地址。播放器通过读取m3u8文件,按顺序播放这些视频片段,从而实现流畅的视频播放。

    m3u8文件的结构

    一个典型的m3u8文件包含如下内容:

    • #EXTM3U:文件的标识符,表示这是一个m3u8文件。
    • #EXTINF:<duration>,<title>每个视频片段的时长(以秒为单位)和可选的标题。(重点关注)
    • .ts文件路径视频片段的具体文件路径。(重点关注)
    • #EXT-X-VERSION:<n>:播放列表文件的版本号。
    • #EXT-X-TARGETDURATION:<s>:播放列表中最长媒体段的时长(以秒为单位)。
    • #EXT-X-MEDIA-SEQUENCE:<number>:播放列表中第一个媒体段的序列号。
    • #EXT-X-DISCONTINUITY指示播放列表中的不连续点,通常用于不同编码的片段之间的过渡。(重点关注)
    • #EXT-X-KEY:指定用于解密媒体段的密钥。
    • #EXT-X-ENDLIST:指示播放列表的结束。

    例子:

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:10
    #EXT-X-MEDIA-SEQUENCE:0
    #EXTINF:10.0,
    segment0.ts
    #EXTINF:10.0,
    segment1.ts
    #EXT-X-DISCONTINUITY
    #EXTINF:10.0,
    segment2.ts
    #EXT-X-ENDLIST

    在这个例子中,播放器会依次播放 segment0.tssegment1.tssegment2.ts 这三个视频片段,每个片段的播放时长为10秒。#EXT-X-DISCONTINUITY 指示播放器在播放 segment1.tssegment2.ts 之间有一个不连续点,通常用于处理不同编码或不同来源的片段之间的过渡。

    脚本实现原理

    目的是去除m3u8视频中的广告段。通过hook xhr或者fetch获取m3u8文件,然后解析m3u8文件,删除那些不需要的广告片段,然后重新生成一个干净的m3u8文件。由于大部分视频网站为了不修改视频源文件,是不会将广告视频和普通视频整合成一个新的视频。这样通常会在m3u8文件里表现出普通视频片段和广告片段的文件名称不一致。脚本的工作原理是基于普通视频片段和广告片段的文件名称不一致。如果广告片段和普通视频片段的文件名称遵循相同的命名规则,本脚本将无法有效区分和删除广告片段。因此,适用此脚本的前提是广告片段的文件名称与普通视频片段的文件名称有明显的区别。
    1.png

    代码实现

    以下是实现去除m3u8视频广告的JavaScript代码:

    let lines = file.split('\n');
    let processed_lines = [];
    let index = 0;
    let name_len;
    let pre_name;
    let next_name;
    
    for (let line of lines) {
        if (line.endsWith('.ts')) {
            if (!next_name) {
                pre_name = line.split('.ts')[0];
                name_len = pre_name.length;
                index++;
                const str_index = String(index);
                next_name = `${pre_name.substring(0, name_len - str_index.length)}${str_index}.ts`;
            } else {
                if (next_name != line) {
                    processed_lines.pop();
                    if (processed_lines[processed_lines.length - 1] == '#EXT-X-DISCONTINUITY') {
                        processed_lines.pop();
                    }
                    log(`删除${line}`);
                    continue;
                } else {
                    index++;
                    const str_index = String(index);
                    next_name = `${pre_name.substring(0, name_len - str_index.length)}${str_index}.ts`;
                }
            }
        }
        processed_lines.push(line);
    }
    
    let processed_file = processed_lines.join('\n');
    return processed_file;

    详细解释

    1. 文件拆分: 首先,将m3u8文件的内容按行拆分成数组 lines
    2. 初始化变量: 初始化一些变量用于处理文件行,如 processed_linesindexname_lenpre_namenext_name
    3. 处理每一行:
      • 如果行以 .ts 结尾,表示这是一个视频片段。
      • 检查是否有 next_name:
        • 如果没有,初始化 pre_namename_len,并生成 next_name
        • 如果有,比较 next_name 和当前行:
        • 如果不同,移除最后一行 processed_lines(最后一行是#EXTINF标识),并检查是否有 #EXT-X-DISCONTINUITY,如有则一并移除,并记录日志。
        • 如果相同,更新 indexnext_name
    4. 生成新的m3u8文件: 将处理后的行重新组合成字符串 processed_file 并返回。

    关于 #EXT-X-DISCONTINUITY

    #EXT-X-DISCONTINUITY 标签用于指示播放列表中的不连续点,通常出现在不同编码或不同来源的片段之间。它告知播放器在播放这些片段时需要处理潜在的编码变化或其他不连续性,上面代码不删除的话,会可能连续出现两个#EXT-X-DISCONTINUITY标识,这样会导致播放到这位置的时候卡顿。

    在本脚本中,当删除一个广告片段时,如果它前面紧挨着 #EXT-X-DISCONTINUITY 标签,这意味着原来这个标签是用来处理广告段的过渡。由于广告段被移除,这个标签就没有存在的必要了,因此脚本会将它一并删除,确保生成的m3u8文件的连续性和完整性。

    注意

    上面的代码修改代码不是一个通用的去除广告代码。m3u8格式是大同小异,里面视频的名称格式可能会不一样,需要按照实际的文件进行微调。
    给两个网站大家可以去看看 一个是 粤语屋 看港剧的 在8分钟前后会出现广告。 一个是优酷 电视剧好像在2分钟左右出现广告。重点再提一下,去除的不是弹窗广告这些,测试优酷·最好有个会员,不然前面的非会员的倒计时广告会烦死。
    脚本我放在下方,大家有兴趣的可以去看一下
    脚本

    最后

    有没有大佬出手去折腾一下爱奇艺。爱奇艺也是用m3u8来播放的,不过它广告和视频是整合到一起的,从视频名称上区分不出来,所以没办法这样去除。不过也有个思路就是hook addSourceBuffer方法,获取一帧图像,然后通过识别图像里是否存在广告标识,存在就不要这一段视频数据。等一个有爱奇艺会员的大佬去试试,真实现了,请跟我说一声,让我去观摩一下。

  • TA的每日心情
    开心
    昨天 20:19
  • 签到天数: 648 天

    [LV.9]以坛为家II

    69

    主题

    503

    回帖

    786

    积分

    专家

    脚本猫首席体验官

    积分
    786

    油中2周年生态建设者新人报道油中3周年挑战者 lv2喜迎中秋

    发表于 2024-6-13 22:28:53 | 显示全部楼层
    ggnb!
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 23:59
  • 签到天数: 191 天

    [LV.7]常住居民III

    687

    主题

    5424

    回帖

    6362

    积分

    管理员

    非物质文化遗产社会摇传承人

    积分
    6362

    荣誉开发者管理员油中2周年生态建设者喜迎中秋

    发表于 2024-6-14 06:31:10 | 显示全部楼层
    硬核,第一次学到
    思路好棒!
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道

    入驻了爱发电https://afdian.net/a/lihengdao666
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情

    5 天前
  • 签到天数: 247 天

    [LV.8]以坛为家I

    4

    主题

    20

    回帖

    179

    积分

    中级工程师

    积分
    179

    挑战者 lv2

    发表于 2024-6-14 12:13:35 | 显示全部楼层
    李恒道 发表于 2024-6-14 06:31
    硬核,第一次学到
    思路好棒!

    谢谢哥哥佳境
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    回帖

    2

    积分

    助理工程师

    积分
    2
    发表于 2024-6-24 16:46:45 | 显示全部楼层
    大佬,能不能不运行脚本,直接js注入呢
    回复

    使用道具 举报

  • TA的每日心情

    5 天前
  • 签到天数: 247 天

    [LV.8]以坛为家I

    4

    主题

    20

    回帖

    179

    积分

    中级工程师

    积分
    179

    挑战者 lv2

    发表于 2024-6-24 17:44:17 | 显示全部楼层
    liudong1 发表于 2024-6-24 16:46
    大佬,能不能不运行脚本,直接js注入呢

    油猴脚本不就是注入?你还需要哪一种注入?
    回复

    使用道具 举报

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表