Compare commits

...

5 Commits

Author SHA1 Message Date
49dae65bca update 2023-05-28 18:09:23 +08:00
8472b29247 update 2023-01-28 17:50:46 +08:00
881037a195 update README 2022-12-11 23:53:49 +08:00
5b204904a7 Merge branch 'master' of ssh://git.evan.run:2200/evan/js-mediaDownloader 2022-12-11 23:52:37 +08:00
401a6c2286 修复大文件无法下载的问题 2022-12-11 23:50:40 +08:00
2 changed files with 91 additions and 66 deletions

View File

@ -21,20 +21,24 @@
## 参数 ## 参数
```javascript ```javascript
//自动快进 //快进抓取
evanEnv.enableAutoForward = true jsMedia.setSpeed(10);
//完成后自动下载 //完成后自动下载
evanEnv.enableAutoDownload = true jsMedia.enableAutoDownload = true;
//手工触发下载
jsMedia.download();
``` ```
## FFmpeg合并示例 ## FFmpeg合并示例
```shell ```shell
ffmpeg -i mediasource_0_0.mp4 -i mediasource_0_1.mp4 -c copy -bsf:a aac_adtstoasc out.mp4 ffmpeg -i audio.mp4 -acodec copy audio.aac
ffmpeg -i audio.aac -i video.mp4 -c copy -bsf:a aac_adtstoasc out.mp4
``` ```
## 常见问题 ## 大文件分段需要先文件合并
- 合并后声音播放不正常:由于部分网站使用了HE-AAC v2(AAC+SBR+PS)作为音频编码,大部分播放器还不支持此音频流格式,故声音不正常,使用Windows自带的视频播放器播放正常 ```
copy /b media_0_*.mp4 out.mp4
```
## 特别说明 ## 特别说明
- 仅限内部交流使用,请勿用于非法用途 - 仅限内部交流使用,请勿用于非法用途

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name Universal encrypted video downloader // @name Universal encrypted video downloader
// @namespace http://tampermonkey.net/ // @namespace http://tampermonkey.net/
// @version 0.1 // @version 1.1
// @description Bypass the encrypted video download protection via js hook // @description Bypass the encrypted video download protection via js hook
// @author Evan // @author Evan
// @match https://www.bilibili.com/video/* // @match https://www.bilibili.com/video/*
@ -12,29 +12,20 @@
// @grant none // @grant none
// ==/UserScript== // ==/UserScript==
evanEnv = new Object(); jsMedia = new Object();
evanEnv.mediaSources = []; jsMedia.mediaSources = [];
evanEnv.enableAutoForward = true; jsMedia.enableAutoDownload = true;
evanEnv.enableAutoDownload = true; //1G
jsMedia.fragmentSize = 1024*1024*1024;
(function () { (function () {
evanEnv.videos = document.getElementsByTagName('video'); let mediaSourceSeq = 0;
evanEnv.buildArrayBuffer = function (bufferList) { jsMedia.videos = document.getElementsByTagName('video');
var totalLength = 0; jsMedia.addZero = function(num){
for (var i = 0; i < bufferList.length; i++) { return ('00' + num).slice(-3);
totalLength += bufferList[i].byteLength;
}
var tmp = new Uint8Array(totalLength);
var lastLength = 0;
for (var ix = 0; ix < bufferList.length; ix++) {
tmp.set(new Uint8Array(bufferList[ix]), lastLength);
lastLength += bufferList[ix].byteLength;
}
return tmp.buffer;
}; };
evanEnv.downloadRawData = function (bufferList, fileName = 'out.mp4') { jsMedia.downloadBlob = function (buff, fileName) {
var buff = evanEnv.buildArrayBuffer(bufferList); let url = window.URL.createObjectURL(new Blob(buff, { type: "arraybuffer" }))
let url = window.URL.createObjectURL(new Blob([buff], {type: "arraybuffer"}))
const link = document.createElement('a'); const link = document.createElement('a');
link.style.display = 'none'; link.style.display = 'none';
link.href = url; link.href = url;
@ -43,22 +34,62 @@ evanEnv.enableAutoDownload = true;
link.click(); link.click();
document.body.removeChild(link); document.body.removeChild(link);
}; };
jsMedia.calcBlobLength = function (buffList) {
let totalLength = 0;
for (let i = 0; i < buffList.length; i++) {
totalLength = totalLength + buffList[i].byteLength;
}
return totalLength;
};
jsMedia.MyMediaSourceBuffer = function () {
this.id = 0;
this.rawData1 = [];
this.rawData2 = [];
let currentSlot = 0;
let downloadedIndex = 0;
this.download = function () {
let lastSlot = currentSlot;
if (currentSlot === 0) {
currentSlot = 1;
} else {
currentSlot = 0;
}
evanEnv.download = function () { if (lastSlot == 0) {
for (var i = 0; i < evanEnv.mediaSources.length; i++) { jsMedia.downloadBlob(this.rawData1, 'media_' + this.id + '_' + jsMedia.addZero(downloadedIndex) + '.mp4');
var currentItem = evanEnv.mediaSources[i]; this.rawData1 = [];
if (currentItem.downloaded == undefined || currentItem.downloaded == false) { } else {
for (var x = 0; x < currentItem.rawSources.length; x++) { jsMedia.downloadBlob(this.rawData2, 'media_' + this.id + '_' + jsMedia.addZero(downloadedIndex) + '.mp4');
evanEnv.downloadRawData(currentItem.rawSources[x], 'mediasource_' + i + '_' + x + '.mp4'); this.rawData2 = [];
} }
downloadedIndex++;
};
this.appendBuffer = function (buf) {
let totalLength = 0;
if (currentSlot === 0) {
this.rawData1.push(buf);
totalLength = jsMedia.calcBlobLength(this.rawData1);
} else {
this.rawData2.push(buf);
totalLength = jsMedia.calcBlobLength(this.rawData2);
} }
currentItem.downloaded = true; if (totalLength >= jsMedia.fragmentSize) {
this.download();
}
};
};
jsMedia.download = function(){
for (let i = 0, length = jsMedia.mediaSources.length; i < length; i++) {
jsMedia.mediaSources[i].download();
} }
}; };
evanEnv.downloadMediaSource = function (mediaSource) {
for (var x = 0; x < mediaSource.rawSources.length; x++) { jsMedia.setSpeed = function (speed) {
evanEnv.downloadRawData(mediaSource.rawSources[x], 'mediasource_' + x + '.mp4'); for (let i = 0, length = jsMedia.videos.length; i < length; i++) {
mediaSource.downloaded = true; jsMedia.videos[i].playbackRate = speed;
} }
}; };
@ -66,41 +97,31 @@ evanEnv.enableAutoDownload = true;
MediaSource.prototype.addSourceBuffer = function (mimeType) { MediaSource.prototype.addSourceBuffer = function (mimeType) {
var mediaSourceThis = this; var mediaSourceThis = this;
evanEnv.mediaSources.push(this);
this.lastPos = 0;
if (evanEnv.enableAutoDownload) {
this.onsourceended = function () {
evanEnv.download();
};
this.onsourceclose = function () {
evanEnv.downloadMediaSource(this);
};
}
var retSourceBuffer = proxy_addSourceBuffer.apply(this, [].slice.call(arguments)); var retSourceBuffer = proxy_addSourceBuffer.apply(this, [].slice.call(arguments));
if (this.rawSources == undefined) { if (this.rawSources == undefined) {
this.rawSources = []; this.rawSources = [];
} }
var buffList = [];
this.rawSources.push(buffList); retSourceBuffer.mySourceBuffer = new jsMedia.MyMediaSourceBuffer();
retSourceBuffer.rawData = buffList; retSourceBuffer.mySourceBuffer.id = mediaSourceSeq;
if (evanEnv.enableAutoForward) { jsMedia.mediaSources.push(retSourceBuffer.mySourceBuffer);
retSourceBuffer.onupdate = function () {
if (this.buffered != this.buffered.length > 0) {
var endPos = this.buffered.end(0); if (jsMedia.enableAutoDownload) {
if (endPos > 5 && endPos - mediaSourceThis.lastPos > 25) { this.onsourceended = function () {
evanEnv.videos[0].currentTime = endPos - 3; jsMedia.download();
mediaSourceThis.lastPos = evanEnv.videos[0].currentTime; };
} this.onsourceclose = function () {
} jsMedia.download();
}; };
} }
mediaSourceSeq++;
return retSourceBuffer; return retSourceBuffer;
}; };
var proxy_appendBuffer = SourceBuffer.prototype.appendBuffer; var proxy_appendBuffer = SourceBuffer.prototype.appendBuffer;
SourceBuffer.prototype.appendBuffer = function (buf) { SourceBuffer.prototype.appendBuffer = function (buf) {
this.rawData.push(buf); this.mySourceBuffer.appendBuffer(buf);
return proxy_appendBuffer.apply(this, [].slice.call(arguments)); return proxy_appendBuffer.apply(this, [].slice.call(arguments));
}; };
})(); })();