No Video Streaming
当前为
// ==UserScript==
// @name YouTube: Audio Only
// @description No Video Streaming
// @namespace UserScript
// @version 0.2.5
// @author CY Fung
// @match https://www.youtube.com/*
// @match https://www.youtube.com/embed/*
// @match https://www.youtube-nocookie.com/embed/*
// @match https://m.youtube.com/*
// @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/
// @icon https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/YouTube-Audio-Only.png
// @grant GM_registerMenuCommand
// @grant GM.setValue
// @grant GM.getValue
// @run-at document-start
// @license MIT
// @compatible chrome
// @compatible firefox
// @compatible opera
// @compatible edge
// @compatible safari
// @allFrames true
// ==/UserScript==
(async function () {
'use strict';
const pageInjectionCode = function () {
// embed & desktop & mobile
window.XMLHttpRequest = ((XMLHttpRequest_) => {
class XMLHttpRequest extends XMLHttpRequest_ {
constructor(...args) {
super(...args);
}
open(method, url, ...args) {
if (typeof url === 'string' && url.length > 24 && url.includes('/videoplayback?') && url.replace('?', '&').includes('&source=')) {
window.postMessage({ ZECxh: url.includes('source=yt_live_broadcast') }, "*");
}
return super.open(method, url, ...args);
}
}
return XMLHttpRequest;
})(window.XMLHttpRequest);
// desktop only
// document.addEventListener('yt-page-data-fetched', async (evt) => {
// const pageFetchedDataLocal = evt.detail;
// let isLiveNow;
// try {
// isLiveNow = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.liveBroadcastDetails.isLiveNow;
// } catch (e) { }
// window.postMessage({ ZECxh: isLiveNow === true }, "*");
// }, false);
Object.defineProperty(Object.prototype, 'deviceIsAudioOnly', {
get() {
console.log(1238)
return true;
},
set(nv) {
return true;
},
enumerable: false,
configurable: true
});
const supportedFormatsConfig = () => {
function typeTest(type) {
if (typeof type === 'string' && type.startsWith('video/')) {
return false;
}
}
// return a custom MIME type checker that can defer to the original function
function makeModifiedTypeChecker(origChecker) {
// Check if a video type is allowed
return function (type) {
let res = undefined;
if (type === undefined) res = false;
else {
res = typeTest.call(this, type);
}
if (res === undefined) res = origChecker.apply(this, arguments);
return res;
};
}
// Override video element canPlayType() function
const proto = (HTMLVideoElement || 0).prototype;
if (proto && typeof proto.canPlayType == 'function') {
proto.canPlayType = makeModifiedTypeChecker(proto.canPlayType);
}
// Override media source extension isTypeSupported() function
const mse = window.MediaSource;
// Check for MSE support before use
if (mse && typeof mse.isTypeSupported == 'function') {
mse.isTypeSupported = makeModifiedTypeChecker(mse.isTypeSupported);
}
};
supportedFormatsConfig();
}
const isEnable = (typeof GM !== 'undefined' && typeof GM.getValue === 'function') ? (await GM.getValue("isEnable_aWsjF", true)) : null;
if (typeof isEnable !== 'boolean') throw new DOMException("Please Update your browser", "NotSupportedError");
if (isEnable) {
const element = document.createElement('button');
element.setAttribute('onclick', `(${pageInjectionCode})()`);
element.click();
}
GM_registerMenuCommand(`Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`, async function () {
await GM.setValue("isEnable_aWsjF", !isEnable);
location.reload();
});
let messageCount = 0;
window.addEventListener('message', (evt) => {
const v = ((evt || 0).data || 0).ZECxh;
if (typeof v === 'boolean') {
const t = ++messageCount;
if (v && isEnable) {
requestAnimationFrame(async () => {
if (t !== messageCount) return;
if (confirm("Livestream is detected. Press OK to disable YouTube Audio Mode.")) {
await GM.setValue("isEnable_aWsjF", !isEnable);
location.reload();
}
});
}
}
});
})();