Repository: DavidBuchanan314/Turbo-Recadmiumator
Branch: master
Commit: a4cdb0d8d2bd
Files: 5
Total size: 8.6 KB
Directory structure:
gitextract_du84s3un/
├── LICENSE
├── README.md
└── src/
├── background.js
├── cadmium-playercore-shim.js
└── manifest.json
================================================
FILE CONTENTS
================================================
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 David Buchanan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Turbo-Recadmiumator [WIP]
A remake of truedread/netflix-1080p which auto-patches cadmium-playercore at runtime to enable enhanced playback features.
Works in both Firefox and Chrom{e,ium}.
Rather than bundling a hand-patched cadmium-playercore.js, this extension
performs the patches at runtime using regex. Therefore, it should be publishable
to the chrome/ff webstores without any copyright issues etc.
It remains to be seen how robust my regexes will be to playercore updates.
## Current features:
- Enable Ctrl+Shift+Alt+S bitrate selection window.
- 1080p video.
- Disable VP9 profiles.
- Enable 5.1 audio profile.
- Auto-select stream with max available bitrate.
## Undocumented Keyboard Shortcuts:
Netflix has a bunch of undocumented keyboard shortcuts, that do useful things. This list may be incomplete.
- Ctrl+Shift+Alt+B - Bitrate selection menu (re-enabled by this project) (NOTE: This used to be S, not B!)
- Ctrl+Shift+Alt+D - Debug overlay - displays lots of useful info and stats, including current resolution and bitrate.
- Ctrl+Shift+Alt+T - Upload custom subtitle file, in DFXP/TTML format.
- Ctrl+Shift+Alt+L - Log viewer.
## TODO:
- Add settings UI (right now, you have to edit the source...)
- Add comments detailing where I stole the code from...
## Credits:
This codebase is cobbled together with bits and pieces from [truedread/netflix-1080p](https://github.com/truedread/netflix-1080p) and its various forks. Notably:
- https://github.com/vladikoff/netflix-1080p-firefox
- https://github.com/TheGoddessInari/netflix-1080p-firefox
- https://github.com/OothecaPickle/netflix-1080p
- https://github.com/jangxx/netflix-1080p
================================================
FILE: src/background.js
================================================
// https://stackoverflow.com/a/45985333
function getBrowser() {
if (typeof chrome !== "undefined") {
if (typeof browser !== "undefined") {
return "Firefox";
} else {
return "Chrome";
}
} else {
return "Edge";
}
}
chrome.webRequest.onBeforeRequest.addListener(
function (details) {
/* Allow our shim to load an untouched copy */
if (details.url.endsWith("?no_filter")) {
return {};
}
if (getBrowser() == "Chrome") {
return {
redirectUrl: chrome.extension.getURL("cadmium-playercore-shim.js")
};
}
/* Work around funky CORS behaviour on Firefox */
else if (getBrowser() == "Firefox") {
let filter = browser.webRequest.filterResponseData(details.requestId);
let encoder = new TextEncoder();
filter.onstop = event => {
fetch(browser.extension.getURL("cadmium-playercore-shim.js")).
then(response => response.text()).
then(text => {
filter.write(encoder.encode(text));
filter.close();
});
};
return {};
}
else {
console.error("Unsupported web browser :(");
}
}, {
urls: [
"*://assets.nflxext.com/player/html/ffe/*",
"*://*.a.nflxso.net/sec/player/html/ffe/*"
]
}, ["blocking"]
);
================================================
FILE: src/cadmium-playercore-shim.js
================================================
/* This script runs as a drop-in replacement of the original cadmium-playercore */
console.log("Hello, I am running instead of playercore");
var my_config = {
"use_VP9": false,
"use_5.1": false,
"set_max_bitrate": true,
}
function repr(obj) {
// can you tell I'm a python programmer?
return JSON.stringify(obj);
}
function do_patch(desc, needle, replacement) {
var match = cadmium_src.match(needle);
if (!match) {
alert("Failed to find patch: " + repr(desc));
} else {
cadmium_src = cadmium_src.replace(needle, replacement);
console.log("[+] Patched: " + repr(desc));
if (match[0].length < 200) { // avoid spamming the console
console.log(repr(match[0]) + " -> " + repr(replacement));
}
}
}
/* We need to do a synchronous request because we need to eval
the response before the body of this script finishes executing */
var request = new XMLHttpRequest();
var cadmium_url = document.getElementById("player-core-js").src;
request.open("GET", cadmium_url + "?no_filter", false); // synchronous
request.send(null);
var cadmium_src = request.responseText;
function get_profile_list() {
custom_profiles = [
"playready-h264mpl30-dash",
"playready-h264mpl31-dash",
"playready-h264mpl40-dash",
"playready-h264hpl30-dash",
"playready-h264hpl31-dash",
"playready-h264hpl40-dash",
"heaac-2-dash",
"heaac-2hq-dash",
"simplesdh",
"nflx-cmisc",
"BIF240",
"BIF320"
];
if (my_config["use_VP9"]) {
custom_profiles = custom_profiles.concat([
"vp9-profile0-L30-dash-cenc",
"vp9-profile0-L31-dash-cenc",
"vp9-profile0-L40-dash-cenc",
]);
}
if (my_config["use_5.1"]) {
custom_profiles.push("heaac-5.1-dash");
}
return custom_profiles;
}
do_patch(
"Hello world",
/(.*)/,
"console.log('Hello, I am code which has been injected into playercore!'); $1"
);
do_patch(
"Custom profiles",
/(viewableId:.,profiles:).,/,
"$1 get_profile_list(),"
);
do_patch(
"Custom profile group",
/(name:"default",profiles:)./,
"$1 get_profile_list()"
);
do_patch(
"Re-enable Ctrl+Shift+Alt+S menu",
/this\...\....\s*\&\&\s*this\.toggle\(\);/,
"this.toggle();");
// run our patched copy of playercore
eval(cadmium_src);
/* netflix_max_bitrate.js */
function getElementByXPath(xpath) {
return document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
function set_max_bitrate() {
const VIDEO_SELECT = getElementByXPath("//div[text()='Video Bitrate / VMAF']");
const AUDIO_SELECT = getElementByXPath("//div[text()='Audio Bitrate']");
const BUTTON = getElementByXPath("//button[text()='Override']");
if (!(VIDEO_SELECT && AUDIO_SELECT && BUTTON)){
window.dispatchEvent(new KeyboardEvent('keydown', {
keyCode: 66,
ctrlKey: true,
altKey: true,
shiftKey: true,
}));
return false;
}
let SELECT_LISTS = [VIDEO_SELECT, AUDIO_SELECT];
let result = false;
for (var index = 0; index < SELECT_LISTS.length; index++) {
let list = SELECT_LISTS[index];
let parent = list.parentElement;
let select = parent.querySelector('select');
if (select.disabled){
return false;
}
let options = parent.querySelectorAll('select > option');
if (options.length == 0){
return false;
}
if (options.length > 1 && options[0].selected == false){
return false;
}
for (var i = 0; i < options.length - 1; i++) {
options[i].selected = false;
}
options[options.length - 1].selected = true;
result = options[options.length - 1].selected;
}
if (result){
console.log("max bitrate selected, closing window");
BUTTON.click();
}
return result;
}
function set_max_bitrate_run(attempts) {
if (!attempts) {
console.log("failed to select max bitrate");
return;
}
set_max_bitrate() || setTimeout(() => set_max_bitrate_run(attempts - 1), 200);
}
const WATCH_REGEXP = /netflix.com\/watch\/.*/;
let oldLocation;
if(my_config["set_max_bitrate"]) {
console.log("netflix_max_bitrate.js enabled");
setInterval(function () {
let newLocation = window.location.toString();
if (newLocation !== oldLocation) {
oldLocation = newLocation;
WATCH_REGEXP.test(newLocation) && set_max_bitrate_run(10);
}
}, 500);
}
================================================
FILE: src/manifest.json
================================================
{
"manifest_version": 2,
"name": "Turbo-Recadmiumator",
"description": "Hotpatches Netflix cadmium-playercore.js to enhance features",
"version": "0.0.1",
"author": "Retr0id",
"background": {
"scripts": [
"background.js"
]
},
"web_accessible_resources": [
"cadmium-playercore-shim.js"
],
"permissions": [
"storage",
"webRequest",
"webRequestBlocking",
"*://assets.nflxext.com/player/html/ffe/*",
"*://*.a.nflxso.net/sec/player/html/ffe/*",
"*://netflix.com/*",
"*://www.netflix.com/*"
]
}