Last active
March 3, 2022 02:51
-
-
Save qinlili23333/ab2ea32e38fe3d390b7d053d53379e8e to your computer and use it in GitHub Desktop.
人卫慕课播放助手
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name 人卫慕课播放助手 | |
// @namespace https://qinlili.bid | |
// @version 0.1.2 | |
// @description 自动升级到720P+预取Key减少缓冲 | |
// @author 琴梨梨 | |
// @match *://www.pmphmooc.com/* | |
// @icon https://www.pmphmooc.com/static/favicon.ico | |
// @require https://lib.baomitu.com/m3u8-parser/4.7.0/m3u8-parser.min.js#sha512-k+LQLfQIGmuQTgjCfnE/iU3jdv+J9sdykVF5SgKtc+aMiKWPZqGjs60Bp3lug6rh9DVhcSZefpetyVXwUny48w== | |
// @grant none | |
// @license WTFPL | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
(function(appendChild) { | |
Node.prototype.appendChild = function(ele,loc) { | |
if(ele.src&&ele.src.startsWith("http://")>0){ | |
console.log(ele) | |
ele.src=ele.src.replace("http://","https://") | |
} | |
return appendChild.call(this, ele,loc); | |
}; | |
})(Node.prototype.appendChild); | |
//https://stackoverflow.com/a/52171480 | |
const cyrb53 = function(str, seed = 0) { | |
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed; | |
for (let i = 0, ch; i < str.length; i++) { | |
ch = str.charCodeAt(i); | |
h1 = Math.imul(h1 ^ ch, 2654435761); | |
h2 = Math.imul(h2 ^ ch, 1597334677); | |
} | |
h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909); | |
h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909); | |
return 4294967296 * (2097151 & h2) + (h1>>>0); | |
}; | |
//https://stackoverflow.com/a/61226119 | |
const blobToBase64 = blob => { | |
const reader = new FileReader(); | |
reader.readAsDataURL(blob); | |
return new Promise(resolve => { | |
reader.onloadend = () => { | |
resolve(reader.result); | |
}; | |
}); | |
}; | |
let cacheKey={} | |
const makeCache=async(url,hashKey)=>{ | |
let cache=await blobToBase64(await (await fetch(url)).blob()) | |
cacheKey[hashKey]=cache | |
document.getElementsByClassName("videoTitle")[0].innerText+="[缓冲加速已开启]" | |
} | |
const m3u8Prefetch=async(m3u8)=>{ | |
console.log("Begin prefetch, getting m3u8 info...-Qinlili") | |
const m3u8Text=await (await fetch(m3u8)).text(); | |
const parser = new m3u8Parser.Parser(); | |
parser.push(m3u8Text); | |
const segments=parser.manifest.segments; | |
console.log("Success fetch m3u8 info. -Qinlili") | |
console.log(segments); | |
segments.forEach(async part=>{ | |
const controller = new AbortController(); | |
const signal = controller.signal; | |
await fetch(part.uri.replace("http://","https://"),{ | |
method:"GET", | |
signal:signal | |
}) | |
controller.abort(); | |
}) | |
console.log("Prefetch done. -Qinlili") | |
} | |
(open=> { | |
XMLHttpRequest.prototype.open = function (method, url, async, user, pass) { | |
if(url.startsWith("http://")){ | |
url=url.replace("http://","https://") | |
} | |
if (url.indexOf("index.m3u8")>0) { | |
console.log("Get m3u8 link: " + url + " -Qinlili"); | |
url = url.replace("480P","720P"); | |
m3u8Prefetch(url); | |
} | |
if (url.indexOf("/api/m3u8/getUri")>0) { | |
let hashKey=cyrb53(url) | |
if(cacheKey[hashKey]){ | |
console.log("Use local cache key-Qinlili") | |
url=cacheKey[hashKey] | |
}else{ | |
console.log("No key cache, use async fetch: " + url + " -Qinlili") | |
makeCache(url,hashKey) | |
} | |
} | |
return open.call(this, method, url, async, user, pass); | |
}; | |
})(XMLHttpRequest.prototype.open); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment