Customize Netflix subtitles appearance
当前为
// ==UserScript==
// @name Netflix Subtitle Customizer
// @namespace https://greasyfork.org/de/users/1476487-hyperr
// @version 1.0 beta
// @description Customize Netflix subtitles appearance
// @author HYPERR.
// @match https://www.netflix.com/watch/*
// @icon https://www.netflix.com/favicon.ico
// @license MIT
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// ==/UserScript==
(function() {
'use strict';
// Default settings
const defaults = {
fontSize: '100%',
fontFamily: 'Netflix Sans',
textColor: '#FFFFFF',
backgroundColor: '#000000',
backgroundOpacity: '0.5',
textShadow: '0px 0px 4px #000000',
bold: false,
italic: false
};
// Load or initialize settings
let settings = Object.assign({}, defaults, GM_getValue('subtitleSettings', {}));
// CSS for subtitles
GM_addStyle(`
.player-timedtext-text-container span {
font-size: ${settings.fontSize} !important;
font-family: ${settings.fontFamily} !important;
color: ${settings.textColor} !important;
background-color: rgba(${hexToRgb(settings.backgroundColor)}, ${settings.backgroundOpacity}) !important;
text-shadow: ${settings.textShadow} !important;
font-weight: ${settings.bold ? 'bold' : 'normal'} !important;
font-style: ${settings.italic ? 'italic' : 'normal'} !important;
}
`);
// Create control panel
function createControlPanel() {
const panel = document.createElement('div');
panel.id = 'subtitle-control-panel';
panel.style.position = 'fixed';
panel.style.bottom = '20px';
panel.style.right = '20px';
panel.style.zIndex = '9999';
panel.style.background = '#333';
panel.style.padding = '10px';
panel.style.borderRadius = '5px';
panel.style.color = 'white';
panel.innerHTML = `
<h3 style="margin-top:0;">Subtitle Settings</h3>
<div>
<label>Font Size: </label>
<input type="range" id="fontSize" min="50" max="200" value="${parseInt(settings.fontSize)}">
<span id="fontSizeValue">${settings.fontSize}</span>%
</div>
<div>
<label>Text Color: </label>
<input type="color" id="textColor" value="${settings.textColor}">
</div>
<div>
<label>Background: </label>
<input type="color" id="backgroundColor" value="${settings.backgroundColor}">
<input type="range" id="backgroundOpacity" min="0" max="1" step="0.1" value="${settings.backgroundOpacity}">
</div>
<div>
<label><input type="checkbox" id="bold" ${settings.bold ? 'checked' : ''}> Bold</label>
<label><input type="checkbox" id="italic" ${settings.italic ? 'checked' : ''}> Italic</label>
</div>
<button id="resetSettings">Reset Defaults</button>
`;
document.body.appendChild(panel);
// Event listeners
document.getElementById('fontSize').addEventListener('input', (e) => {
const value = e.target.value + '%';
document.getElementById('fontSizeValue').textContent = value;
updateSetting('fontSize', value);
});
document.getElementById('textColor').addEventListener('input', (e) => {
updateSetting('textColor', e.target.value);
});
document.getElementById('backgroundColor').addEventListener('input', (e) => {
updateSetting('backgroundColor', e.target.value);
});
document.getElementById('backgroundOpacity').addEventListener('input', (e) => {
updateSetting('backgroundOpacity', e.target.value);
});
document.getElementById('bold').addEventListener('change', (e) => {
updateSetting('bold', e.target.checked);
});
document.getElementById('italic').addEventListener('change', (e) => {
updateSetting('italic', e.target.checked);
});
document.getElementById('resetSettings').addEventListener('click', () => {
settings = Object.assign({}, defaults);
GM_setValue('subtitleSettings', settings);
location.reload();
});
}
// Helper function to update settings
function updateSetting(key, value) {
settings[key] = value;
GM_setValue('subtitleSettings', settings);
location.reload();
}
// Helper function to convert hex to rgb
function hexToRgb(hex) {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `${r}, ${g}, ${b}`;
}
// Wait for Netflix player to load
const observer = new MutationObserver(() => {
if (document.querySelector('.player-timedtext-text-container')) {
observer.disconnect();
createControlPanel();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
// Add menu command for Tampermonkey
GM_registerMenuCommand('Configure Subtitle Settings', () => {
const panel = document.getElementById('subtitle-control-panel');
if (panel) {
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
}
});
})();