Please bookmark this page to avoid losing your image tool!

YouTube Video And ID Scanner Tool

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, fallbackSearch = "true") {
    // Create the main container
    const container = document.createElement('div');
    container.style.fontFamily = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
    container.style.padding = '20px';
    container.style.borderRadius = '8px';
    container.style.boxShadow = '0 4px 12px rgba(0,0,0,0.1)';
    container.style.backgroundColor = '#ffffff';
    container.style.color = '#333';
    container.style.maxWidth = '100%';
    container.style.boxSizing = 'border-box';

    // Header
    const header = document.createElement('h2');
    header.style.marginTop = '0';
    header.style.color = '#ff0000';
    header.style.display = 'flex';
    header.style.alignItems = 'center';
    header.style.gap = '10px';
    header.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" viewBox="0 0 16 16">
        <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.052-.072 1.964l-.008.106-.022.26-.01.104c-.05.52-.12.1023-.22 1.402a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/>
    </svg> YouTube Video & ID Scanner`;
    container.appendChild(header);

    // Loader wrapper
    const loaderWrap = document.createElement('div');
    loaderWrap.style.display = 'flex';
    loaderWrap.style.alignItems = 'center';
    loaderWrap.style.gap = '12px';
    loaderWrap.style.marginBottom = '20px';
    loaderWrap.style.padding = '15px';
    loaderWrap.style.backgroundColor = '#f1f8ff';
    loaderWrap.style.border = '1px solid #cce5ff';
    loaderWrap.style.borderRadius = '5px';
    loaderWrap.style.color = '#004085';

    const spinner = document.createElement('div');
    spinner.style.width = '24px';
    spinner.style.height = '24px';
    spinner.style.border = '3px solid rgba(0, 64, 133, 0.2)';
    spinner.style.borderTop = '3px solid #004085';
    spinner.style.borderRadius = '50%';
    spinner.style.animation = 'spin 1s linear infinite';
    
    const styleTag = document.createElement('style');
    styleTag.textContent = `@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }`;
    container.appendChild(styleTag);

    const statusP = document.createElement('div');
    statusP.textContent = 'Initializing scanner...';
    statusP.style.fontWeight = '500';

    loaderWrap.appendChild(spinner);
    loaderWrap.appendChild(statusP);
    container.appendChild(loaderWrap);

    // Results container
    const resultDiv = document.createElement('div');
    container.appendChild(resultDiv);

    async function runScanner() {
        let textFound = "";

        // Step 1: Detect QR codes using native BarcodeDetector if available
        statusP.textContent = 'Scanning for QR codes...';
        if ('BarcodeDetector' in window) {
            try {
                const barcodeDetector = new BarcodeDetector({ formats: ['qr_code'] });
                const barcodes = await barcodeDetector.detect(originalImg);
                if (barcodes.length > 0) {
                    textFound += " " + barcodes.map(b => b.rawValue).join(" ");
                }
            } catch (e) {
                console.log('BarcodeDetector error', e);
            }
        }

        // Step 2: Use jsQR as a fallback/complement for QR reading
        if (!textFound.includes("youtube.com") && !textFound.includes("youtu.be")) {
            try {
                await new Promise((resolve, reject) => {
                    if (window.jsQR) { resolve(); return; }
                    const script = document.createElement('script');
                    script.src = 'https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.js';
                    script.onload = resolve;
                    script.onerror = reject;
                    document.head.appendChild(script);
                });
                
                const canvas = document.createElement('canvas');
                canvas.width = originalImg.width;
                canvas.height = originalImg.height;
                const ctx = canvas.getContext('2d');
                ctx.drawImage(originalImg, 0, 0);
                const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                const code = jsQR(imageData.data, imageData.width, imageData.height);
                if (code) {
                    textFound += " " + code.data;
                }
            } catch (e) {
                console.log('jsQR failed', e);
            }
        }

        // Step 3: Run OCR text detection using Tesseract.js
        try {
            statusP.textContent = 'Performing text recognition (OCR)... this may take a moment.';
            await new Promise((resolve, reject) => {
                 if (window.Tesseract) { resolve(); return; }
                 const script = document.createElement('script');
                 script.src = 'https://cdn.jsdelivr.net/npm/tesseract.js@4/dist/tesseract.min.js';
                 script.onload = resolve;
                 script.onerror = reject;
                 document.head.appendChild(script);
            });
            // Include English + Russian considering possible review context (Обзор Ютуб)
            const tesseractResult = await Tesseract.recognize(originalImg, 'eng+rus');
            textFound += " " + tesseractResult.data.text;
        } catch (e) {
            console.log('Tesseract failed', e);
        }

        // Finish loading visual
        loaderWrap.style.display = 'none';

        // Step 4: Extract IDs
        const ids = new Set();
        
        // Match explicit YouTube URLs
        const urlRegex = /(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/gi;
        let match;
        while ((match = urlRegex.exec(textFound)) !== null) {
            ids.add(match[1]);
        }
        
        // Match IDs following keywords like "id", "v", "video"
        const idRegex = /(?:id|v|video)[^\w]{1,5}([a-zA-Z0-9_-]{11})(?!\w)/gi;
        while ((match = idRegex.exec(textFound)) !== null) {
            ids.add(match[1]);
        }

        // Aggressive fallback matching for typical high-entropy YouTube ID structures
        if (ids.size === 0 && fallbackSearch === "true") {
            const fallbackRegex = /\b([a-zA-Z0-9_-]{11})\b/g;
            while ((match = fallbackRegex.exec(textFound)) !== null) {
                const potId = match[1];
                // Heuristic: Must contain a mix of uppercase, lowercase, and numbers
                if (/[a-z]/.test(potId) && /[A-Z]/.test(potId) && /[0-9]/.test(potId)) {
                    ids.add(potId);
                }
            }
        }

        const idArray = Array.from(ids);
        if (idArray.length === 0) {
            const noRes = document.createElement('div');
            noRes.style.padding = '15px';
            noRes.style.backgroundColor = '#f8d7da';
            noRes.style.color = '#721c24';
            noRes.style.borderRadius = '5px';
            noRes.style.border = '1px solid #f5c6cb';
            noRes.textContent = 'No YouTube Videos or IDs could be detected in this image. Try an image with a clearer QR code or legible URLs.';
            resultDiv.appendChild(noRes);
            return;
        }

        // Render detected items
        const foundHeading = document.createElement('h3');
        foundHeading.textContent = `Scanned ${idArray.length} embedded video resource(s):`;
        foundHeading.style.marginTop = '0';
        resultDiv.appendChild(foundHeading);

        idArray.forEach(id => {
            const card = document.createElement('div');
            card.style.display = 'flex';
            card.style.flexWrap = 'wrap';
            card.style.alignItems = 'center';
            card.style.gap = '20px';
            card.style.marginBottom = '20px';
            card.style.padding = '20px';
            card.style.backgroundColor = '#f9f9f9';
            card.style.border = '1px solid #e1e1e1';
            card.style.borderRadius = '10px';
            card.style.transition = 'all 0.2sease-in-out';
            
            card.onmouseover = () => {
                card.style.boxShadow = '0 6px 12px rgba(0,0,0,0.1)';
                card.style.transform = 'translateY(-2px)';
            };
            card.onmouseout = () => {
                card.style.boxShadow = 'none';
                card.style.transform = 'none';
            };

            const iframe = document.createElement('iframe');
            iframe.width = '280';
            iframe.height = '157';
            iframe.src = `https://www.youtube.com/embed/${id}`;
            iframe.frameBorder = '0';
            iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture';
            iframe.allowFullscreen = true;
            iframe.style.borderRadius = '8px';
            iframe.style.flexShrink = '0';

            const info = document.createElement('div');
            info.style.display = 'flex';
            info.style.flexDirection = 'column';
            info.style.justifyContent = 'center';

            const title = document.createElement('h4');
            title.style.margin = '0 0 15px 0';
            title.textContent = `Identifier: ${id}`;
            title.style.fontFamily = 'monospace';
            title.style.fontSize = '1.2em';
            title.style.backgroundColor = '#eef0f2';
            title.style.padding = '8px 12px';
            title.style.borderRadius = '6px';
            title.style.color = '#111';
            title.style.display = 'inline-block';

            const link = document.createElement('a');
            link.href = `https://www.youtube.com/watch?v=${id}`;
            link.target = '_blank';
            link.textContent = 'Watch on YouTube ↗';
            link.style.color = '#fff';
            link.style.backgroundColor = '#ff0000';
            link.style.padding = '10px 20px';
            link.style.borderRadius = '6px';
            link.style.textDecoration = 'none';
            link.style.fontWeight = 'bold';
            link.style.fontSize = '0.95em';
            link.style.display = 'inline-block';
            link.style.textAlign = 'center';
            link.style.width = 'fit-content';
            
            link.onmouseover = () => link.style.backgroundColor = '#cc0000';
            link.onmouseout = () => link.style.backgroundColor = '#ff0000';

            info.appendChild(title);
            info.appendChild(link);

            card.appendChild(iframe);
            card.appendChild(info);
            resultDiv.appendChild(card);
        });
    }

    // Start scanner operation
    runScanner();

    return container;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The YouTube Video and ID Scanner Tool is designed to extract YouTube video information from images. By utilizing QR code detection and Optical Character Recognition (OCR), the tool can identify YouTube URLs or unique 11-character video IDs embedded within an image. Once detected, the tool provides a preview of the video and direct links to watch the content on YouTube. This tool is useful for quickly identifying videos from screenshots, posters, or promotional materials containing QR codes or written video links.

Leave a Reply

Your email address will not be published. Required fields are marked *