MSE Dump Tools

Media Source Extensions API 数据 Dump 工具

目前為 2021-01-18 提交的版本,檢視 最新版本

// ==UserScript==
// @name         MSE Dump Tools
// @namespace    CloudMoeMediaSourceExtensionsAPIDataDumper
// @version      1.3.3
// @description  Media Source Extensions API 数据 Dump 工具
// @author       TGSAN
// @include      /.*/
// @run-at       document-start
// @grant        GM_unregisterMenuCommand
// @grant        GM_registerMenuCommand
// @grant        unsafeWindow
// ==/UserScript==

(function () {
    'use strict';

    GM_registerMenuCommand(`视频 - 最快播放速度`, function () { document.getElementsByTagName("video")[0].playbackRate = 16 });
    GM_registerMenuCommand(`视频 - 恢复播放速度`, function () { document.getElementsByTagName("video")[0].playbackRate = 1 });
    GM_registerMenuCommand(`音频 - 最快播放速度`, function () { document.getElementsByTagName("audio")[0].playbackRate = 16 });
    GM_registerMenuCommand(`音频 - 恢复播放速度`, function () { document.getElementsByTagName("audio")[0].playbackRate = 1 });
    GM_registerMenuCommand(`结束Dump`, EndAllDumpTasks);

    var dumpEndTasks = [];

    function dateFormat(dataObj, fmt) {
        var o = {
            "M+": dataObj.getMonth() + 1,               //月份
            "d+": dataObj.getDate(),                    //日
            "h+": dataObj.getHours(),                   //小时
            "m+": dataObj.getMinutes(),                 //分
            "s+": dataObj.getSeconds(),                 //秒
            "q+": Math.floor((dataObj.getMonth() + 3) / 3), //季度
            "S": dataObj.getMilliseconds()             //毫秒
        };
        if (/(y+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (dataObj.getFullYear() + "").substr(4 - RegExp.$1.length));
        }
        for (var k in o) {
            if (new RegExp("(" + k + ")").test(fmt)) {
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            }
        }
        return fmt;
    }

    function EndAllDumpTasks() {
        while (dumpEndTasks.length > 0) {
            let endTask = dumpEndTasks.shift();
            endTask();
        }
    }

    unsafeWindow.SavedDataList = [];

    unsafeWindow.DownloadData = function (dataKey, fileName) {
        const link = document.createElement('a');
        link.href = URL.createObjectURL(new Blob([unsafeWindow.SavedDataList[dataKey]]));
        link.download = fileName;
        link.click();
        window.URL.revokeObjectURL(link.href);
    }

    function DownloadVideo() {
        DownloadData("video", "Dumped_Video_" + dateFormat(new Date(), "yyyyMMddhhmmss") + ".mp4");
    }

    function DownloadAudio() {
        DownloadData("audio", "Dumped_Audio_" + dateFormat(new Date(), "yyyyMMddhhmmss") + ".m4a");
    }

    function Uint8ArrayConcat(a, b) {
        var c = new Uint8Array(a.length + b.length);
        c.set(a);
        c.set(b, a.length);
        return c;
    }

    function BytesToSize(bytes) {
        if (bytes === 0) return '0 B';
        var k = 1024;
        var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
        var i = Math.floor(Math.log(bytes) / Math.log(k));
        return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
    }

    var latestDownloadVideoCaption = undefined;
    var latestDownloadAudioCaption = undefined;

    var _addSourceBuffer = unsafeWindow.MediaSource.prototype.addSourceBuffer;
    unsafeWindow.MediaSource.prototype.addSourceBuffer = function (mime) {
        console.log("MediaSource addSourceBuffer Type: ", mime);
        var sourceBuffer = _addSourceBuffer.call(this, mime);
        var _append = sourceBuffer.appendBuffer;
        var endToSave = false;
        var sourceBufferData = new Uint8Array();
        var isVideo = (mime.startsWith("audio") ? false : true);
        dumpEndTasks.push(() => {
            endToSave = true;
            console.warn(`轨道: ${mime} 已结束保存。`);
            if (isVideo) {
                unsafeWindow.SavedDataList["video"] = sourceBufferData;
                if (latestDownloadVideoCaption) {
                    GM_unregisterMenuCommand(latestDownloadVideoCaption);
                    latestDownloadVideoCaption = undefined;
                }
                latestDownloadVideoCaption = `下载视频数据 (${BytesToSize(sourceBufferData.length)})`;
                GM_registerMenuCommand(latestDownloadVideoCaption, DownloadVideo);
            } else {
                unsafeWindow.SavedDataList["audio"] = sourceBufferData;
                if (latestDownloadAudioCaption) {
                    GM_unregisterMenuCommand(latestDownloadAudioCaption);
                    latestDownloadAudioCaption = undefined;
                }
                latestDownloadAudioCaption = `下载音频数据 (${BytesToSize(sourceBufferData.length)})`;
                GM_registerMenuCommand(latestDownloadAudioCaption, DownloadAudio);
            }
        });
        sourceBuffer.appendBuffer = function (buffer) {
            if (!endToSave) {
                sourceBufferData = Uint8ArrayConcat(sourceBufferData, new Uint8Array(buffer));
            }
            _append.call(this, buffer);
        }
        return sourceBuffer;
    }

})();