2023年8月1日发(作者:)

m3u8到底是什么格式?⼀篇⽂章搞定m3u8下载

注⼊代码 // 注⼊html let $section = Element('section') $TML = ` m3u8 downloader

页⾯加载中,请耐⼼等待...

推荐⼀个 m3u8 ⽹页版提取⼯具,⽆需下载软件,打开⽹站即可下载,⾃动检测,⼀键下载。 ⼯具链接:/tool-show/m3u8-downloader/ ⼯具教程:/a/1192?_ea=32289224

{{tips}}
? ⼿动添加油猴插件 github 其他实⽤⼯具 English version
测试链接:/0ef121cdvodtransgzp1257120875/3055695e5285891/v.f230.m3u8
下载完成
{{ isPause ? '恢复下载' : '暂停下载' }}
当⽆法下载,资源发⽣跨域限制时,在视频源页⾯打开控制台,注⼊代码解决,点击本按钮复制代码
下载的视频看不了?试试这个终结解决⽅案「⽆差别视频提取⼯具」,有配套「油猴」插件啦
` $ = '100%' $ = '800px' $ = '0' $ = '0' $on = 'relative' $ = '9999' $oundColor = 'white' Child($section); // 加载 ASE 解密 let $ase = Element('script') $ = '/tool-show/m3u8-downloader/' // 加载 mp4 转码 let $mp4 = Element('script') $ = '/tool-show/m3u8-downloader/' // 加载 vue let $vue = Element('script') $ = '/tool-show/m3u8-downloader/' // 监听 vue 加载完成,执⾏业务代码 $ntListener('load', () => {mentById('loading') && mentById('loading').remove()new Vue({ el: '#m-app', data() { return { url: '', // 在线链接 tips: 'm3u8 视频在线提取⼯具', // 顶部提⽰ isPause: false, // 是否暂停下载 isGetMP4: false, // 是否转码为 MP4 下载 durationSecond: 0, // 视频持续时长 isShowRefer: true, // 是否显⽰推送 downloading: false, // 是否下载中 beginTime: '', // 开始下载的时间 errorNum: 0, // 错误数 finishNum: 0, // 已下载数 downloadIndex: 0, // 当前下载⽚段 finishList: [], // 下载完成项⽬ tsUrlList: [], // ts URL数组 mediaFileList: [], // 下载的媒体数组 rangeDownload: { // 特定范围下载 isShowRange: false, // 是否显⽰范围下载 startSegment: '', // 起始⽚段 endSegment: '', // 截⽌⽚段 targetSegment: 1, // 待下载⽚段 }, aesConf: { // AES 视频解密配置 method: '', // 加密算法 uri: '', // key 所在⽂件路径 iv: '', // 偏移值 key: '', // 秘钥 decryptor: null, // 解码器对象 stringToBuffer: function (str) { return new TextEncoder().encode(str) }, }, } }, created() { rce(); ntListener('keyup', p) }, beforeDestroy() { EventListener('keyup', p) }, methods: { // 获取链接中携带的资源链接 getSource() { let { href } = location if (f('?source=') > -1) { = ('?source=')[1] } }, // 退出弹窗 onKeyup(event) { if (e === 13) { // 键⼊ESC 3U8() } }, // ajax 请求 ajax(options) { options = options || {}; let xhr = new XMLHttpRequest(); if ( === 'file') { seType = 'arraybuffer'; } ystatechange = function () { if (tate === 4) { let status = ; if (status >= 200 && status < 300) { s && s(se); } else { && (status); } } }; ("GET", , true); (null); }, // 合成URL applyURL(targetURL, baseURL) { baseURL = baseURL || if (f('http') === 0) { return targetURL } else if (targetURL[0] === '/') { let domain = ('/') return domain[0] + '//' + domain[2] + targetURL } else { let domain = ('/') () return ('/') + '/' + targetURL } }, // 解析为 mp4 下载 getMP4() { P4 = true 3U8() }, // 获取在线⽂件 getM3U8(onlyGetRange) { if (!) { alert('请输⼊链接') return } if (rCase().indexOf('.m3u8') === -1) { alert('链接有误,请重新输⼊') return } if (ading) { alert('资源下载中,请稍后') return } // 在下载页⾯才触发,代码注⼊的页⾯不需要校验 // 当前协议不⼀致,切换协议 if (f('') > -1 && f(ol) === -1) { //alert('当前协议不⼀致,跳转⾄正确页⾯重新下载') = `${(':')[0]}:///tool-show/m3u8-downloader/?source=${}` return } // 在下载页⾯才触发,修改页⾯ URL,携带下载路径,避免刷新后丢失 if (f('') > -1) { eState(null, '', `${('?')[0]}?source=${}`) } = 'm3u8 ⽂件下载中,请稍后' ime = new Date() ({ url: , success: (m3u8Str) => { ist = [] List = [] // 提取 ts 视频⽚段地址 ('n').forEach((item) => { if (rCase().indexOf('.ts') > -1 || rCase().indexOf('.image') > -1) { (RL(item, )) ({ title: item, status: '' }) } }) // 仅获取视频⽚段数 if (onlyGetRange) { Range = true ment = Segment = return } else { let startSegment = (egment || 1, 1) // 最⼩为 1 let endSegment = (ment || , 1) startSegment = (startSegment, ) // 最⼤为 endSegment = (endSegment, ) egment = (startSegment, endSegment) ment = (startSegment, endSegment) Segment = ment - egment + 1 adIndex = egment - 1 ading = true } // 获取需要下载的 MP4 视频长度 if (P4) { let infoIndex = 0 ('n').forEach(item => { if (rCase().indexOf('#EXTINF:') > -1) { // 计算视频总时长,设置 mp4 信息时使⽤ infoIndex++ if (egment <= infoIndex && infoIndex <= ment) { onSecond += parseFloat(('#EXTINF:')[1]) } } }) } // 检测视频 AES 加密 if (f('#EXT-X-KEY') > -1) { = ((/(.*METHOD=([^,s]+))/) || ['', '', ''])[2] = ((/(.*URI="([^"]+))"/) || ['', '', ''])[2] = ((/(.*IV=([^,s]+))/) || ['', '', ''])[2] = ? ToBuffer() : '' = RL(, ) // let params = (/#EXT-X-KEY:([^,]*,?METHOD=([^,]+))?([^,]*,?URI="([^,]+)")?([^,]*,?IV=([^,^n]+))?/) // = params[2] // = RL(params[4], ) // = params[6] ? ToBuffer(params[6]) : '' (); } else if ( > 0) { // 如果视频没加密,则直接下载⽚段,否则先下载秘钥 adTS() } else { rror('资源为空,请查看链接是否有效') } }, fail: () => { rror('链接不正确,请查看链接是否有效') } }) }, // 获取AES配置 getAES() { alert('视频被 AES 加密,点击确认,进⾏视频解码') ({ type: 'file', url: , success: (key) => { // ('getAES', key) // = ToBuffer(key) = key tor = new AESDecryptor() uctor() Key(); adTS() }, fail: () => { rror('视频已进⾏定制化加密,不提供定制化解密下载') } }) }, // ts ⽚段的 AES 解码 aesDecrypt(data, index) { let iv = || new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, index]) return t(data, 0, || iv, true) }, // 下载分⽚ downloadTS() { = 'ts 视频碎⽚下载中,请稍后' let download = () => { let isPause = e // 使⽤另⼀个变量来保持下载前的暂停状态,避免回调后没修改 let index = adIndex adIndex++ if (List[index] && List[index].status === '') { ({ url: ist[index], type: 'file', success: (file) => { (file, index, () => adIndex < ment && !isPause && download()) }, fail: () => { um++ List[index].status = 'error' if (adIndex < ment) { !isPause && download() } } }) } else if (adIndex < ment) { // 跳过已经成功的⽚段 !isPause && download() } } // 建⽴多少个 ajax 线程 for (let i = 0; i < (10, Segment - Num); i++) { download(i) } }, // 处理 ts ⽚段,AES 解密、mp4 转码 dealTS(file, index, callback) { const data = ? rypt(file, index) : file sionMp4(data, index, (afterData) => { // mp4 转码 ileList[index - egment + 1] = afterData // 判断⽂件是否需要解密 List[index].status = 'finish' Num++ if (Num === Segment) { adFile(ileList, Time(ime, 'YYYY_MM_DD hh_mm_ss')) } callback && callback() }) }, // 转码为 mp4 conversionMp4(data, index, callback) { if (P4) { let transmuxer = new uxer({ keepOriginalTimestamps: true, duration: parseInt(onSecond), }); ('data', segment => { if (index === egment - 1) { let data = new Uint8Array(ngth + ngth); (gment, 0); (, ngth); callback() } else { callback() } }) (new Uint8Array(data)); (); } else { callback(data) } }, // 暂停与恢复 togglePause() { e = !e !e && ll() }, // 重新下载某个⽚段 retry(index) { if (List[index].status === 'error') { List[index].status = '' ({ url: ist[index], type: 'file', success: (file) => { um-- (file, index) }, fail: () => { List[index].status = 'error' } }) } }, // 重新下载所有错误⽚段 retryAll() { h((item) => { // 重置所有⽚段状态 if ( === 'error') { = '' } }) um = 0 adIndex = egment - 1 adTS() }, // 下载整合后的TS⽂件 downloadFile(fileDataList, fileName) { = 'ts 碎⽚整合中,请留意浏览器下载' let fileBlob = null let a = Element('a') if (P4) { fileBlob = new Blob(fileDataList, { type: 'video/mp4' }) // 创建⼀个Blob对象,并设置⽂件的 MIME 类型 ad = fileName + '.mp4' } else { fileBlob = new Blob(fileDataList, { type: 'video/MP2T' }) // 创建⼀个Blob对象,并设置⽂件的 MIME 类型 ad = fileName + '.ts' } = ObjectURL(fileBlob) y = 'none' Child(a) () () }, // 格式化时间 formatTime(date, formatStr) { const formatType = { Y: lYear(), M: th() + 1, D: e(), h: rs(), m: utes(), s: onds(), } return e( /Y+|M+|D+|h+|m+|s+/g, target => (new Array().join('0') + formatType[target[0]]).substr(-) ) }, // 强制下载现有⽚段 forceDownload() { if () { adFile(ileList, Time(ime, 'YYYY_MM_DD hh_mm_ss')) } else { alert('当前⽆已下载⽚段') } }, // 发⽣错误,进⾏提⽰ alertError(tips) { alert(tips) ading = false = 'm3u8 视频在线提取⼯具'; }, // 拷贝本页⾯本⾝,解决跨域问题 copyCode() { if ( !== '代码下载中,请稍后') { = '代码下载中,请稍后'; ({ url: './', success: (fileStr) => { let fileList = (``); let dom = fileList[0]; let script = fileList[1] + fileList[2]; script = (''); script = script[1] + script[2]; if () { script = e(`url: '', // 在线链接`, `url: '${}',`); } let codeStr = ` // 注⼊html let $section = Element('section') $TML = `${dom}` $ = '100%' $ = '800px' $ = '0' $ = '0' $on = 'relative' $ = '9999' $oundColor = 'white' Child($section); // 加载 ASE 解密 let $ase = Element('script') $ = '/tool-show/m3u8-downloader/' // 加载 mp4 转码 let $mp4 = Element('script') $ = '/tool-show/m3u8-downloader/' // 加载 vue let $vue = Element('script') $ = '/tool-show/m3u8-downloader/' // 监听 vue 加载完成,执⾏业务代码 $ntListener('load', () => {${script}}) Child($vue); Child($mp4); Child($ase); alert('注⼊成功,请滚动到页⾯底部,若⽩屏则等待资源加载') `; Clipboard(codeStr); = '复制成功,打开视频⽹页控制台,注⼊本代码'; }, fail: () => { rror('链接不正确,请查看链接是否有效'); }, }) } }, // 拷贝剪切板 copyToClipboard(content) { clearTimeout(ter) if (!ommandSupported('copy')) { return false } let $input = Element('textarea') $y = '0' $ = content Child($input) $() const result = mmand('copy') Child($input) $input = null return result }, }})}) Child($vue); Child($mp4); Child($ase); alert('注⼊成功,请滚动到页⾯底部,若⽩屏则等待资源加载')

  

