TesterTV_YouTube_Screenshots

Create YouTube Screenshots

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         TesterTV_YouTube_Screenshots
// @namespace    https://greasyfork.org/ru/scripts/482417-testertv-youtube-screenshots
// @version      2023.12.16
// @description  Create YouTube Screenshots
// @license      GPL version 3 or any later version
// @author       TesterTV
// @match        https://www.youtube.com/*
// @match        https://m.youtube.com/*
// @match        https://music.youtube.com/*
// @grant        GM_download
// ==/UserScript==


setInterval(function() {
    if (window.location.href !== "https://www.youtube.com" && window.location.href !== "https://www.youtube.com/" && window.location.href !== "https://m.youtube.com/" && window.location.href !== "https://m.youtube.com" && window.location.href !== "https://music.youtube.com/" && window.location.href !== "https://music.youtube.com") {
        // Check if the page contains an element with id "ButtonEffects"
        if (!document.getElementById("ScreenshotButton")) {
            // If the element isn't found, start the effects script
            YoutubeScreenshots();
        }
    }
}, 1000);

function YoutubeScreenshots() {

    // Check if current window isn't an iframe
    var isInIframe = window === window.top;
    if (isInIframe) {

//********************************************************************************************************************
//***                                             Screenshot 📷                                                   ***
//********************************************************************************************************************

//***************************
//*** ButtonScreenshot 📷 ***
//***************************

    // Create the screenshot button
    const ScreenshotButton = document.createElement('button');
    ScreenshotButton.id = 'ScreenshotButton';
    ScreenshotButton.style.position = 'relative';
    ScreenshotButton.textContent = '📷';
    ScreenshotButton.style.fontSize = '20px';
    ScreenshotButton.style.background = 'none';
    ScreenshotButton.style.border = "3px solid rgba(0, 0, 0, 0)";
    ScreenshotButton.style.color = 'white';
    ScreenshotButton.style.margin = '6px 10px 0';
    ScreenshotButton.style.height= '34px';
    ScreenshotButton.style.width= '36px';
    ScreenshotButton.style.borderRadius = '5%';
    ScreenshotButton.style.left = '10px';
    ScreenshotButton.style.display = 'flex';
    ScreenshotButton.style.justifyContent = 'center';
    ScreenshotButton.style.alignItems = 'center';

    // Insert into the YouTube player controls
    var ControlsLeft = document.querySelector('.ytp-left-controls');
    ControlsLeft.style.position = 'relative';
    ControlsLeft.style.display = 'flex';
    //ControlsLeft.style.alignItems = 'center';
    var TimeDisplay = document.querySelector('.ytp-time-display');
    ControlsLeft.insertBefore(ScreenshotButton, TimeDisplay.nextSibling);

//********************************************************************************************************************
//***                               Listener event - Screenshot function 📷👂                                      ***
//********************************************************************************************************************

    // Add event listener to the screenshot button
    ScreenshotButton.addEventListener("click", function(event) {
        const VideoElement = document.querySelector('video');
        const Canvas = document.createElement('canvas');
        const Context = Canvas.getContext('2d');
        Canvas.width = VideoElement.videoWidth;
        Canvas.height = VideoElement.videoHeight;
        Context.drawImage(VideoElement, 0, 0, Canvas.width, Canvas.height);

        // Get the current video timing
        const CurrentTime = VideoElement.currentTime;
        const Hours = Math.floor(CurrentTime / 3600);
        const Minutes = Math.floor((CurrentTime % 3600) / 60);
        const Seconds = Math.floor(CurrentTime % 60);
        const FormattedTime = `${Hours.toString().padStart(2, '0')}:${Minutes.toString().padStart(2, '0')}:${Seconds.toString().padStart(2, '0')}`;

        // Save the screenshot to local drive with the timing in the filename
        const ScreenshotImage = Canvas.toDataURL('image/png');
        GM_download({
            url: ScreenshotImage,
            name: `screenshot_${FormattedTime}.png`,

            // Screenshot will be downloaded directly to the download folder without asking the user for the title or location.
            saveAs: false //"true" for SaveAs request
        });

        // Set focus on player
        var playButton = document.querySelector('.html5-main-video');
        playButton.focus();

    });

//****************************************
//***   Listener event - Button 📷👂   ***
//****************************************

    // Add an event listener to check if the user has pressed the screenshot button
    ScreenshotButton.addEventListener("click", function(event) {
        ScreenshotButton.style.border = "3px solid rgba(255, 0, 0, 0.5)";

          if (ScreenshotButton) {
              setTimeout(function() {
                  ScreenshotButton.style.border = "3px solid rgba(0, 0, 0, 0)";
              }, 150);
          }

    });

    // Add mouseover event listener to the button...
	ScreenshotButton.addEventListener('mouseover', function() {
		ScreenshotButton.style.border = "3px solid #74e3ff";
	});

    // Add mouseover event listener to the button...
    ScreenshotButton.addEventListener('mouseleave', function() {
        ScreenshotButton.style.border = "3px solid rgba(0, 0, 0, 0)";
    });

//********************************************************************************************************************
//***                                         Screenshot drawing 📸🖌️                                             ***
//********************************************************************************************************************

//***************************
//***  ButtonShow/Hide 👀 ***
//***************************

    // Create the hide/show draw options button
    const ButtonDrawHideShow = document.createElement('button');
    ButtonDrawHideShow.id = 'ButtonDrawHideShow';
    ButtonDrawHideShow.style.position = 'relative';
    ButtonDrawHideShow.textContent = '🖌️';
    ButtonDrawHideShow.style.fontSize = '20px';
    ButtonDrawHideShow.style.background = 'none';
    ButtonDrawHideShow.style.border = "3px solid rgba(0, 0, 0, 0)";
    ButtonDrawHideShow.style.color = 'white';
    ButtonDrawHideShow.style.margin = '6px 0px 0';
    ButtonDrawHideShow.style.height= '34px';
    ButtonDrawHideShow.style.width= '36px';
    ButtonDrawHideShow.style.borderRadius = '5%';
    ButtonDrawHideShow.style.left = '10px';
    ButtonDrawHideShow.style.display = 'flex';
    ButtonDrawHideShow.style.justifyContent = 'center';
    ButtonDrawHideShow.style.alignItems = 'center';

    // Insert into the YouTube player controls
    //var ControlsLeft = document.querySelector('.ytp-left-controls');
    ControlsLeft.style.position = 'relative';
    ControlsLeft.style.display = 'flex';
    //ControlsLeft.style.alignItems = 'center';
    //var TimeDisplay = document.querySelector('.ytp-time-display');
    ControlsLeft.insertBefore(ButtonDrawHideShow, TimeDisplay.nextSibling);

//**********************************
//*** ButtonScreenshotForDraw 📸 ***
//**********************************

    // Create button
    const ButtonScreenshotForDraw = document.createElement('button');
    ButtonScreenshotForDraw.id = "ButtonScreenshotForDraw"
    ButtonScreenshotForDraw.style.position = 'fixed';
    ButtonScreenshotForDraw.style.height= '34px';
    ButtonScreenshotForDraw.style.width= '36px';
    ButtonScreenshotForDraw.style.top = '80px';
    ButtonScreenshotForDraw.style.left = '10px';
    ButtonScreenshotForDraw.textContent = '📸';
    ButtonScreenshotForDraw.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
    ButtonScreenshotForDraw.style.border = '1px solid grey';
    ButtonScreenshotForDraw.style.fontSize = '20px';
    ButtonScreenshotForDraw.style.display = 'flex';
    ButtonScreenshotForDraw.style.justifyContent = 'center';
    ButtonScreenshotForDraw.style.alignItems = 'center';
    ButtonScreenshotForDraw.style.zIndex = '9995';
    ButtonScreenshotForDraw.style.display = 'none'
    document.body.appendChild(ButtonScreenshotForDraw);

//*************************
//***  Color picker 🎨 ***
//*************************

    // Create color picker
    const ColorPicker = document.createElement('input');
    ColorPicker.id = 'ColorPicker';
    ColorPicker.type = 'color';
    ColorPicker.style.position = 'fixed';
    ColorPicker.style.width= '36px'
    ColorPicker.style.top = '120px';
    ColorPicker.style.left = '10px';
    ColorPicker.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
    ColorPicker.style.border = '1px solid grey';
    ColorPicker.value = '#74e3ff'; // Initial color is red
    ColorPicker.style.zIndex = '9996';
    ColorPicker.style.display = 'none'
    document.body.appendChild(ColorPicker);

//***************************
//***    ButtonSave 💾   ***
//***************************

    // Create save button
    const SaveButton = document.createElement('button');
    SaveButton.id = "SaveButton"
    SaveButton.style.position = 'fixed';
    SaveButton.style.height= '34px';
    SaveButton.style.width= '36px';
    SaveButton.style.top = '158px';
    SaveButton.style.left = '10px';
    SaveButton.textContent = '💾';
    SaveButton.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
    SaveButton.style.border = '1px solid grey';
    SaveButton.style.fontSize = '20px';
    SaveButton.style.zIndex = '9997';
    SaveButton.style.display = 'none'
    document.body.appendChild(SaveButton);

//***************************
//***   ExitDrawMode ❌  ***
//***************************

    // Create exit button
    const ButtonExitDraw = document.createElement('button');
    ButtonExitDraw.id = "ButtonExitDraw"
    ButtonExitDraw.style.position = 'fixed';
    ButtonExitDraw.style.height= '34px';
    ButtonExitDraw.style.width= '36px';
    ButtonExitDraw.style.top = '198px';
    ButtonExitDraw.style.left = '10px';
    ButtonExitDraw.textContent = '❌';
    ButtonExitDraw.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
    ButtonExitDraw.style.border = '1px solid grey';
    ButtonExitDraw.style.fontSize = '20px';
    ButtonExitDraw.style.zIndex = '9998';
    ButtonExitDraw.style.display = 'none'
    document.body.appendChild(ButtonExitDraw);

//*************************
//***   Container 📦   ***
//*************************

    // Create image container
    const ImageContainer = document.createElement('div');
    ImageContainer.id = 'ImageContainer';
    ImageContainer.style.position = 'fixed';
    ImageContainer.style.transform = 'translate(-50%, -50%)';
    ImageContainer.style.top = '50%';
    ImageContainer.style.left = '50%';
    ImageContainer.style.display = 'none';
    ImageContainer.style.zIndex = '9990';
    ImageContainer.style.display = 'none'
    document.body.appendChild(ImageContainer);

//***************************
//***Take a Screenshot 🖼️***
//***************************

    // Create canvas for drawing
    const canvas = document.createElement('canvas');
    canvas.style.position = 'absolute';
    canvas.style.top = '50%';
    canvas.style.left = '50%';
    canvas.style.transform = 'translate(-50%, -50%)';
    ImageContainer.appendChild(canvas);
    const context = canvas.getContext('2d');

//*****************************
//***BrushThicknessSlider 🎚️***
//*****************************

    // Create the BrushThicknessSlider element
    var BrushThicknessSlider = document.createElement('input');
    BrushThicknessSlider.id = 'BrushThicknessSlider';
    BrushThicknessSlider.type = 'range';
    BrushThicknessSlider.min = '1';
    BrushThicknessSlider.max = '30';
    BrushThicknessSlider.step = '0.1';
    BrushThicknessSlider.value = '5';
    BrushThicknessSlider.style.transform = 'rotate(270deg)'; // Rotate the slider vertically
    BrushThicknessSlider.style.position = 'absolute';
    BrushThicknessSlider.style.zIndex = '9999';
    BrushThicknessSlider.style.display = 'none'

    // Chnage sliders color
    BrushThicknessSlider.style.background = ColorPicker.value;
    BrushThicknessSlider.style.border = 'none';
    BrushThicknessSlider.style.height = '5px';
    BrushThicknessSlider.style.top = '151px';
    BrushThicknessSlider.style.left = '-15px';
    BrushThicknessSlider.style.width = '152px';
    BrushThicknessSlider.style.outline = 'none';
    BrushThicknessSlider.style.appearance = 'none';
    BrushThicknessSlider.style.webkitAppearance = 'none';
    BrushThicknessSlider.style.mozAppearance = 'none';
    BrushThicknessSlider.style.msAppearance = 'none';
    BrushThicknessSlider.style.webkitSliderThumb = '-webkit-slider-thumb';
    BrushThicknessSlider.style.mozSliderThumb = '-moz-slider-thumb';
    BrushThicknessSlider.style.msSliderThumb = '-ms-slider-thumb';
    BrushThicknessSlider.style.sliderThumb = 'slider-thumb';

    // Append the slider to the document body or any other desired parent element
    document.body.appendChild(BrushThicknessSlider);

//********************************************************************************************************************
//***                               Listener event - Screenshot draw 🖌️👂                                          ***
//********************************************************************************************************************

//****************************************
//***   ButtonDrawHideShow 🖌️👂        ***
//****************************************

    // Add an event listener to check if the user has pressed the screenshot button
    ButtonDrawHideShow.addEventListener("click", function(event) {
        ButtonDrawHideShow.style.border = "3px solid rgba(255, 0, 0, 0.5)";
          if (ButtonDrawHideShow) {
              setTimeout(function() {
                  ButtonDrawHideShow.style.border = "3px solid rgba(0, 0, 0, 0)";
              }, 150);
          }
    });

    // Add mouseover event listener to the button...
	ButtonDrawHideShow.addEventListener('mouseover', function() {
		ButtonDrawHideShow.style.border = "3px solid #74e3ff";
	});

    // Add mouseover event listener to the button...
    ButtonDrawHideShow.addEventListener('mouseleave', function() {
        ButtonDrawHideShow.style.border = "3px solid rgba(0, 0, 0, 0)";
    });

//************************************
//*** DrawFunctionsHide/Show 🖌️🖼️ ***
//************************************

    // Add event listener to the draw button. Function to show/hide video frame
    document.getElementById("ButtonDrawHideShow").addEventListener("click", function(event) {

        if (ImageContainer.style.display === 'none') {
            ButtonScreenshotForDraw.style.display = 'block';
            ColorPicker.style.display = 'block';
            SaveButton.style.display = 'block';
            ButtonExitDraw.style.display = 'block'
            BrushThicknessSlider.style.display = 'block'

            ButtonScreenshotForDraw.style.display = 'flex';
            ButtonScreenshotForDraw.style.justifyContent = 'center';
            ButtonScreenshotForDraw.style.alignItems = 'center';

            ColorPicker.style.display = 'flex';
            ColorPicker.style.justifyContent = 'center';
            ColorPicker.style.alignItems = 'center';

            SaveButton.style.display = 'flex';
            SaveButton.style.justifyContent = 'center';
            SaveButton.style.alignItems = 'center';

            ButtonExitDraw.style.display = 'flex';
            ButtonExitDraw.style.justifyContent = 'center';
            ButtonExitDraw.style.alignItems = 'center';

            //Click Screenshot button
            var button = document.getElementById('ButtonScreenshotForDraw');
            if (button) {button.click();}

        } else {
            ButtonScreenshotForDraw.style.display = 'none';
            ColorPicker.style.display = 'none';
            SaveButton.style.display = 'none';
            ButtonExitDraw.style.display = 'none'
            BrushThicknessSlider.style.display = 'none'

            // Hide video frame
            canvas.removeEventListener('mousedown', startDrawing);
            canvas.removeEventListener('mousemove', draw);
            canvas.removeEventListener('mouseup', stopDrawing);
            canvas.removeEventListener('mouseout', stopDrawing);

            ImageContainer.style.display = 'none';
        }
    });

//*****************************
//***   DrawControl 🖱️🖼️   ***
//*****************************

    // Add event listener to the draw button. Function to show/hide video frame
    document.getElementById("ButtonScreenshotForDraw").addEventListener("click", function(event) {

        //Remove old screenshot
            canvas.removeEventListener('mousedown', startDrawing);
            canvas.removeEventListener('mousemove', draw);
            canvas.removeEventListener('mouseup', stopDrawing);
            canvas.removeEventListener('mouseout', stopDrawing);
            ImageContainer.style.display = 'none';

        //Create new screenshot
        const videoElement = document.querySelector('video');

        // Show video frame
        canvas.width = videoElement.videoWidth;
        canvas.height = videoElement.videoHeight;
        context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);

        // Add mouse event listeners for drawing
        canvas.addEventListener('mousedown', startDrawing);
        canvas.addEventListener('mousemove', draw);
        canvas.addEventListener('mouseup', stopDrawing);
        canvas.addEventListener('mouseout', stopDrawing);

        ImageContainer.style.display = 'block';
    });

//***************************
//***      Drawing 🖌️    ***
//***************************

    // Variables for drawing
    let isDrawing = false;
    let lastX = 0;
    let lastY = 0;

    // Set initial drawing color
    let DrawingColor = ColorPicker.value;

    // Add event listener to the color picker. Function to change drawing color
    document.getElementById("ColorPicker").addEventListener("change", function(event) {
        DrawingColor = ColorPicker.value;
        BrushThicknessSlider.style.background = ColorPicker.value;
    });

    function draw(e) {
        if (!isDrawing) return;

        context.beginPath();
        context.moveTo(lastX, lastY);
        context.lineTo(e.offsetX, e.offsetY);

        context.strokeStyle = DrawingColor;
        //context.lineWidth = 5;
        context.lineWidth = BrushThicknessSlider.value;

        context.lineCap = 'round';
        context.stroke();

        [lastX, lastY] = [e.offsetX, e.offsetY];
    }

    function startDrawing(e) {
        isDrawing = true;
        [lastX, lastY] = [e.offsetX, e.offsetY];
    }

    function stopDrawing() {
        isDrawing = false;
    }

//****************************
//*** ScreenshotSave 💾🖼️ ***
//****************************

    // Add event listener to the save button
    document.getElementById("SaveButton").addEventListener("click", function(event) {
        // Get the current video timing
        const VideoElement = document.querySelector('video');
        const CurrentTime = VideoElement.currentTime;
        const Hours = Math.floor(CurrentTime / 3600);
        const Minutes = Math.floor((CurrentTime % 3600) / 60);
        const Seconds = Math.floor(CurrentTime % 60);
        const FormattedTime = `${Hours.toString().padStart(2, '0')}:${Minutes.toString().padStart(2, '0')}:${Seconds.toString().padStart(2, '0')}`;

        const dataUrl = canvas.toDataURL('image/png');
        GM_download({
            url: dataUrl,
            name: `screenshot_${FormattedTime}.png`,

            //Video will be downloaded directly to the download folder without asking the user for the title or location.
            saveAs: false //"true" for SaveAs request
        });
    });

//****************************
//*** ScreenshotExit ❌🖼️ ***
//****************************

    // Add event listener to the save button
    document.getElementById("ButtonExitDraw").addEventListener("click", function(event) {
            //Click Screenshot button
            var button = document.getElementById('ButtonDrawHideShow');
            if (button) {button.click();}
    });

//***************************
//*** Thickness change 🎚️ ***
//***************************

    // Add an event listener to update the thickness when the slider value changes by user
    BrushThicknessSlider.addEventListener('input', function() {context.lineWidth = BrushThicknessSlider.value;});

//********************************************************************************************************************
//***                                  Remove player notifications 💬🗑️                                           ***
//********************************************************************************************************************

    // Select the elements to be removed
        //Remove video notification by selector (ytp-fullerscreen-edu-text , ytp-fullerscreen-edu-chevron,)
        //Remove video time by class (ytp-time-display.notranslate)
        //Remove next video button by class (ytp-next-button)
    const elementsToRemove = document.querySelectorAll('.ytp-fullerscreen-edu-text, .ytp-fullerscreen-edu-chevron');

    // Loop through each element and remove it
    elementsToRemove.forEach(element => {element.remove();});

    }//window isn't an iframe

}