Greasy Fork

Greasy Fork is available in English.

YouTube - 音量徽章

在音量按钮上显示当前音量百分比的徽章。

目前为 2025-04-17 提交的版本。查看 最新版本

// ==UserScript==
// @name               YouTube - Volume Badge
// @name:fr            YouTube - Badge de Volume
// @name:es            YouTube - Indicador de volumen
// @name:de            YouTube - Lautstärke-Anzeige
// @name:it            YouTube - Etichetta del volume
// @name:zh-CN         YouTube - 音量徽章
// @namespace          https://gist.github.com/4lrick/7a069ce704be9ac95f00d8fb9c2c9bb2
// @version            1.0
// @description        Displays a badge on the volume button showing the current volume percentage.
// @description:fr     Affiche un badge sur le bouton de volume indiquant le pourcentage actuel.
// @description:es     Muestra una insignia en el botón de volumen con el porcentaje actual.
// @description:de     Zeigt ein Abzeichen auf dem Lautstärkeknopf mit dem aktuellen Prozentsatz an.
// @description:it     Mostra un'etichetta sul pulsante del volume con la percentuale attuale.
// @description:zh-CN  在音量按钮上显示当前音量百分比的徽章。
// @author			   4lrick
// @match              https://www.youtube.com/*
// @icon               https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant              none
// @license            GPL-3.0-only
// ==/UserScript==

(function() {
    'use strict';

    const VOLUME_BADGE_ID = 'ytp-volume-badge';
	const VOLUME_BADGE_STYLE = {
        position: 'absolute',
        top: '12px',
        right: '10px',
		padding: '1px 3px',
		backgroundColor: 'var(--yt-spec-red-indicator, #e1002d)',
		fontFamily: "Verdana,sans-serif",
		fontSize: '11px',
		fontWeight: 'bold',
        color: 'white',
		textShadow: "0 2px 0 rgba(0,0,0,.6)",
		backgroundImage: "none",
		borderRadius: '1.5px',
		height: 'auto',
		width: 'auto',
		lineHeight: 'normal',
		transition: 'opacity 0.2s ease',
    	opacity: '0',
    };

    function createBadge() {
        const badge = document.createElement('div');

        badge.id = VOLUME_BADGE_ID;
        Object.assign(badge.style, VOLUME_BADGE_STYLE);

        return badge;
    }

    function injectBadge() {
        const muteBtn = document.querySelector('.ytp-mute-button');
		if (!muteBtn || document.getElementById(VOLUME_BADGE_ID)) return;

		const badge = createBadge();
        muteBtn.style.position = 'relative';
        muteBtn.appendChild(badge);
		return badge;
    }

	function updateBadgeSize() {
		const badge = document.getElementById(VOLUME_BADGE_ID);
		if (!badge) return;

		const fullscreenEl = document.fullscreenElement;
		const video = document.querySelector('video');
		const isVideoFullscreen = fullscreenEl && fullscreenEl.contains(video);

		if (isVideoFullscreen) {
			badge.style.fontSize = '11px';
		} else {
			badge.style.fontSize = '9px';
		}
	}


    function displayBadge(player) {
    	let badge = document.getElementById(VOLUME_BADGE_ID) || injectBadge();
        if (!badge || !player) return;

        const volume = player.getVolume();
        const isMuted = player.isMuted() || volume === 0;
		updateBadgeSize();

		badge.textContent = volume;
        badge.style.opacity = isMuted ? '0' : '1';

    }

    function checkVideoExists() {
        const video = document.querySelector('video');
        const player = document.getElementById('movie_player');
		if (!video || !player) return;

		displayBadge(player);

        video.addEventListener('volumechange', () => {
            displayBadge(player);
        });

        observer.disconnect();
    }

    const observer = new MutationObserver(checkVideoExists);
    observer.observe(document.body, { childList: true, subtree: true });
	document.addEventListener('fullscreenchange', updateBadgeSize);
})();