手撸一个M3U8下载插件

M3U8嗅探下载

思路与核心代码

基本思路

​ M3U8视频格式是一种基于HTTP Live Streaming(HLS)协议的视频文件格式。它是苹果公司开发的,目前广泛应用于iOS、macOS和tvOS等系统中。与传统的视频格式不同,M3U8视频格式将整个视频分成多个小片段进行传输,这些小片段可以根据网络情况自动调节其质量和大小。这种方式使得M3U8视频格式非常适合在网络环境不稳定或带宽不足的情况下播放视频。

​ 示例-1就是一个m3u8文件的内容截取,一个个的ts文件就是一个个小的视频片段,所以我们拿到m3u8文件并解析内容之后,将一个个ts文件合并到一起就是完整的视频。浏览器 chrome.webRequest API 可以观察和分析流量,以及拦截、屏蔽或修改运行中的请求。我们可以用它来嗅探网页中的m3u8文件地址。

示例 - 1:m3u8文件内容

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:8
#EXT-X-DISCONTINUITY

#EXTINF:4.000000,
cf645dad0e2000000.ts
#EXTINF:4.000000,
cf645dad0e2000001.ts
#EXTINF:4.000000,
cf645dad0e2000002.ts
#EXTINF:4.000000,
cf645dad0e2000003.ts

#EXT-X-ENDLIST

示例 - 2 :嗅探文件请求

var caches = {};
chrome.webRequest.onCompleted.addListener(function(details){
    let rul = details.url;
    let type = details.type;
    let documentId = details.documentId;
    if(type == 'xmlhttprequest'){
        let suffix = rul.substr(rul.lastIndexOf('\.'));
        if(suffix == '.m3u8'){
            if(!caches[documentId]){
                caches[documentId] = {list:[]};
            }
            caches[documentId].list.push(rul);
        }
    }
}, {urls: ["<all_urls>"]}, []);
  • 使用 chrome.webRequest API监听网络请求完成事件,当请求的是m3u8文件时记录请求路径。

示例 - 3 :解析m3u8并缓存ts

function cacheFile(tabId,index,url) {
    fetch(url)
    .then(response => {
       return response.text()
    })
    .then(data => {
        let lines = data.trim().split("\n");
        let files = lines.filter(line => line.trim().endsWith('.ts'));  // 需要缓存的文件列表 
        let baseUrl = url.substring(0,url.lastIndexOf('\/'));           // 缓存视频的基本路径
        let fileSize = 0;                                               // 已经缓存的文件数量
        files.forEach((fileName,x)=>{
            fetch(baseUrl+"/"+fileName)
            .then(response => {
                return response.blob();
            })
            .then(blob => {
                let reader = new FileReader();
                reader.onloadend = function() {
                    let key = tabId+""+index+""+x;
                    chrome.storage.local.set({ [key] : reader.result }).then(() => {
                        fileSize = fileSize+1;
                        console.log("进度:"+fileSize+"/"+files.length);
                        if(fileSize==files.length){                     // 全部缓存之后,通知合并下载
                            chrome.tabs.sendMessage(tabId,{ command: 'download', 
                                                           tabId:tabId, index:index, fileSize:fileSize });
                        }else{                                          // 更新进度
                            chrome.tabs.sendMessage(tabId,{ command: 'update-cache-progress', tabId:tabId, 
                                                           progress:fileSize, fileSize:files.length });
                        }
                    });
                };
                reader.readAsDataURL(blob);
            })
            .catch((err) => {
                console.error("缓存异常:["+baseUrl+"/"+fileName+"]"+err);
            });
        });
    });
}

示例 - 4 :环形进度条

<svg id="progressSVG" width="80" height="80">
  <circle cx="40" cy="40" r="30" fill="none" stroke="#ddd" stroke-width="5" />
  <circle class="progress" cx="40" cy="40" r="30" fill="none" 
          stroke="#0f0" 
          stroke-width="5" 
          stroke-dasharray="188.5" 
          stroke-dashoffset="190.9"/>
  <text x="50%" y="50%" text-anchor="middle" dy=".3em" font-size="12">0%</text>
</svg>
  • 两个空心圆,第二个空心圆通过stroke、stroke-width、stroke-dasharray、stroke-dashoffset定义了轮廓,通过更新stroke-dashoffset使其绿色轮廓覆盖第一个空心圆,就实现了一个简单的环形进度条。

效果体验

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值