This commit is contained in:
wenyifan 2022-08-20 14:29:49 +08:00
commit f7124d84a3
2 changed files with 144 additions and 0 deletions

38
README.md Normal file
View File

@ -0,0 +1,38 @@
# 通用网页视频下载油猴脚本
## 特性
- 使用JS-Hook技术基于MediaSource原理捕获解密后的原始视频流,通杀几乎网页视频保护方案
- 支持直播流
## 已测试场景
- bilibili所有视频含付费保护视频
- bilibili直播
- 虎牙直播
- 慕课网
- 腾讯课堂
- P站 -_-;
## 用法
- 使用油猴插件导入脚本,修改作用域
- 脚本生效后视频完成加载会自动完成下载
- 下载后的文件需要使用FFmpeg完成音视频合并
## 参数
```javascript
//自动快进
evanEnv.enableAutoForward = true
//完成后自动下载
evanEnv.enableAutoDownload = true
```
## FFmpeg合并示例
```shell
ffmpeg -i mediasource_0_0.mp4 -i mediasource_0_1.mp4 -c copy -bsf:a aac_adtstoasc out.mp4
```
## 常见问题
- 合并后声音播放不正常:由于部分网站使用了HE-AAC v2(AAC+SBR+PS)作为音频编码,大部分播放器还不支持此音频流格式,故声音不正常,使用Windows自带的视频播放器播放正常
## 特别说明
- 仅限内部交流使用,请勿用于非法用途

106
downloadMedia.js Normal file
View File

@ -0,0 +1,106 @@
// ==UserScript==
// @name Universal encrypted video downloader
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Bypass the encrypted video download protection via js hook
// @author Evan
// @match https://www.bilibili.com/video/*
// @match https://www.bilibili.com/bangumi/play/*
// @match https://www.youtube.com/watch*
// @match https://www.huya.com/*
// @match https://live.bilibili.com/*
// @grant none
// ==/UserScript==
evanEnv = new Object();
evanEnv.mediaSources = [];
evanEnv.enableAutoForward = true;
evanEnv.enableAutoDownload = true;
(function () {
evanEnv.videos = document.getElementsByTagName('video');
evanEnv.buildArrayBuffer = function (bufferList) {
var totalLength = 0;
for (var i = 0; i < bufferList.length; i++) {
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') {
var buff = evanEnv.buildArrayBuffer(bufferList);
let url = window.URL.createObjectURL(new Blob([buff], {type: "arraybuffer"}))
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
evanEnv.download = function () {
for (var i = 0; i < evanEnv.mediaSources.length; i++) {
var currentItem = evanEnv.mediaSources[i];
if (currentItem.downloaded == undefined || currentItem.downloaded == false) {
for (var x = 0; x < currentItem.rawSources.length; x++) {
evanEnv.downloadRawData(currentItem.rawSources[x], 'mediasource_' + i + '_' + x + '.mp4');
}
}
currentItem.downloaded = true;
}
};
evanEnv.downloadMediaSource = function (mediaSource) {
for (var x = 0; x < mediaSource.rawSources.length; x++) {
evanEnv.downloadRawData(mediaSource.rawSources[x], 'mediasource_' + x + '.mp4');
mediaSource.downloaded = true;
}
};
var proxy_addSourceBuffer = MediaSource.prototype.addSourceBuffer;
MediaSource.prototype.addSourceBuffer = function (mimeType) {
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));
if (this.rawSources == undefined) {
this.rawSources = [];
}
var buffList = [];
this.rawSources.push(buffList);
retSourceBuffer.rawData = buffList;
if (evanEnv.enableAutoForward) {
retSourceBuffer.onupdate = function () {
if (this.buffered != this.buffered.length > 0) {
var endPos = this.buffered.end(0);
if (endPos > 5 && endPos - mediaSourceThis.lastPos > 25) {
evanEnv.videos[0].currentTime = endPos - 3;
mediaSourceThis.lastPos = evanEnv.videos[0].currentTime;
}
}
};
}
return retSourceBuffer;
};
var proxy_appendBuffer = SourceBuffer.prototype.appendBuffer;
SourceBuffer.prototype.appendBuffer = function (buf) {
this.rawData.push(buf);
return proxy_appendBuffer.apply(this, [].slice.call(arguments));
};
})();