Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

允许手动输入aes的key地址 #17

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# m3u8 视频在线提取工具

![界面](http://upyun.luckly-mjw.cn/Assets/m3u8-download/01.jpeg)
### [工具在线地址](http://blog.luckly-mjw.cn/tool-show/m3u8-downloader/index.html),推荐使用 chrome 浏览器。
### [工具在线地址](https://cxwithyxy.github.io/m3u8-downloader/),推荐使用 chrome 浏览器。

### 研发背景
- m3u8视频格式简介
Expand Down
108 changes: 63 additions & 45 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -371,11 +371,15 @@
</script>
<!--vue 前端框架-->
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="http://blog.luckly-mjw.cn/tool-show/m3u8-downloader/aes-decryptor.js"></script>
<script src="http://blog.luckly-mjw.cn/tool-show/m3u8-downloader/mux-mp4.js"></script>
<script src="aes-decryptor.js"></script>
<script src="mux-mp4.js"></script>

<script>
// script注入
window.loadSomeJS = async function (JSURL)
{
return await (await fetch(JSURL)).text()
};
new Vue({
el: '#m-app',

Expand All @@ -402,19 +406,8 @@
decryptor: null, // 解码器对象

stringToBuffer: function (str) {
let val = ''
for (let i = 0; i < str.length; i++) {
if (val === '') {
val = str.charCodeAt(i).toString(16)
} else {
val += ',' + str.charCodeAt(i).toString(16)
}
}

// 将16进制转化为ArrayBuffer
return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
})).buffer
var enc = new TextEncoder();
return enc.encode(str);
},
},
}
Expand Down Expand Up @@ -510,13 +503,13 @@
url: this.url,
success: (m3u8Str) => {
this.tsUrlList = []

let tsfileSuffixName = prompt("在m3u8文件里面的ts文件URL的后缀名是什么", ".ts")
// 提取 ts 视频片段地址
m3u8Str.split('\n').forEach((item) => {
if (this.isGetMP4 && item.toUpperCase().indexOf('#EXTINF:') > -1) { // 计算视频总时长,设置 mp4 信息时使用
this.durationSecond += parseFloat(item.split('#EXTINF:')[1])
}
if (item.toLowerCase().indexOf('.ts') > -1) {
if (item.toLowerCase().indexOf(tsfileSuffixName) > -1) {
this.tsUrlList.push(this.applyURL(item, this.url))
this.finishList.push({
title: item,
Expand Down Expand Up @@ -551,21 +544,35 @@
},

// 获取AES配置
getAES() {
async getAES() {
alert('视频被 AES 加密,点击确认,进行视频解码')
this.ajax({
url: this.aesConf.uri,
success: (key) => {
this.aesConf.key = this.aesConf.stringToBuffer(key)
this.aesConf.decryptor = new AESDecryptor()
this.aesConf.decryptor.constructor()
this.aesConf.decryptor.expandKey(this.aesConf.key);
this.downloadTS()
},
fail: () => {
this.alertError('AES 配置不正确')
let aseConfURL = this.aesConf.uri;
this.aesConf.uri = prompt("请确认AES key的下载链接,看情况修改!或输入真实解码key的Uint8Array的数组(数字加英文逗号)", aseConfURL);

try
{
if(this.aesConf.uri.indexOf("http") == -1)
{
this.aesConf.key = new Uint8Array(this.aesConf.uri.split(",")).buffer
}
})
else
{
let tempDownloader = await fetch(this.aesConf.uri, {
method: 'get',
responseType: 'arraybuffer'
})
this.aesConf.key = await tempDownloader.arrayBuffer()
}
this.aesConf.decryptor = new AESDecryptor()
this.aesConf.decryptor.constructor()
this.aesConf.decryptor.expandKey(this.aesConf.key);
console.log("start");
this.downloadTS()
}catch(e)
{
console.log(e);
this.alertError('AES 配置不正确')
}
},

// ts 片段的 AES 解码
Expand All @@ -577,24 +584,31 @@
// 下载分片
downloadTS() {
this.tips = 'ts 视频碎片下载中,请稍后'
let download = () => {
let download = async () => {
console.log("loadding")
let index = this.downloadIndex
this.downloadIndex++
if (this.finishList[index] && this.finishList[index].status === '') {
this.ajax({
url: this.tsUrlList[index],
type: 'file',
success: (file) => {
this.dealTS(file, index, () => this.downloadIndex < this.tsUrlList.length && download())
},
fail: () => {
this.errorNum++
this.finishList[index].status = 'error'
if (this.downloadIndex < this.tsUrlList.length) {
download()
try
{
let tempDownloader = await fetch(
this.tsUrlList[index],
{
method: 'get',
responseType: 'arraybuffer'
}
);
let file = await tempDownloader.arrayBuffer();
this.dealTS(file, index, () => this.downloadIndex < this.tsUrlList.length && download())
}catch(e)
{
console.log(e);
this.errorNum++
this.finishList[index].status = 'error'
if (this.downloadIndex < this.tsUrlList.length) {
download()
}
})
}
} else if (this.downloadIndex < this.tsUrlList.length) { // 跳过已经成功的片段
download()
}
Expand Down Expand Up @@ -726,7 +740,9 @@
},

// 拷贝本页面本身,解决跨域问题
copyCode() {
async copyCode() {
let aseCodeString = await loadSomeJS(location.href + "aes-decryptor.js");
let muxMp4CodeString = await loadSomeJS(location.href + "mux-mp4.js");
if (this.tips !== '代码下载中,请稍后' && this.tips !== '复制成功,打开视频网页控制台,注入本代码') {
this.tips = '代码下载中,请稍后';
this.ajax({
Expand All @@ -737,7 +753,6 @@
let script = fileList[1] + fileList[2];
script = script.split('// script注入');
script = script[1] + script[2];

if (this.url) {
script = script.replace(`url: '', // 在线链接`, `url: '${this.url}',`);
}
Expand All @@ -762,6 +777,9 @@
// 监听 vue 加载完成,执行业务代码
$vue.addEventListener('load', () => {${script}})
document.body.appendChild($vue);

${aseCodeString};
${muxMp4CodeString};
alert('注入成功,请滚动到页面底部')
`;
this.copyToClipboard(codeStr);
Expand Down