VideoHelper

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

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==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);
})();