Video Control with Reload

为指定视频添加可移动的进度条、音量控制器和重新加载按钮

目前為 2024-06-29 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Video Control with Reload
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  为指定视频添加可移动的进度条、音量控制器和重新加载按钮
// @match        https://app.kosmi.io/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    let videoElement = null;
    let isCompacted = false; // 控制器是否缩小为一个小方块

    // 创建控制器
    // 创建控制器
function createController() {
    const controller = document.createElement('div');
    controller.id = 'video-controller';
    controller.style.cssText = `
        position: fixed;
        bottom: 20px;
        left: 50%;
        transform: translateX(-50%);
        background-color: rgba(0, 0, 0, 0.7);
        color: white;
        padding: 10px;
        border-radius: 5px;
        z-index: 9999;
        cursor: move;
        user-select: none;
        width: 300px;
        transition: width 0.3s, height 0.3s;
    `;
    controller.innerHTML = `
        <div id="progress-container" style="width: 100%; height: 10px; background-color: #444; position: relative; cursor: pointer;">
            <div id="progress-indicator" style="width: 0%; height: 100%; background-color: #fff; position: absolute;"></div>
        </div>
        <div id="time-display" style="text-align: center; margin-top: 5px;">0:00 / 0:00</div>
        <div id="volume-container" style="display: flex; align-items: center; margin-top: 10px;">
            <span id="volume-icon" style="margin-right: 10px;">🔊</span>
            <input type="range" id="volume-slider" min="0" max="1" step="0.1" value="1" style="flex-grow: 1;">
        </div>
        <button id="reload-button" style="width: 100%; margin-top: 10px; padding: 5px; background-color: #4CAF50; border: none; color: white; cursor: pointer;">重新加载视频控制</button>
        <button id="compact-button" style="width: 100%; margin-top: 10px; padding: 5px; background-color: #2196F3; border: none; color: white; cursor: pointer;">缩小控制器</button>
    `;
    document.body.appendChild(controller);
    return controller;
}

    // 使控制器可拖动
    function makeDraggable(element) {
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        element.onmousedown = dragMouseDown;

        function dragMouseDown(e) {
            if (e.target.id === 'progress-container' || e.target.id === 'progress-indicator' || e.target.id === 'volume-slider' || e.target.id === 'reload-button') return;
            e = e || window.event;
            e.preventDefault();
            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
            document.onmousemove = elementDrag;
        }

        function elementDrag(e) {
            e = e || window.event;
            e.preventDefault();
            pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
            element.style.top = (element.offsetTop - pos2) + "px";
            element.style.left = (element.offsetLeft - pos1) + "px";
            element.style.bottom = 'auto';
            element.style.transform = 'none';
        }

        function closeDragElement() {
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }

    // 格式化时间
    function formatTime(seconds) {
        const minutes = Math.floor(seconds / 60);
        seconds = Math.floor(seconds % 60);
        return `${minutes}:${seconds.toString().padStart(2, '0')}`;
    }

    // 主函数
    function main() {
        // 先移除已存在的控制器元素
        const existingController = document.getElementById('video-controller');
        if (existingController) {
            existingController.remove();
        }

        videoElement = document.querySelector('video[src^="blob:https://app.kosmi.io/"]');
        if (!videoElement) {
            console.log('未找到指定视频');
            return;
        }

        const controller = createController();
        makeDraggable(controller);

        const progressContainer = document.getElementById('progress-container');
        const progressIndicator = document.getElementById('progress-indicator');
        const timeDisplay = document.getElementById('time-display');
        const volumeSlider = document.getElementById('volume-slider');
        const volumeIcon = document.getElementById('volume-icon');
        const reloadButton = document.getElementById('reload-button');

        // 更新进度
        function updateProgress() {
            const progress = (videoElement.currentTime / videoElement.duration) * 100;
            progressIndicator.style.width = `${progress}%`;
            const current = formatTime(videoElement.currentTime);
            const total = formatTime(videoElement.duration);
            timeDisplay.textContent = `${current} / ${total}`;
        }

        // 点击进度条更新视频位置
        progressContainer.addEventListener('click', function(e) {
            const rect = progressContainer.getBoundingClientRect();
            const pos = (e.clientX - rect.left) / rect.width;
            videoElement.currentTime = pos * videoElement.duration;
        });

        // 更新音量
        volumeSlider.addEventListener('input', function() {
            videoElement.volume = this.value;
            updateVolumeIcon(this.value);
        });

        // 更新音量图标
        function updateVolumeIcon(volume) {
            if (volume > 0.5) {
                volumeIcon.textContent = '🔊';
            } else if (volume > 0) {
                volumeIcon.textContent = '🔉';
            } else {
                volumeIcon.textContent = '🔇';
            }
        }

        // 初始化音量
        volumeSlider.value = videoElement.volume;
        updateVolumeIcon(videoElement.volume);

        // 重新加载按钮事件
        reloadButton.addEventListener('click', function() {
            // 移除旧的事件监听器
            videoElement.removeEventListener('timeupdate', updateProgress);
            videoElement.removeEventListener('loadedmetadata', updateProgress);

            // 重新执行主函数
            main();

            // 重新绑定事件监听器
            videoElement.addEventListener('timeupdate', updateProgress);
            videoElement.addEventListener('loadedmetadata', updateProgress);
        });

        videoElement.addEventListener('timeupdate', updateProgress);
        videoElement.addEventListener('loadedmetadata', updateProgress);
            const compactButton = document.getElementById('compact-button');

    // 缩小/展开控制器
    compactButton.addEventListener('click', function() {
        isCompacted = !isCompacted;
        if (isCompacted) {
            controller.style.width = '50px';
            controller.style.height = '50px';
            controller.style.overflow = 'hidden';
            compactButton.textContent = '展开控制器';
        } else {
            controller.style.width = '300px';
            controller.style.height = 'auto';
            controller.style.overflow = 'visible';
            compactButton.textContent = '缩小控制器';
        }
    });
    }

    // 等待视频加载完成
    function waitForVideo() {
        console.log('waitForVideo');
        const video = document.querySelector('video[src^="blob:https://app.kosmi.io/"]');
        if (video) {
            main();
        } else {
            setTimeout(waitForVideo, 1000);
        }
    }

    waitForVideo();
    console.log('1111111111waitForVideo');
})();