// ==UserScript== // @name Universal encrypted video downloader // @namespace http://tampermonkey.net/ // @version 1.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== jsMedia = new Object(); jsMedia.mediaSources = []; jsMedia.enableAutoDownload = true; //1G jsMedia.fragmentSize = 1024*1024*1024; (function () { let mediaSourceSeq = 0; jsMedia.videos = document.getElementsByTagName('video'); jsMedia.addZero = function(num){ return ('00' + num).slice(-3); }; jsMedia.downloadBlob = function (buff, fileName) { 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); }; 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; } if (lastSlot == 0) { jsMedia.downloadBlob(this.rawData1, 'media_' + this.id + '_' + jsMedia.addZero(downloadedIndex) + '.mp4'); this.rawData1 = []; } else { jsMedia.downloadBlob(this.rawData2, 'media_' + this.id + '_' + jsMedia.addZero(downloadedIndex) + '.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); } if (totalLength >= jsMedia.fragmentSize) { this.download(); } }; }; jsMedia.download = function(){ for (let i = 0, length = jsMedia.mediaSources.length; i < length; i++) { jsMedia.mediaSources[i].download(); } }; jsMedia.setSpeed = function (speed) { for (let i = 0, length = jsMedia.videos.length; i < length; i++) { jsMedia.videos[i].playbackRate = speed; } }; var proxy_addSourceBuffer = MediaSource.prototype.addSourceBuffer; MediaSource.prototype.addSourceBuffer = function (mimeType) { var mediaSourceThis = this; var retSourceBuffer = proxy_addSourceBuffer.apply(this, [].slice.call(arguments)); if (this.rawSources == undefined) { this.rawSources = []; } retSourceBuffer.mySourceBuffer = new jsMedia.MyMediaSourceBuffer(); retSourceBuffer.mySourceBuffer.id = mediaSourceSeq; jsMedia.mediaSources.push(retSourceBuffer.mySourceBuffer); if (jsMedia.enableAutoDownload) { this.onsourceended = function () { jsMedia.download(); }; this.onsourceclose = function () { jsMedia.download(); }; } mediaSourceSeq++; return retSourceBuffer; }; var proxy_appendBuffer = SourceBuffer.prototype.appendBuffer; SourceBuffer.prototype.appendBuffer = function (buf) { this.mySourceBuffer.appendBuffer(buf); return proxy_appendBuffer.apply(this, [].slice.call(arguments)); }; })();