// ==UserScript== // @name MSE Dump Tools // @namespace CloudMoeMediaSourceExtensionsAPIDataDumper // @version 1.3.1 // @description Media Source Extensions API 数据 Dump 工具 // @author TGSAN // @include /.*/ // @run-at document-start // @grant GM_unregisterMenuCommand // @grant GM_registerMenuCommand // @grant unsafeWindow // @downloadURL none // ==/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() { dumpEndTasks.forEach((endTask) => { 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; } })();