您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Overlay Twitch player with VK embed
// ==UserScript== // @name ACU VK DLC Scriptas // @namespace http://tampermonkey.net/ // @version 1.0 // @description Overlay Twitch player with VK embed // @author UgandanHobo // @match https://www.twitch.tv/* // @grant none // @license WTFPL // ==/UserScript== (function() { 'use strict'; // Channel -> VK embed base URL const channelMap = { "poorkiwi": "https://vkvideo.ru/video_ext.php?oid=-230429474&id=456239024&hash=5fc3f72c715ac08f&autoplay=1&hd=4&js_api=1", "finger_plasma": "https://vkvideo.ru/video_ext.php?oid=-230429399&id=456239020&hash=d1ade4e0a6b3989b&autoplay=1&hd=4&js_api=1", "warpcorebreachwallsfell": "https://vkvideo.ru/video_ext.php?oid=-232483180&id=456239017&hash=c6860ae4a01cc4c2&autoplay=1&hd=4&js_api=1" }; let lastPath = null; let previousTwitchPlayer = null; let clickToEnableAudioHandler = null; function getChannelName() { const m = location.pathname.match(/^\/([^\/?#]+)/); return m ? m[1].toLowerCase() : null; } function hideTwitchPlayer(t) { if (!t) return; previousTwitchPlayer = t; t.dataset.oldStyle = t.getAttribute("style") || ""; t.style.position = "absolute"; t.style.top = "-10000px"; t.style.left = "-10000px"; } function restoreTwitchPlayer() { const t = previousTwitchPlayer || document.querySelector('.video-player'); if (!t) return; if (t.dataset.oldStyle !== undefined) { t.setAttribute("style", t.dataset.oldStyle); delete t.dataset.oldStyle; } else { t.style.position = ""; t.style.top = ""; t.style.left = ""; } previousTwitchPlayer = null; } function ensureVkApi(cb) { if (window.VK && window.VK.VideoPlayer) return cb(); let s = document.getElementById('vk-api-script'); if (!s) { s = document.createElement('script'); s.id = 'vk-api-script'; s.src = "https://vk.com/js/api/videoplayer.js"; s.onload = cb; document.head.appendChild(s); } else { s.onload = cb; // in case it’s loading } } function trySet1080p(iframe) { // Best effort: URL already has hd=4; also try a postMessage nudge after init/start. try { iframe.contentWindow.postMessage({ method: "set_quality", quality: 4 }, "*"); } catch(e){} // Retry once more a bit later in case the stream qualities weren’t known yet. setTimeout(() => { try { iframe.contentWindow.postMessage({ method: "set_quality", quality: 4 }, "*"); } catch(e){} }, 1500); } function wireAudioAutoplayWorkaround(player) { // Immediate attempt after init try { player.unmute(); player.play && player.play(); } catch(e){} // If browser blocks autoplay with sound, VK emits AUTOPLAY_SOUND_PROHIBITED. const onBlocked = () => { // One-time global click to satisfy user-gesture requirement, then unmute+play. if (clickToEnableAudioHandler) return; clickToEnableAudioHandler = () => { try { player.unmute(); player.play && player.play(); } catch(e){} document.removeEventListener('click', clickToEnableAudioHandler, true); document.removeEventListener('touchstart', clickToEnableAudioHandler, true); clickToEnableAudioHandler = null; }; document.addEventListener('click', clickToEnableAudioHandler, true); document.addEventListener('touchstart', clickToEnableAudioHandler, true); }; player.on && player.on("autoplaySoundProhibited", onBlocked); // Some builds use lowercase event names; just in case: player.on && player.on("AUTOPLAY_SOUND_PROHIBITED", onBlocked); } function injectOverlay() { const channel = getChannelName(); const t = document.querySelector('.video-player'); const existing = document.getElementById('vk-overlay-frame'); if (!channel || !(channel in channelMap)) { if (existing) existing.remove(); restoreTwitchPlayer(); return; } if (existing || !t) return; hideTwitchPlayer(t); const p = t.parentNode; const o = document.createElement('div'); o.id = 'vk-overlay-frame'; o.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;z-index:99999;background:#000;'; p.style.position = 'relative'; // Request autoplay + 1080p + API const src = channelMap[channel]; const f = document.createElement('iframe'); f.src = src; f.style.cssText = 'width:100%;height:100%;border:0;display:block;'; f.setAttribute('frameborder', '0'); f.setAttribute('allowfullscreen', '1'); f.setAttribute('allow', 'autoplay; encrypted-media; fullscreen; picture-in-picture'); o.appendChild(f); p.appendChild(o); ensureVkApi(() => { // Wait a tick for the iframe to be ready-ish const hook = () => { try { const player = VK.VideoPlayer(f); // Robust unmute: immediate + blocked-autoplay fallback via first user click. wireAudioAutoplayWorkaround(player); // Nudge quality to 1080p after init/start trySet1080p(f); // Also retry both actions right after "started" player.on && player.on("started", () => { trySet1080p(f); try { player.unmute(); } catch(e){} }); // As a belt-and-suspenders, unmute again after 10s (your requested delay) setTimeout(() => { try { player.unmute(); } catch(e){} }, 10000); } catch (e) { // If VideoPlayer throws (iframe not ready yet), try again shortly setTimeout(hook, 500); } }; hook(); }); } function tick() { if (location.pathname !== lastPath) { lastPath = location.pathname; injectOverlay(); } } setInterval(tick, 800); injectOverlay(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址