HTML5 Video Screenshot with Button

Capture screenshot from HTML5 video player using button or Ctrl+Shift+S

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

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

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

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

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

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.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         HTML5 Video Screenshot with Button
// @version      1.0
// @description  Capture screenshot from HTML5 video player using button or Ctrl+Shift+S
// @match        *://*/*
// @grant        none
// @license MIT
// @namespace https://greasyfork.org/users/1349839
// ==/UserScript==

(function() {
    'use strict';

    function captureScreenshot(video) {
        const canvas = document.createElement('canvas');
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);

        canvas.toBlob((blob) => {
            navigator.clipboard.write([
                new ClipboardItem({ 'image/png': blob })
            ]).then(() => {
                showTip('Screenshot copied to clipboard');
            }).catch((error) => {
                showTip('Failed to copy screenshot', true);
                console.error('Failed to copy screenshot: ', error);
            });
        }, 'image/png');
    }

    function showTip(message, isError = false) {
        const tip = document.createElement('div');
        tip.textContent = message;
        tip.style.position = 'fixed';
        tip.style.bottom = '20px';
        tip.style.right = '20px';
        tip.style.padding = '10px';
        tip.style.backgroundColor = isError ? 'rgba(255, 0, 0, 0.8)' : 'rgba(0, 0, 0, 0.8)';
        tip.style.color = 'white';
        tip.style.borderRadius = '5px';
        tip.style.zIndex = '9999999';
        document.body.appendChild(tip);
        setTimeout(() => tip.remove(), 3000);
    }

    function createButton(text, onClick) {
        const button = document.createElement('button');
        button.textContent = text;
        button.style.padding = '5px 10px';
        button.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.borderRadius = '5px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '16px';
        button.style.transition = 'opacity 0.3s';
        button.style.opacity = '0';
        button.onclick = onClick;
        return button;
    }

    function addControlsToVideo(video) {
        const wrapper = document.createElement('div');
        wrapper.style.position = 'absolute';
        wrapper.style.top = '10px';
        wrapper.style.right = '10px';
        wrapper.style.zIndex = '9999998';

        const screenshotButton = createButton('📷', (e) => {
            e.preventDefault();
            e.stopPropagation();
            captureScreenshot(video);
        });

        wrapper.appendChild(screenshotButton);

        let hideTimeout;
        let isMouseOverControls = false;

        function showControls() {
            screenshotButton.style.opacity = '1';
            clearTimeout(hideTimeout);
            if (!isMouseOverControls) {
                hideTimeout = setTimeout(() => {
                    if (!isMouseOverControls) {
                        screenshotButton.style.opacity = '0';
                    }
                }, 2000);
            }
        }

        // Show controls on mouse move and hide after 2 seconds of inactivity
        video.parentElement.addEventListener('mousemove', showControls);
        video.parentElement.addEventListener('mouseenter', showControls);

        // Clear timeout when leaving the video area
        video.parentElement.addEventListener('mouseleave', () => {
            if (!isMouseOverControls) {
                screenshotButton.style.opacity = '0';
                clearTimeout(hideTimeout);
            }
        });

        // Keep controls visible when mouse is over them
        wrapper.addEventListener('mouseenter', () => {
            isMouseOverControls = true;
            clearTimeout(hideTimeout);
            screenshotButton.style.opacity = '1';
        });

        wrapper.addEventListener('mouseleave', () => {
            isMouseOverControls = false;
            showControls();
        });

        // Create a wrapper for the video if it doesn't exist
        let videoWrapper = video.parentElement;
        if (!videoWrapper.style.position || videoWrapper.style.position === 'static') {
            videoWrapper = document.createElement('div');
            videoWrapper.style.position = 'relative';
            videoWrapper.style.display = 'inline-block';
            video.parentNode.insertBefore(videoWrapper, video);
            videoWrapper.appendChild(video);
        }

        videoWrapper.appendChild(wrapper);

        // Add keyboard shortcut functionality to the button
        screenshotButton.addEventListener('keydown', function(e) {
            if (e.ctrlKey && e.shiftKey && e.key === 'S') {
                e.preventDefault();
                captureScreenshot(video);
            }
        });
    }

    // Listen for the shortcut key (Ctrl+Shift+S)
    document.addEventListener('keydown', function(e) {
        if (e.ctrlKey && e.shiftKey && e.key === 'S') {
            e.preventDefault();
            const video = document.querySelector('video');
            if (video) {
                captureScreenshot(video);
            } else {
                showTip('No video element found on the page', true);
            }
        }
    });

    // Add controls to video players
    function addControlsToVideos() {
        const videos = document.querySelectorAll('video');
        videos.forEach(addControlsToVideo);
    }

    // Initial addition of controls
    addControlsToVideos();

    // Use a MutationObserver to add controls to dynamically loaded videos
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            if (mutation.addedNodes) {
                mutation.addedNodes.forEach((node) => {
                    if (node.nodeName === 'VIDEO') {
                        addControlsToVideo(node);
                    } else if (node.querySelector) {
                        const videos = node.querySelectorAll('video');
                        videos.forEach(addControlsToVideo);
                    }
                });
            }
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();