Files
cat-catch/js/mpd.js
ChuXun 53f9554f38 1
2025-10-19 20:55:27 +08:00

187 lines
7.1 KiB
JavaScript

// url 参数解析
const params = new URL(location.href).searchParams;
const _url = params.get("url");
// const _referer = params.get("referer");
const _requestHeaders = params.get("requestHeaders");
const _title = params.get("title");
// 修改当前标签下的所有xhr的requestHeaders
let requestHeaders = JSONparse(_requestHeaders);
setRequestHeaders(requestHeaders, () => { awaitG(init); });
var mpdJson = {}; // 解析器json结果
var mpdXml = {}; // 解析器xml结果
// var mpdContent; // mpd文件内容
var m3u8Content = ""; //m3u8内容
var mediaInfo = "" // 媒体文件信息
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message == "getM3u8") {
sendResponse({ m3u8Content, mediaInfo });
}
});
function init() {
loadCSS();
if (_url) {
fetch(_url)
.then(response => response.text())
.then(function (text) {
// mpdContent = text;
// parseMPD(mpdContent);
parseMPD(text);
$("#mpd_url").html(_url).attr("href", _url);
});
} else {
$("#loading").hide();
$("#mpdCustom").show();
$("#parse").click(function () {
let url = $("#mpdUrl").val().trim();;
url = "mpd.html?url=" + encodeURIComponent(url);
let referer = $("#referer").val().trim();;
if (referer) { url += "&requestHeaders=" + JSON.stringify({ referer: referer }); }
chrome.tabs.update({ url: url });
});
}
$("#mpdVideoLists, #mpdAudioLists").change(function () {
let type = this.id == "mpdVideoLists" ? "video" : "audio";
showSegment(type, $(this).val());
});
$("#getVideo, #getAudio").click(function () {
let type = "video";
let index = $("#mpdVideoLists").val();
if (this.id == "getAudio") {
type = "audio";
index = $("#mpdAudioLists").val();
}
showSegment(type, index);
});
$("#videoToM3u8, #audioToM3u8").click(function () {
let index = $("#mpdVideoLists").val();
let items = mpdJson.playlists[index];
let type = "video";
if (this.id == "audioToM3u8") {
index = $("#mpdAudioLists").val();
let temp = index.split("$-bmmmd-$");
index = temp[0];
let index2 = temp[1];
items = mpdJson.mediaGroups.AUDIO.audio[index].playlists[index2];
type = "audio";
}
mediaInfo = getInfo(type);
m3u8Content = "#EXTM3U\n";
m3u8Content += "#EXT-X-VERSION:3\n";
m3u8Content += "#EXT-X-TARGETDURATION:" + items.targetDuration + "\n";
m3u8Content += "#EXT-X-MEDIA-SEQUENCE:0\n";
m3u8Content += "#EXT-X-PLAYLIST-TYPE:VOD\n";
m3u8Content += '#EXT-X-MAP:URI="' + items.segments[0].map.resolvedUri + '"\n';
for (let key in items.segments) {
m3u8Content += "#EXTINF:" + items.segments[key].duration + ",\n"
m3u8Content += items.segments[key].resolvedUri + "\n";
}
m3u8Content += "#EXT-X-ENDLIST";
// $("#media_file").html(m3u8Content); return;
chrome.tabs.getCurrent(function (tabs) {
chrome.tabs.create({ url: "m3u8.html?getId=" + tabs.id });
});
});
}
// 加密类型
function getEncryptionType(schemeIdUri) {
if (schemeIdUri.includes("edef8ba9-79d6-4ace-a3c8-27dcd51d21ed")) {
return "Widevine";
} else if (schemeIdUri.includes("9a04f079-9840-4286-ab92-e65be0885f95")) {
return "Microsoft PlayReady";
} else if (schemeIdUri.includes("94ce86fb-07ff-4f43-adb8-93d2fa968ca2")) {
return "Apple FairPlay";
} else {
return "Unknown";
}
}
// 判断DRM
function isDRM(mpdContent) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(mpdContent, "application/xml");
let drmInfo = new Map();
const contentProtections = xmlDoc.getElementsByTagName("ContentProtection");
for (let i = 0; i < contentProtections.length; i++) {
const protection = contentProtections[i];
const schemeIdUri = protection.getAttribute("schemeIdUri");
let pssh = protection.getElementsByTagName("cenc:pssh")[0];
if (!pssh) {
pssh = protection.getElementsByTagName("mspr:pro")[0];
}
if (schemeIdUri && pssh) {
if (!drmInfo.has(schemeIdUri)) {
drmInfo.set(schemeIdUri, pssh.textContent);
}
}
}
return Array.from(drmInfo.entries()).map(([schemeIdUri, pssh]) => ({
schemeIdUri,
pssh,
encryptionType: getEncryptionType(schemeIdUri)
}));
}
function parseMPD(mpdContent) {
$("#loading").hide(); $("#main").show();
mpdJson = mpdParser.parse(mpdContent, { manifestUri: _url });
const drmInfo = isDRM(mpdContent);
if (drmInfo.length > 0) {
$("#loading").show();
$("#loading .optionBox").html(`<b>${i18n.DRMerror}</b><br><br>`);
drmInfo.map(item => {
$("#loading .optionBox").append(`<b>${item.encryptionType}</b><input value="${item.pssh}" style="width: 100%;"/>`);
});
}
for (let key in mpdJson.playlists) {
$("#mpdVideoLists").append(`<option value='${key}'>${mpdJson.playlists[key].attributes.NAME
} | ${(mpdJson.playlists[key].attributes.BANDWIDTH / 1024).toFixed(1)
} kbps | ${mpdJson.playlists[key].attributes["FRAME-RATE"].toFixed(1)
} fps | ${mpdJson.playlists[key].attributes.RESOLUTION.width
} x ${mpdJson.playlists[key].attributes.RESOLUTION.height
}</option>`);
}
for (let key in mpdJson.mediaGroups.AUDIO.audio) {
for (let index in mpdJson.mediaGroups.AUDIO.audio[key].playlists) {
let item = mpdJson.mediaGroups.AUDIO.audio[key].playlists[index];
// console.log(item);
$("#mpdAudioLists").append(`<option value='${key}$-bmmmd-$${index}'>${key} | ${item.attributes.NAME} | ${item.attributes.BANDWIDTH / 1000}Kbps</option>`);
}
}
$("#info").html(getInfo("video"));
showSegment("video", 0);
}
function showSegment(type, index) {
let textarea = "";
let items;
if (type == "video") {
items = mpdJson.playlists[index];
} else {
let temp = index.split("$-bmmmd-$");
index = temp[0];
let index2 = temp[1];
items = mpdJson.mediaGroups.AUDIO.audio[index].playlists[index2];
}
for (let key in items.segments) {
textarea += items.segments[key].resolvedUri + "\n\n";
}
$("#media_file").html(textarea);
$("#count").html(i18n("m3u8Info", [items.segments.length, secToTime(mpdJson.duration)]));
items.segments.length > 0 && $("#tips").html('initialization: <input type="text" value="' + items.segments[0].map.resolvedUri + '" spellcheck="false" readonly="readonly" class="width100">');
$("#info").html(getInfo(type));
}
function getInfo(type = "audio") {
if (type == "audio") {
return i18n.audio + ": " + $("#mpdAudioLists").find("option:selected").text();
} else {
return i18n.video + ": " + $("#mpdVideoLists").find("option:selected").text();
}
}