您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Extract images and videos from X.com (Twitter) media gallery and play slideshow with controls, countdown timer and pause on spacebar
// ==UserScript== // @name X.com Media Gallery Slideshow with Timer and Video Support + Pause // @namespace http://tampermonkey.net/ // @version 1.7 // @description Extract images and videos from X.com (Twitter) media gallery and play slideshow with controls, countdown timer and pause on spacebar // @author OpenAI // @match https://twitter.com/* // @match https://x.com/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; let slideshowOverlay = null; let slideshowMedia = []; // Array of objects {type: 'image'|'video', src: URL} let currentIndex = 0; let slideshowTimeout = null; let countdownInterval = null; let countdownSeconds = 10; let isPaused = false; let currentVideo = null; // Extract media URLs (images and videos) from X.com media gallery function extractMedia() { const seen = new Set(); const media = []; // Images const imgElements = document.querySelectorAll('img[src*="pbs.twimg.com/media/"]'); imgElements.forEach(img => { const baseUrl = img.src.split('?')[0]; if (!seen.has(baseUrl)) { seen.add(baseUrl); // Images full size media.push({ type: 'image', src: baseUrl + '?format=jpg&name=large' }); } }); // Videos const videoElements = document.querySelectorAll('video'); videoElements.forEach(video => { let src = video.currentSrc || video.src; if (src && !seen.has(src)) { seen.add(src); media.push({ type: 'video', src: src }); } }); return media; } function clearTimers() { clearTimeout(slideshowTimeout); clearInterval(countdownInterval); } // Create and show slideshow overlay function showSlideshow(mediaArray) { if (mediaArray.length === 0) { alert('No media found!'); return; } if (slideshowOverlay) { slideshowOverlay.remove(); clearTimers(); document.removeEventListener('keydown', keyHandler); } slideshowMedia = mediaArray; currentIndex = 0; countdownSeconds = 10; isPaused = false; currentVideo = null; slideshowOverlay = document.createElement('div'); slideshowOverlay.style.position = 'fixed'; slideshowOverlay.style.top = '0'; slideshowOverlay.style.left = '0'; slideshowOverlay.style.width = '100vw'; slideshowOverlay.style.height = '100vh'; slideshowOverlay.style.backgroundColor = 'rgba(0,0,0,0.9)'; slideshowOverlay.style.display = 'flex'; slideshowOverlay.style.alignItems = 'center'; slideshowOverlay.style.justifyContent = 'center'; slideshowOverlay.style.flexDirection = 'column'; slideshowOverlay.style.zIndex = '100000'; const mediaContainer = document.createElement('div'); mediaContainer.style.maxWidth = '90%'; mediaContainer.style.maxHeight = '90%'; mediaContainer.style.borderRadius = '10px'; mediaContainer.style.boxShadow = '0 0 20px rgba(255, 255, 255, 0.7)'; mediaContainer.style.display = 'flex'; mediaContainer.style.alignItems = 'center'; mediaContainer.style.justifyContent = 'center'; slideshowOverlay.appendChild(mediaContainer); const timerDisplay = document.createElement('div'); timerDisplay.style.color = 'white'; timerDisplay.style.fontSize = '18px'; timerDisplay.style.marginTop = '10px'; timerDisplay.style.fontFamily = 'Arial, sans-serif'; timerDisplay.textContent = `Next media in: ${countdownSeconds} seconds`; slideshowOverlay.appendChild(timerDisplay); const closeBtn = document.createElement('button'); closeBtn.innerText = '✕'; closeBtn.style.position = 'fixed'; closeBtn.style.top = '20px'; closeBtn.style.right = '20px'; closeBtn.style.fontSize = '30px'; closeBtn.style.background = 'transparent'; closeBtn.style.color = 'white'; closeBtn.style.border = 'none'; closeBtn.style.cursor = 'pointer'; closeBtn.style.zIndex = '100001'; closeBtn.title = 'Close Slideshow'; closeBtn.addEventListener('click', () => { clearTimers(); slideshowOverlay.remove(); slideshowOverlay = null; document.removeEventListener('keydown', keyHandler); }); slideshowOverlay.appendChild(closeBtn); function loadMedia(index) { mediaContainer.innerHTML = ''; currentVideo = null; const mediaObj = slideshowMedia[index]; if (!mediaObj) return; if (mediaObj.type === 'image') { const img = document.createElement('img'); img.src = mediaObj.src; img.style.maxWidth = '100%'; img.style.maxHeight = '100%'; img.style.borderRadius = '10px'; mediaContainer.appendChild(img); countdownSeconds = 10; timerDisplay.textContent = `Next media in: ${countdownSeconds} seconds`; resetInterval(10000); } else if (mediaObj.type === 'video') { const video = document.createElement('video'); video.src = mediaObj.src; video.style.maxWidth = '100%'; video.style.maxHeight = '100%'; video.style.borderRadius = '10px'; video.autoplay = true; video.controls = true; video.loop = false; mediaContainer.appendChild(video); currentVideo = video; video.addEventListener('loadedmetadata', () => { countdownSeconds = Math.ceil(video.duration); timerDisplay.textContent = `Next media in: ${countdownSeconds} seconds`; resetInterval(countdownSeconds * 1000); if (isPaused) video.pause(); }); video.addEventListener('ended', () => { nextMedia(); }); } } function showMedia(index) { currentIndex = (index + slideshowMedia.length) % slideshowMedia.length; loadMedia(currentIndex); } function nextMedia() { showMedia(currentIndex + 1); } function prevMedia() { showMedia(currentIndex - 1); } function resetInterval(duration) { clearTimers(); countdownSeconds = Math.floor(duration / 1000); timerDisplay.textContent = `Next media in: ${countdownSeconds} seconds`; if (!isPaused) { slideshowTimeout = setTimeout(() => { nextMedia(); }, duration); countdownInterval = setInterval(() => { if (!isPaused) { countdownSeconds--; if (countdownSeconds < 0) countdownSeconds = 0; timerDisplay.textContent = `Next media in: ${countdownSeconds} seconds`; } }, 1000); } } function togglePause() { isPaused = !isPaused; if (isPaused) { clearTimers(); if (currentVideo && !currentVideo.paused) currentVideo.pause(); } else { if (currentVideo && currentVideo.paused) currentVideo.play(); resetInterval(countdownSeconds * 1000); } } function keyHandler(e) { if (!slideshowOverlay) return; if (e.key === 'ArrowRight') { nextMedia(); } else if (e.key === 'ArrowLeft') { prevMedia(); } else if (e.key === 'Escape') { closeBtn.click(); } else if (e.code === 'Space') { e.preventDefault(); // prevent page scroll togglePause(); } } document.addEventListener('keydown', keyHandler); showMedia(0); document.body.appendChild(slideshowOverlay); } function addButton() { if (document.getElementById('extract-media-btn')) return; const btn = document.createElement('button'); btn.innerText = 'Start X.com Slideshow'; btn.id = 'extract-media-btn'; btn.style.position = 'fixed'; btn.style.top = '10px'; btn.style.right = '10px'; btn.style.zIndex = '9999'; btn.style.padding = '10px'; btn.style.background = '#1da1f2'; btn.style.color = 'white'; btn.style.border = 'none'; btn.style.borderRadius = '5px'; btn.style.cursor = 'pointer'; btn.title = 'Start slideshow'; btn.addEventListener('click', () => { const media = extractMedia(); showSlideshow(media); }); document.body.appendChild(btn); } const observer = new MutationObserver(() => { addButton(); }); observer.observe(document.body, { childList: true, subtree: true }); addButton(); })();