VideoHelper

看片小助肘 - 支持片头跳过设置,倍速播放记忆,自动全屏设置,音量记忆、截屏功能和自动播放功能

// ==UserScript==
// @name         VideoHelper
// @namespace    https://github.com/Cocowwy/Tampermonkey-Tools
// @version      1.2
// @description  看片小助肘 - 支持片头跳过设置,倍速播放记忆,自动全屏设置,音量记忆、截屏功能和自动播放功能
// @author       Cocowwy
// @match        *://*/*
// @updateUrl    https://github.com/Cocowwy/Tampermonkey-Tools/blob/master/VideoHelper.js
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const STORAGE_KEY = 'video_auto_jump_time';
    const SPEED_STORAGE_KEY = 'video_playback_speed';
    const AUTO_FULLSCREEN_KEY = 'video_auto_fullscreen';
    const VOLUME_STORAGE_KEY = 'video_volume';
    const AUTO_PLAY_KEY = 'video_auto_play';
    let isPanelVisible = false;
    let isDragging = false;
    let startX, startY, initialX, initialY;

    // 创建折叠按钮
    const toggleBtn = document.createElement('div');
    toggleBtn.innerHTML = '📽️';
    toggleBtn.style.cssText = `
        position: fixed;
        left: 10px;
        top: 50%;
        transform: translateY(-50%);
        cursor: pointer;
        z-index: 9999;
        opacity: 0.7;
        transition: opacity 0.3s;
        font-size: 20px;
        border-radius: 50%;
        width: 40px;
        height: 40px;
        display: flex;
        align-items: center;
        justify-content: center;
        color: white;
        background: rgba(0, 0, 0, 0.85);
    `;
    toggleBtn.addEventListener('mouseenter', () => toggleBtn.style.opacity = '1');
    toggleBtn.addEventListener('mouseleave', () => toggleBtn.style.opacity = '0.7');
    document.body.appendChild(toggleBtn);

    // 创建配置面板
    const panel = document.createElement('div');
    panel.style.cssText = `
        position: fixed;
        left: -300px; /* 初始隐藏位置 */
        top: 50%;
        transform: translateY(-50%);
        background: rgba(0, 0, 0, 0.85);
        padding: 20px;
        border-radius: 8px;
        box-shadow: 0 0 15px rgba(0,0,0,0.3);
        transition: all 0.3s ease;
        color: white;
        width: 260px;
        z-index: 9998;
        backdrop-filter: blur(5px);
    `;

    // 拖动处理函数
    const handleMouseDown = (e) => {
        isDragging = true;
        startX = e.clientX;
        startY = e.clientY;
        initialX = panel.offsetLeft;
        initialY = panel.offsetTop;
        panel.style.transition = 'none';
    };

    const handleMouseMove = (e) => {
        if (!isDragging) return;
        const dx = e.clientX - startX;
        const dy = e.clientY - startY;
        panel.style.left = `${initialX + dx}px`;
        panel.style.top = `${initialY + dy}px`;
    };

    const handleMouseUp = () => {
        isDragging = false;
        panel.style.transition = 'all 0.3s ease';
    };

    // 面板内容
    panel.innerHTML = `
        <div style="margin-bottom: 15px; font-weight: bold; font-size: 16px;">
            🎬 视频小助肘
            <div style="float: right; cursor: pointer; opacity: 0.7;" id="closeBtn">×</div>
        </div>
        <div style="margin-bottom: 15px;">
            <label style="display: block; margin-bottom: 8px; font-size: 14px;">
                跳过片头时间(秒):
            </label>
            <input type="number"
                   id="timeInput"
                   style="width: 95%;
                          padding: 8px;
                          border: 1px solid rgba(255,255,255,0.2);
                          border-radius: 4px;
                          background: rgba(255,255,255,0.1);
                          color: white;
                          margin-bottom: 15px;">
            </input>
            <label style="display: block; margin-bottom: 8px; font-size: 14px;">
                播放倍速:
            </label>
            <input type="number"
                   id="speedInput"
                   style="width: 95%;
                          padding: 8px;
                          border: 1px solid rgba(255,255,255,0.2);
                          border-radius: 4px;
                          background: rgba(255,255,255,0.1);
                          color: white;
                          margin-bottom: 15px;">
            </input>
            <label style="display: block; margin-bottom: 8px; font-size: 14px;">
                音量 (0 - 100):
            </label>
            <input type="number"
                   id="volumeInput"
                   min="0"
                   max="100"
                   style="width: 95%;
                          padding: 8px;
                          border: 1px solid rgba(255,255,255,0.2);
                          border-radius: 4px;
                          background: rgba(255,255,255,0.1);
                          color: white;
                          margin-bottom: 15px;">
            </input>
            <label style="display: block; margin-bottom: 8px; font-size: 14px;">
                自动全屏:
            </label>
            <input type="checkbox" id="autoFullscreenCheckbox">
            <label style="display: block; margin-bottom: 8px; font-size: 14px;">
                自动播放:
            </label>
            <input type="checkbox" id="autoPlayCheckbox">
            <button id="saveBtn"
                    style="width: 100%;
                           padding: 8px;
                           background: #2196F3;
                           border: none;
                           border-radius: 4px;
                           color: white;
                           cursor: pointer;
                           transition: background 0.3s;">
                保存
            </button>
            <button id="screenshotBtn"
                    style="width: 100%;
                           padding: 8px;
                           background: #4CAF50;
                           border: none;
                           border-radius: 4px;
                           color: white;
                           cursor: pointer;
                           transition: background 0.3s;
                           margin-top: 10px;">
                视频截屏
            </button>
        </div>
    `;

    // 元素引用
    const timeInput = panel.querySelector('#timeInput');
    const speedInput = panel.querySelector('#speedInput');
    const volumeInput = panel.querySelector('#volumeInput');
    const autoFullscreenCheckbox = panel.querySelector('#autoFullscreenCheckbox');
    const autoPlayCheckbox = panel.querySelector('#autoPlayCheckbox');
    const saveBtn = panel.querySelector('#saveBtn');
    const closeBtn = panel.querySelector('#closeBtn');
    const screenshotBtn = panel.querySelector('#screenshotBtn');

    // 事件监听
    saveBtn.addEventListener('mouseenter', () => saveBtn.style.background = '#1976D2');
    saveBtn.addEventListener('mouseleave', () => saveBtn.style.background = '#2196F3');
    closeBtn.addEventListener('click', () => togglePanel(false));
    panel.addEventListener('mousedown', handleMouseDown);
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);

    // 功能函数
    function togglePanel(show) {
        isPanelVisible = show;
        panel.style.left = show ? '60px' : '-300px'; // 展开时距离左侧60px
        toggleBtn.innerHTML = show ? 'X' : '📽️';
    }

    toggleBtn.addEventListener('click', () => togglePanel(!isPanelVisible));

    // 初始化存储值
    timeInput.value = localStorage.getItem(STORAGE_KEY) || 0;
    speedInput.value = localStorage.getItem(SPEED_STORAGE_KEY) || 1;
    volumeInput.value = localStorage.getItem(VOLUME_STORAGE_KEY) || 100;
    autoFullscreenCheckbox.checked = localStorage.getItem(AUTO_FULLSCREEN_KEY) === 'true';
    autoPlayCheckbox.checked = localStorage.getItem(AUTO_PLAY_KEY) === 'true';

    saveBtn.addEventListener('click', () => {
        const jumpTime = parseInt(timeInput.value, 10);
        const playbackSpeed = parseFloat(speedInput.value);
        const volume = parseInt(volumeInput.value, 10);
        const autoFullscreen = autoFullscreenCheckbox.checked;
        const autoPlay = autoPlayCheckbox.checked;

        if (!isNaN(jumpTime) && !isNaN(playbackSpeed) && !isNaN(volume) && volume >= 0 && volume <= 100) {
            localStorage.setItem(STORAGE_KEY, jumpTime);
            localStorage.setItem(SPEED_STORAGE_KEY, playbackSpeed);
            localStorage.setItem(VOLUME_STORAGE_KEY, volume);
            localStorage.setItem(AUTO_FULLSCREEN_KEY, autoFullscreen);
            localStorage.setItem(AUTO_PLAY_KEY, autoPlay);

            const video = document.querySelector('video');
            if (video) {
                video.currentTime = jumpTime;
                video.playbackRate = playbackSpeed;
                video.volume = volume / 100;
                
                if (autoPlay) {
                    video.play().catch(() => {
                        showToast('⚠️ 自动播放被浏览器阻止,请手动播放');
                    });
                }
            }

            showToast('✅ 设置已保存');
        } else {
            showToast('⚠️ 请输入有效数字,音量范围为 0 - 100');
        }
    });

    // 视频处理
    const video = document.querySelector('video');
    if (video) {
        video.addEventListener('loadedmetadata', () => {
            const jumpTime = parseInt(localStorage.getItem(STORAGE_KEY), 10);
            const playbackSpeed = parseFloat(localStorage.getItem(SPEED_STORAGE_KEY));
            const volume = parseFloat(localStorage.getItem(VOLUME_STORAGE_KEY));
            const autoFullscreen = localStorage.getItem(AUTO_FULLSCREEN_KEY) === 'true';

            if (!isNaN(jumpTime) && jumpTime <= video.duration) {
                video.currentTime = jumpTime;
            }
            if (!isNaN(playbackSpeed)) {
                video.playbackRate = playbackSpeed;
            }
            if (!isNaN(volume) && volume >= 0 && volume <= 100) {
                video.volume = volume / 100;
            }
        });

        video.addEventListener('play', () => {
            const autoFullscreen = localStorage.getItem(AUTO_FULLSCREEN_KEY) === 'true';
            if (autoFullscreen) {
                if (video.requestFullscreen) {
                    video.requestFullscreen();
                } else if (video.webkitRequestFullscreen) {
                    video.webkitRequestFullscreen();
                } else if (video.msRequestFullscreen) {
                    video.msRequestFullscreen();
                } else if (video.mozRequestFullscreen) {
                    video.mozRequestFullscreen();
                } else {
                    showToast('⚠️ 当前浏览器不支持全屏功能');
                }
            }
        });
    }

    // 截屏功能
    screenshotBtn.addEventListener('click', () => {
        const video = document.querySelector('video');
        if (video) {
            const canvas = document.createElement('canvas');
            canvas.width = video.videoWidth;
            canvas.height = video.videoHeight;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

            const link = document.createElement('a');
            link.href = canvas.toDataURL('image/png');
            link.download = 'video_screenshot.png';
            link.click();

            showToast('📸 截屏已保存');
        } else {
            showToast('⚠️ 未找到视频元素');
        }
    });

    // 提示信息函数
    function showToast(message) {
        const toast = document.createElement('div');
        toast.textContent = message;
        toast.style.cssText = `
            position: fixed;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0,0,0,0.8);
            color: white;
            padding: 12px 24px;
            border-radius: 4px;
            font-size: 14px;
            z-index: 10000;
            animation: fadeInOut 2.5s;
        `;
        document.body.appendChild(toast);
        setTimeout(() => toast.remove(), 2500);
    }

    // 注入CSS动画
    const style = document.createElement('style');
    style.textContent = `
        @keyframes fadeInOut {
            0% { opacity: 0; transform: translate(-50%, 10px); }
            15% { opacity: 1; transform: translate(-50%, 0); }
            85% { opacity: 1; transform: translate(-50%, 0); }
            100% { opacity: 0; transform: translate(-50%, -10px); }
        }
    `;
    document.head.appendChild(style);

    document.body.appendChild(panel);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址