您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
the script saves and applies your set volume level, when it is off or suddenly too loud!
// ==UserScript== // @name Twitter Video Player Volume Fix // @namespace http://tampermonkey.net/ // @version 1.03.25 // @description the script saves and applies your set volume level, when it is off or suddenly too loud! // @author 6iri6r6r // @match https://x.com/* // @grant GM_getValue // @grant GM_setValue // @license MIT // @icon https://avatars.mds.yandex.net/i?id=062579e45305ee7dff7c7b26c4dd7bdced335bbc-16398073-images-thumbs&n=13 // ==/UserScript== (function () { const VOLUME_STORAGE_KEY = "XcomTwitter_video_player_MasterVolume"; const MUTED_STORAGE_KEY = "XcomTwitter_video_MasterVolume_Muted"; let savedVolume = GM_getValue(VOLUME_STORAGE_KEY, 0.5); // По умолчанию 50% let savedMuted = GM_getValue(MUTED_STORAGE_KEY, false); // По умолчанию звук включен // Логируем загруженные значения console.log("[TwitterVolumeFix] Загружена громкость:", savedVolume); console.log("[TwitterVolumeFix] Загружено состояние muted:", savedMuted); // Сохраняем громкость function saveVolume(volume) { if (volume !== savedVolume) { savedVolume = volume; GM_setValue(VOLUME_STORAGE_KEY, volume); console.log("[TwitterVolumeFix] Сохранена громкость:", volume); } } // Сохраняем состояние muted function saveMuted(muted) { if (muted !== savedMuted) { savedMuted = muted; GM_setValue(MUTED_STORAGE_KEY, muted); console.log("[TwitterVolumeFix] Сохранено состояние muted:", muted); } } // Применяем сохранённые настройки к видео function applySettings(video) { if (!video) return; video.volume = savedVolume; // Применяем точное значение громкости video.muted = savedMuted; // Применяем сохранённое состояние muted console.log("[TwitterVolumeFix] Применены настройки: volume =", video.volume, ", muted =", video.muted); } // Отслеживаем клики по кнопке "Игнорировать/Не игнорировать" function attachButtonHandlers() { document.querySelectorAll('button[aria-label="Игнорировать"], button[aria-label="Не игнорировать"]').forEach((button) => { if (!button.dataset.muteHandlerAttached) { button.dataset.muteHandlerAttached = "true"; button.addEventListener("click", () => { const isMuted = button.getAttribute("aria-label") === "Игнорировать"; document.querySelectorAll("video").forEach((video) => { video.muted = isMuted; if (!isMuted) { // При unmute восстанавливаем сохранённую громкость video.volume = savedVolume; } saveMuted(isMuted); }); console.log("[TwitterVolumeFix] Кнопка нажата, muted =", isMuted, ", volume =", savedVolume); }); } }); } // Отслеживаем клики по кнопке "Назад" function attachBackButtonHandlers() { document.querySelectorAll('button[aria-label="Назад"]').forEach((button) => { if (!button.dataset.backHandlerAttached) { button.dataset.backHandlerAttached = "true"; button.addEventListener("click", () => { // При нажатии "Назад" принудительно применяем сохранённые настройки ко всем видео setTimeout(() => { document.querySelectorAll("video").forEach(applySettings); console.log("[TwitterVolumeFix] Нажата кнопка 'Назад', применены настройки: volume =", savedVolume, ", muted =", savedMuted); }, 100); // Задержка для ожидания загрузки видео после навигации }); } }); } // Подключаем обработчики к конкретному видео function attachVideoHandlers(video) { if (!video.dataset.volumeHandlerAttached) { video.dataset.volumeHandlerAttached = "true"; // Применяем настройки при загрузке нового ролика video.addEventListener("loadedmetadata", () => applySettings(video)); video.addEventListener("play", () => applySettings(video)); // Сохраняем громкость при изменении через слайдер video.addEventListener("volumechange", () => { if (video.volume !== savedVolume && !video.muted) { saveVolume(video.volume); } }); // Сразу применяем для уже загруженного видео applySettings(video); } } // Ищем все видео и кнопки на странице function processElements() { document.querySelectorAll("video").forEach(attachVideoHandlers); attachButtonHandlers(); attachBackButtonHandlers(); } // Наблюдаем за изменениями DOM (SPA-переходы) const observer = new MutationObserver(() => processElements()); observer.observe(document.body, { childList: true, subtree: true }); // На случай, если элементы уже есть при загрузке processElements(); })();