您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
SOOP 라이브 및 클립 창에서 화면 캡쳐시 플레이어 컨트롤러 부분을 보이지 않게 할 수 있도록 컨트롤러 비활성화/캡쳐 버튼을 추가합니다.
当前为
// ==UserScript== // @name SOOP 클립 및 라이브 깔끔하게 캡쳐 // @namespace http://tampermonkey.net/ // @version 1.1 // @license MIT // @description SOOP 라이브 및 클립 창에서 화면 캡쳐시 플레이어 컨트롤러 부분을 보이지 않게 할 수 있도록 컨트롤러 비활성화/캡쳐 버튼을 추가합니다. // @author Linseed, Gemini // @match https://stbbs.sooplive.co.kr/vodclip/create.php // @match https://play.sooplive.co.kr/* // @require https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // --- 스크립트 설정 --- const CHECK_INTERVAL = 500; // 플레이어 요소를 찾기 위한 반복 확인 간격 (ms) /** * 필요한 DOM 요소들이 로드될 때까지 기다립니다. * videoLayer와 player_ctrlBox가 모두 존재하면 main 함수를 실행합니다. */ const waitForElements = setInterval(() => { const videoLayer = document.getElementById('videoLayer'); const ctrlBox = document.querySelector('.player_ctrlBox'); const titleElement = document.querySelector('.u_clip_title'); const nicknameElement = document.querySelector('.nickname'); if (videoLayer && ctrlBox && (titleElement || nicknameElement)) { clearInterval(waitForElements); main(videoLayer, ctrlBox, titleElement, nicknameElement); } }, CHECK_INTERVAL); /** * 스크립트의 메인 로직을 실행합니다. * @param {HTMLElement} videoLayer - 캡쳐할 대상이 되는 비디오 레이어 요소 * @param {HTMLElement} ctrlBox - 숨기거나 표시할 컨트롤 박스 요소 * @param {HTMLElement | null} titleElement - 버튼을 추가할 제목 요소 * @param {HTMLElement | null} nicknameElement - 버튼을 추가할 닉네임 요소 */ function main(videoLayer, ctrlBox, titleElement, nicknameElement) { // --- 1. 상태 변수 정의 --- let isLocked = false; // --- 2. UI 요소 생성 --- const container = document.createElement('div'); container.id = 'soop-script-container'; if (titleElement) { // u_clip_title class의 맨 위에 버튼 컨테이너를 추가합니다. titleElement.prepend(container); } else if (nicknameElement) { // nickname class의 바로 뒤에 버튼 컨테이너를 추가합니다. nicknameElement.after(container); } const lockButton = document.createElement('button'); lockButton.id = 'lockBtn'; lockButton.textContent = '🔓'; lockButton.title = '컨트롤러 잠금/해제'; container.appendChild(lockButton); const captureButton = document.createElement('button'); captureButton.id = 'captureBtn'; captureButton.textContent = '📷'; captureButton.title = '현재 화면 캡쳐'; container.appendChild(captureButton); // --- 3. UI 스타일 적용 --- GM_addStyle(` #soop-script-container { display: inline-flex; gap: 8px; margin-left: 10px; vertical-align: middle; } #soop-script-container button { padding: 4px 8px; font-size: 16px; border: 1px solid #ccc; border-radius: 6px; background-color: rgba(240, 240, 240, 0.85); cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,0.1); transition: all 0.2s ease-in-out; line-height: 1; } #soop-script-container button:hover { background-color: rgba(255, 255, 255, 1); transform: translateY(-1px); } `); // --- 4. 핵심 기능 함수 정의 --- /** * 잠금 상태를 설정하고 UI를 업데이트합니다. * @param {boolean} locked - 설정할 잠금 상태 (true: 잠김, false: 열림) */ const setLockState = (locked) => { isLocked = locked; lockButton.textContent = isLocked ? '🔒' : '🔓'; // display 속성을 변경하여 컨트롤 박스를 숨기거나 표시합니다. ctrlBox.style.display = isLocked ? 'none' : ''; }; // --- 5. 이벤트 리스너 등록 --- // 잠금 버튼 클릭 이벤트 lockButton.addEventListener('click', () => { setLockState(!isLocked); }); // 캡쳐 버튼 클릭 이벤트 captureButton.addEventListener('click', async () => { const originalLockState = isLocked; // 1. 캡쳐를 위해 컨트롤러를 일시적으로 숨깁니다. if (!originalLockState) { setLockState(true); // UI가 업데이트될 시간을 잠시 기다립니다 (100ms). await new Promise(resolve => setTimeout(resolve, 100)); } // 2. html2canvas를 사용하여 비디오 레이어를 캡쳐합니다. try { const canvas = await html2canvas(videoLayer, { useCORS: true, // 외부 소스 비디오 캡쳐를 위해 필요할 수 있습니다. }); const link = document.createElement('a'); // 파일명에 날짜와 시간을 포함하여 중복을 방지합니다. const timestamp = new Date().toISOString().slice(0, 19).replace(/[-T:]/g, ''); link.download = `soop-capture-${timestamp}.png`; link.href = canvas.toDataURL('image/png'); link.click(); } catch (error) { console.error('스크립트 캡쳐 오류:', error); alert('화면 캡쳐에 실패했습니다. 브라우저 콘솔을 확인해주세요.'); } finally { // 3. 캡쳐가 끝나면 원래 잠금 상태로 복구합니다. if (!originalLockState) { setLockState(false); } } }); } })();