2023年8月1日发(作者:)

m3u8到底是什么格式?⼀篇⽂章搞定m3u8下载

注⼊代码 // 注⼊html let $section = Element('section') $TML = ` m3u8 downloader

页⾯加载中,请耐⼼等待...

推荐⼀个 m3u8 ⽹页版提取⼯具,⽆需下载软件,打开⽹站即可下载,⾃动检测,⼀键下载。 ⼯具链接:/tool-show/m3u8-downloader/ ⼯具教程:/a/1192?_ea=32289224

{{tips}}
? ⼿动添加油猴插件 github 其他实⽤⼯具 English version
测试链接:/0ef121cdvodtransgzp1257120875/3055695e5285891/v.f230.m3u8
下载完成
{{ isPause ? '恢复下载' : '暂停下载' }}
当⽆法下载,资源发⽣跨域限制时,在视频源页⾯打开控制台,注⼊代码解决,点击本按钮复制代码
下载的视频看不了?试试这个终结解决⽅案「⽆差别视频提取⼯具」,有配套「油猴」插件啦
` $ = '100%' $ = '800px' $ = '0' $ = '0' $on = 'relative' $ = '9999' $oundColor = 'white' Child($section); // 加载 ASE 解密 let $ase = Element('script') $ = '/tool-show/m3u8-downloader/' // 加载 mp4 转码 let $mp4 = Element('script') $ = '/tool-show/m3u8-downloader/' // 加载 vue let $vue = Element('script') $ = '/tool-show/m3u8-downloader/' // 监听 vue 加载完成,执⾏业务代码 $ntListener('load', () => {mentById('loading') && mentById('loading').remove()new Vue({ el: '#m-app', data() { return { url: '', // 在线链接 tips: 'm3u8 视频在线提取⼯具', // 顶部提⽰ isPause: false, // 是否暂停下载 isGetMP4: false, // 是否转码为 MP4 下载 durationSecond: 0, // 视频持续时长 isShowRefer: true, // 是否显⽰推送 downloading: false, // 是否下载中 beginTime: '', // 开始下载的时间 errorNum: 0, // 错误数 finishNum: 0, // 已下载数 downloadIndex: 0, // 当前下载⽚段 finishList: [], // 下载完成项⽬ tsUrlList: [], // ts URL数组 mediaFileList: [], // 下载的媒体数组 rangeDownload: { // 特定范围下载 isShowRange: false, // 是否显⽰范围下载 startSegment: '', // 起始⽚段 endSegment: '', // 截⽌⽚段 targetSegment: 1, // 待下载⽚段 }, aesConf: { // AES 视频解密配置 method: '', // 加密算法 uri: '', // key 所在⽂件路径 iv: '', // 偏移值 key: '', // 秘钥 decryptor: null, // 解码器对象 stringToBuffer: function (str) { return new TextEncoder().encode(str) }, }, } }, created() { rce(); ntListener('keyup', p) }, beforeDestroy() { EventListener('keyup', p) }, methods: { // 获取链接中携带的资源链接 getSource() { let { href } = location if (f('?source=') > -1) { = ('?source=')[1] } }, // 退出弹窗 onKeyup(event) { if (e === 13) { // 键⼊ESC 3U8() } }, // ajax 请求 ajax(options) { options = options || {}; let xhr = new XMLHttpRequest(); if ( === 'file') { seType = 'arraybuffer'; } ystatechange = function () { if (tate === 4) { let status = ; if (status >= 200 && status < 300) { s && s(se); } else { && (status); } } }; ("GET", , true); (null); }, // 合成URL applyURL(targetURL, baseURL) { baseURL = baseURL || if (f('http') === 0) { return targetURL } else if (targetURL[0] === '/') { let domain = ('/') return domain[0] + '//' + domain[2] + targetURL } else { let domain = ('/') () return ('/') + '/' + targetURL } }, // 解析为 mp4 下载 getMP4() { P4 = true 3U8() }, // 获取在线⽂件 getM3U8(onlyGetRange) { if (!) { alert('请输⼊链接') return } if (rCase().indexOf('.m3u8') === -1) { alert('链接有误,请重新输⼊') return } if (ading) { alert('资源下载中,请稍后') return } // 在下载页⾯才触发,代码注⼊的页⾯不需要校验 // 当前协议不⼀致,切换协议 if (f('') > -1 && f(ol) === -1) { //alert('当前协议不⼀致,跳转⾄正确页⾯重新下载') = `${(':')[0]}:///tool-show/m3u8-downloader/?source=${}` return } // 在下载页⾯才触发,修改页⾯ URL,携带下载路径,避免刷新后丢失 if (f('') > -1) { eState(null, '', `${('?')[0]}?source=${}`) } = 'm3u8 ⽂件下载中,请稍后' ime = new Date() ({ url: , success: (m3u8Str) => { ist = [] List = [] // 提取 ts 视频⽚段地址 ('n').forEach((item) => { if (rCase().indexOf('.ts') > -1 || rCase().indexOf('.image') > -1) { (RL(item, )) ({ title: item, status: '' }) } }) // 仅获取视频⽚段数 if (onlyGetRange) { Range = true ment = Segment = return } else { let startSegment = (egment || 1, 1) // 最⼩为 1 let endSegment = (ment || , 1) startSegment = (startSegment, ) // 最⼤为 endSegment = (endSegment, ) egment = (startSegment, endSegment) ment = (startSegment, endSegment) Segment = ment - egment + 1 adIndex = egment - 1 ading = true } // 获取需要下载的 MP4 视频长度 if (P4) { let infoIndex = 0 ('n').forEach(item => { if (rCase().indexOf('#EXTINF:') > -1) { // 计算视频总时长,设置 mp4 信息时使⽤ infoIndex++ if (egment <= infoIndex && infoIndex <= ment) { onSecond += parseFloat(('#EXTINF:')[1]) } } }) } // 检测视频 AES 加密 if (f('#EXT-X-KEY') > -1) { = ((/(.*METHOD=([^,s]+))/) || ['', '', ''])[2] = ((/(.*URI="([^"]+))"/) || ['', '', ''])[2] = ((/(.*IV=([^,s]+))/) || ['', '', ''])[2] = ? ToBuffer() : '' = RL(, ) // let params = (/#EXT-X-KEY:([^,]*,?METHOD=([^,]+))?([^,]*,?URI="([^,]+)")?([^,]*,?IV=([^,^n]+))?/) // = params[2] // = RL(params[4], ) // = params[6] ? ToBuffer(params[6]) : '' (); } else if ( > 0) { // 如果视频没加密,则直接下载⽚段,否则先下载秘钥 adTS() } else { rror('资源为空,请查看链接是否有效') } }, fail: () => { rror('链接不正确,请查看链接是否有效') } }) }, // 获取AES配置 getAES() { alert('视频被 AES 加密,点击确认,进⾏视频解码') ({ type: 'file', url: , success: (key) => { // ('getAES', key) // = ToBuffer(key) = key tor = new AESDecryptor() uctor() Key(); adTS() }, fail: () => { rror('视频已进⾏定制化加密,不提供定制化解密下载') } }) }, // ts ⽚段的 AES 解码 aesDecrypt(data, index) { let iv = || new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, index]) return t(data, 0, || iv, true) }, // 下载分⽚ downloadTS() { = 'ts 视频碎⽚下载中,请稍后' let download = () => { let isPause = e // 使⽤另⼀个变量来保持下载前的暂停状态,避免回调后没修改 let index = adIndex adIndex++ if (List[index] && List[index].status === '') { ({ url: ist[index], type: 'file', success: (file) => { (file, index, () => adIndex < ment && !isPause && download()) }, fail: () => { um++ List[index].status = 'error' if (adIndex < ment) { !isPause && download() } } }) } else if (adIndex < ment) { // 跳过已经成功的⽚段 !isPause && download() } } // 建⽴多少个 ajax 线程 for (let i = 0; i < (10, Segment - Num); i++) { download(i) } }, // 处理 ts ⽚段,AES 解密、mp4 转码 dealTS(file, index, callback) { const data = ? rypt(file, index) : file sionMp4(data, index, (afterData) => { // mp4 转码 ileList[index - egment + 1] = afterData // 判断⽂件是否需要解密 List[index].status = 'finish' Num++ if (Num === Segment) { adFile(ileList, Time(ime, 'YYYY_MM_DD hh_mm_ss')) } callback && callback() }) }, // 转码为 mp4 conversionMp4(data, index, callback) { if (P4) { let transmuxer = new uxer({ keepOriginalTimestamps: true, duration: parseInt(onSecond), }); ('data', segment => { if (index === egment - 1) { let data = new Uint8Array(ngth + ngth); (gment, 0); (, ngth); callback() } else { callback() } }) (new Uint8Array(data)); (); } else { callback(data) } }, // 暂停与恢复 togglePause() { e = !e !e && ll() }, // 重新下载某个⽚段 retry(index) { if (List[index].status === 'error') { List[index].status = '' ({ url: ist[index], type: 'file', success: (file) => { um-- (file, index) }, fail: () => { List[index].status = 'error' } }) } }, // 重新下载所有错误⽚段 retryAll() { h((item) => { // 重置所有⽚段状态 if ( === 'error') { = '' } }) um = 0 adIndex = egment - 1 adTS() }, // 下载整合后的TS⽂件 downloadFile(fileDataList, fileName) { = 'ts 碎⽚整合中,请留意浏览器下载' let fileBlob = null let a = Element('a') if (P4) { fileBlob = new Blob(fileDataList, { type: 'video/mp4' }) // 创建⼀个Blob对象,并设置⽂件的 MIME 类型 ad = fileName + '.mp4' } else { fileBlob = new Blob(fileDataList, { type: 'video/MP2T' }) // 创建⼀个Blob对象,并设置⽂件的 MIME 类型 ad = fileName + '.ts' } = ObjectURL(fileBlob) y = 'none' Child(a) () () }, // 格式化时间 formatTime(date, formatStr) { const formatType = { Y: lYear(), M: th() + 1, D: e(), h: rs(), m: utes(), s: onds(), } return e( /Y+|M+|D+|h+|m+|s+/g, target => (new Array().join('0') + formatType[target[0]]).substr(-) ) }, // 强制下载现有⽚段 forceDownload() { if () { adFile(ileList, Time(ime, 'YYYY_MM_DD hh_mm_ss')) } else { alert('当前⽆已下载⽚段') } }, // 发⽣错误,进⾏提⽰ alertError(tips) { alert(tips) ading = false = 'm3u8 视频在线提取⼯具'; }, // 拷贝本页⾯本⾝,解决跨域问题 copyCode() { if ( !== '代码下载中,请稍后') { = '代码下载中,请稍后'; ({ url: './', success: (fileStr) => { let fileList = (``); let dom = fileList[0]; let script = fileList[1] + fileList[2]; script = (''); script = script[1] + script[2]; if () { script = e(`url: '', // 在线链接`, `url: '${}',`); } let codeStr = ` // 注⼊html let $section = Element('section') $TML = `${dom}` $ = '100%' $ = '800px' $ = '0' $ = '0' $on = 'relative' $ = '9999' $oundColor = 'white' Child($section); // 加载 ASE 解密 let $ase = Element('script') $ = '/tool-show/m3u8-downloader/' // 加载 mp4 转码 let $mp4 = Element('script') $ = '/tool-show/m3u8-downloader/' // 加载 vue let $vue = Element('script') $ = '/tool-show/m3u8-downloader/' // 监听 vue 加载完成,执⾏业务代码 $ntListener('load', () => {${script}}) Child($vue); Child($mp4); Child($ase); alert('注⼊成功,请滚动到页⾯底部,若⽩屏则等待资源加载') `; Clipboard(codeStr); = '复制成功,打开视频⽹页控制台,注⼊本代码'; }, fail: () => { rror('链接不正确,请查看链接是否有效'); }, }) } }, // 拷贝剪切板 copyToClipboard(content) { clearTimeout(ter) if (!ommandSupported('copy')) { return false } let $input = Element('textarea') $y = '0' $ = content Child($input) $() const result = mmand('copy') Child($input) $input = null return result }, }})}) Child($vue); Child($mp4); Child($ase); alert('注⼊成功,请滚动到页⾯底部,若⽩屏则等待资源加载')