您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Allows you to customize YouTube subtitles / Le permite personalizar los subtítulos de YouTube.
// ==UserScript== // @name YouTube Customizable Subtitles / Youtube Subtitulos Personalizables // @namespace http://tampermonkey.net/ // @version 2.0 // @description Allows you to customize YouTube subtitles / Le permite personalizar los subtítulos de YouTube. // @author Eterve Nallo - Diam // @license MIT // @match *://*.youtube.com/* // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; const languages = { en: { configTitle: 'Subtitle Settings', outlineColor: 'Outline Color:', outlineWidth: 'Outline Width:', textColor: 'Text Color:', saveButton: 'Save', closeButton: 'X', languageButton: 'Language', languageLabel: 'Choose Language', menuCommand: 'Show/Hide Subtitle Settings' }, es: { configTitle: 'Configuración de Subtítulos', outlineColor: 'Color del Contorno:', outlineWidth: 'Grosor del Contorno:', textColor: 'Color del Texto:', saveButton: 'Guardar', closeButton: 'X', languageButton: 'Idioma', languageLabel: 'Elegir Idioma', menuCommand: 'Mostrar/Ocultar Configuración de Subtítulos' }, ja: { configTitle: '字幕設定', outlineColor: 'アウトラインカラー:', outlineWidth: 'アウトラインの幅:', textColor: '文字色:', saveButton: '保存', closeButton: 'X', languageButton: '言語', languageLabel: '言語を選択', menuCommand: '字幕設定を表示/非表示' }, ru: { configTitle: 'Настройки субтитров', outlineColor: 'Цвет контура:', outlineWidth: 'Ширина контура:', textColor: 'Цвет текста:', saveButton: 'Сохранить', closeButton: 'X', languageButton: 'Язык', languageLabel: 'Выберите язык', menuCommand: 'Показать/Скрыть настройки субтитров' }, ko: { configTitle: '자막 설정', outlineColor: '윤곽선 색상:', outlineWidth: '윤곽선 너비:', textColor: '글자 색상:', saveButton: '저장', closeButton: 'X', languageButton: '언어', languageLabel: '언어 선택', menuCommand: '자막 설정 표시/숨기기' }, zh: { configTitle: '字幕设置', outlineColor: '轮廓颜色:', outlineWidth: '轮廓宽度:', textColor: '文字颜色:', saveButton: '保存', closeButton: 'X', languageButton: '语言', languageLabel: '选择语言', menuCommand: '显示/隐藏字幕设置' } }; const defaultConfig = { outlineColor: 'black', outlineWidth: 1, textColor: 'white', showPanel: false, language: 'en' }; function loadConfig() { const savedConfig = GM_getValue('ytSubtitleConfig'); return savedConfig ? JSON.parse(savedConfig) : defaultConfig; } function saveConfig(config) { GM_setValue('ytSubtitleConfig', JSON.stringify(config)); } const config = loadConfig(); const lang = languages[config.language] || languages.en; function applySubtitleStyles() { const shadowOffset = `${config.outlineWidth / 2}px`; GM_addStyle(` .ytp-caption-segment { color: ${config.textColor} !important; text-shadow: ${shadowOffset} ${shadowOffset} 0 ${config.outlineColor}, -${shadowOffset} -${shadowOffset} 0 ${config.outlineColor}, ${shadowOffset} -${shadowOffset} 0 ${config.outlineColor}, -${shadowOffset} ${shadowOffset} 0 ${config.outlineColor}; background: transparent !important; font-weight: bold; font-size: calc(16px + 1vw); } `); } function createConfigPanel() { const videoPlayer = document.querySelector('.html5-video-player'); if (!videoPlayer) { console.error('No se encontró el reproductor de video'); return; } const panel = document.createElement('div'); panel.id = 'subtitleConfigPanel'; panel.style.position = 'absolute'; panel.style.top = '10px'; panel.style.right = '10px'; panel.style.padding = '10px'; panel.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; panel.style.color = 'white'; panel.style.borderRadius = '5px'; panel.style.zIndex = '9999'; panel.style.display = 'block'; panel.innerHTML = ` <h4>${lang.configTitle}</h4> <label>${lang.outlineColor} <input type="color" id="outlineColor" value="${config.outlineColor}"> </label><br> <label>${lang.outlineWidth} <div id="outlineWidthControl" style="display: flex; align-items: center;"> <input type="range" id="outlineWidthSlider" min="0.5" max="5" step="0.5" value="${config.outlineWidth}" style="width: 150px;"> <div id="outlineWidthDisplay" style="margin-left: 10px; font-size: 16px; width: 35px; text-align: center;">${config.outlineWidth}</div> </div> </label><br> <label>${lang.textColor} <input type="color" id="textColor" value="${config.textColor}"> </label><br> <button id="saveConfig">${lang.saveButton}</button> <button id="closePanel" style="margin-top: 10px;">${lang.closeButton}</button> <br><button id="changeLanguage">${lang.languageButton}</button> `; videoPlayer.appendChild(panel); // Actualizar el grosor del contorno en tiempo real con el slider document.getElementById('outlineWidthSlider').addEventListener('input', (event) => { const newOutlineWidth = parseFloat(event.target.value); document.getElementById('outlineWidthDisplay').textContent = newOutlineWidth; config.outlineWidth = newOutlineWidth; applySubtitleStyles(); }); document.getElementById('saveConfig').addEventListener('click', () => { config.outlineColor = document.getElementById('outlineColor').value; config.textColor = document.getElementById('textColor').value; applySubtitleStyles(); saveConfig(config); }); document.getElementById('closePanel').addEventListener('click', () => { panel.remove(); config.showPanel = false; saveConfig(config); }); document.getElementById('changeLanguage').addEventListener('click', () => { toggleLanguageMenu(panel); }); } function toggleLanguageMenu(panel) { const languageMenu = panel.querySelector('#languageMenu'); if (!languageMenu) { // Crear nueva ventana de idiomas const languageMenu = document.createElement('div'); languageMenu.id = 'languageMenu'; languageMenu.style.position = 'absolute'; languageMenu.style.top = '50px'; languageMenu.style.left = '10px'; languageMenu.style.padding = '10px'; languageMenu.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; languageMenu.style.color = 'white'; languageMenu.style.borderRadius = '5px'; languageMenu.style.zIndex = '9999'; languageMenu.innerHTML = ` <h4>${lang.languageLabel}</h4> <button id="language_en">English</button> <button id="language_es">Español</button> <button id="language_ja">日本語</button> <button id="language_ru">Русский</button> <button id="language_ko">한국어</button> <button id="language_zh">中文</button> <button id="closeLanguageMenu" style="margin-top: 10px;">${lang.closeButton}</button> `; panel.appendChild(languageMenu); // Añadir eventos a los botones de idioma document.getElementById('language_en').addEventListener('click', () => { changeLanguage('en'); }); document.getElementById('language_es').addEventListener('click', () => { changeLanguage('es'); }); document.getElementById('language_ja').addEventListener('click', () => { changeLanguage('ja'); }); document.getElementById('language_ru').addEventListener('click', () => { changeLanguage('ru'); }); document.getElementById('language_ko').addEventListener('click', () => { changeLanguage('ko'); }); document.getElementById('language_zh').addEventListener('click', () => { changeLanguage('zh'); }); // Cerrar el menú de idiomas document.getElementById('closeLanguageMenu').addEventListener('click', () => { languageMenu.remove(); }); } } function changeLanguage(newLanguage) { config.language = newLanguage; saveConfig(config); location.reload(); // Recarga la página para aplicar el nuevo idioma } function toggleConfigPanel() { const videoPlayer = document.querySelector('.html5-video-player'); if (!videoPlayer) { console.error('No se encontró el reproductor de video'); return; } const panel = document.getElementById('subtitleConfigPanel'); if (panel) { panel.remove(); config.showPanel = false; } else { createConfigPanel(); } saveConfig(config); } GM_registerMenuCommand(lang.menuCommand, toggleConfigPanel); applySubtitleStyles(); if (config.showPanel) { createConfigPanel(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址