// h264only
// Copyright 2026 Pavel Sobolev
//
// This file is part of the h264only project, located at
// .
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// SPDX-License-Identifier: GPL-3.0-or-later
// ==UserScript==
// @name h264only
// @namespace dev.paveloom.h264only
// @description Block support for any video compression standard besides H.264
// @version 0.1.0
// @license GPL-3.0-or-later
// @downloadURL https://codeberg.org/paveloom-o/h264only/raw/branch/main/h264only.user.js
// @updateURL https://codeberg.org/paveloom-o/h264only/raw/branch/main/h264only.user.js
// @match *://m.youtube.com/*
// @match *://music.youtube.com/*
// @match *://www.youtube.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
console.info("[h264only] userscript started")
function patch() {
function isBlocked(mimeType) {
const regex = /(vp0?8|vp0?9|av0?1)/i;
return typeof mimeType === "string" && regex.test(mimeType);
}
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType
if (window.HTMLMediaElement && HTMLMediaElement.prototype.canPlayType) {
const original = HTMLMediaElement.prototype.canPlayType;
HTMLMediaElement.prototype.canPlayType = function(type) {
return isBlocked(type) ? "" : original.call(this, type);
};
console.info("[h264only] override for `window.HTMLMediaElement` applied")
}
// https://developer.mozilla.org/en-US/docs/Web/API/MediaCapabilities/decodingInfo
if (window.MediaCapabilities && MediaCapabilities.prototype.decodingInfo) {
const original = MediaCapabilities.prototype.decodingInfo;
MediaCapabilities.prototype.decodingInfo = (configuration) => {
const contentType = configuration?.video?.contentType;
if (isBlocked(contentType)) {
return Promise.resolve({
supported: false,
smooth: false,
powerEfficient: false
});
} else {
return original.call(this, configuration);
}
};
console.info("[h264only] override for `navigator.mediaCapabilities` applied")
}
// https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/isTypeSupported_static
if (window.MediaSource && MediaSource.isTypeSupported) {
const original = MediaSource.isTypeSupported;
MediaSource.isTypeSupported = function(type) {
return isBlocked(type) ? false : original(type);
}
console.info("[h264only] override for `window.MediaSource` applied")
}
console.info("[h264only] patch applied");
}
// https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement/textContent
if (typeof trustedTypes === "undefined")
trustedTypes = { createPolicy: (_, rules) => rules };
const policy = trustedTypes.createPolicy("h264only", {
createScript: (x) => x
});
const untrustedScript = "(" + patch.toString() + ")();";
const trustedScript = policy.createScript(untrustedScript);
try {
const script = document.createElement("script");
script.textContent = trustedScript;
document.appendChild(script);
script.remove();
console.info("[h264only] injection succeeded");
} catch {
console.error("[h264only] injection failed");
}