YouTube Stream Timestamp Logger

Logs the current YouTube stream URL, timestamp, and timestamped URL in shortened format

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         YouTube Stream Timestamp Logger
// @namespace    http://tampermonkey.net/
// @version      420.69
// @description  Logs the current YouTube stream URL, timestamp, and timestamped URL in shortened format
// @author       Kai Amamiya / ModernDisappointment | using the help of ChatGPT 3.0
// @license      MIT
// @match        *://www.youtube.com/watch*
// ==/UserScript==

(function() {
    'use strict';

    // Function to convert seconds to HH:MM:SS.sss format
    function formatTime(seconds) {
        let hours = Math.floor(seconds / 3600);
        let minutes = Math.floor((seconds % 3600) / 60);
        let secs = (seconds % 60).toFixed(3);
        return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(6, '0')}`;
    }

    // Function to convert seconds to URL timestamp format
    function secondsToURLTimestamp(seconds) {
        return Math.floor(seconds); // Round down to the nearest whole number
    }

    // Function to copy text to clipboard
    function copyToClipboard(text) {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand('copy');
        document.body.removeChild(textarea);
    }

    // Function to log and copy the current media time and video URL
    function logVideoDetails() {
        const ytPlayer = document.querySelector('video');
        if (ytPlayer) {
            const currentTime = ytPlayer.currentTime;
            const videoURL = window.location.href;
            const timestamp = formatTime(currentTime);
            const urlTimestamp = secondsToURLTimestamp(currentTime);
            // Extract video ID from the URL
            const videoIdMatch = videoURL.match(/[?&]v=([a-zA-Z0-9_-]+)/);
            const videoId = videoIdMatch ? videoIdMatch[1] : '';
            const timestampedURL = `https://youtu.be/${videoId}?t=${urlTimestamp}`;
            const output = `Note: \nVideo URL: ${videoURL}\nTimestamp: ${timestamp}\nVideo URL w/ Time: ${timestampedURL}`;
            console.log(output);
            copyToClipboard(output);
            alert('Video URL, Timestamp, and Timestamped URL copied to clipboard!');
        } else {
            console.log('YouTube video element not found.');
        }
    }
    // Function to create or remove the button based on the page state
    function updateButton() {
        // Check if we are on a YouTube video or stream page
        const isYouTubeVideoPage = /\/watch\?v=/.test(window.location.href) || /\/live/.test(window.location.href);
        const isVideoPage = document.querySelector('video') !== null;
        const isFullscreen = document.fullscreenElement !== null;

        if (isYouTubeVideoPage && isVideoPage && !isFullscreen) {
            if (!document.getElementById('copyTimestampButton')) {
                const button = document.createElement('button');
                button.id = 'copyTimestampButton';
                button.innerHTML = 'Timestamp';
                button.style.position = 'fixed';
                button.style.bottom = '10px';
                button.style.left = '10px';
                button.style.zIndex = '9999';
                button.style.padding = '10px';
                button.style.backgroundColor = '#404040';
                button.style.color = '#FFFFFF';
                button.style.border = 'none';
                button.style.cursor = 'pointer';
                button.addEventListener('click', logVideoDetails);
                document.body.appendChild(button);
            }
        } else {
            const button = document.getElementById('copyTimestampButton');
            if (button) {
                button.remove();
            }
        }
    }

    // Set up observers to check for changes
    function setupObservers() {
        // Monitor for changes in the page that might indicate a video or fullscreen state change
        const observer = new MutationObserver(updateButton);
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // Also check for fullscreen changes
        document.addEventListener('fullscreenchange', updateButton);
    }

    // Initialize observers when the page loads
    window.addEventListener('load', setupObservers);
    // Also check initially if on a video page
    window.addEventListener('load', updateButton);
})();