Please bookmark this page to avoid losing your image tool!

Image Scanner And Audio Dubbing 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.
async function processImage(originalImg, lang = 'en-US', pitch = 1, rate = 1) {
    // Determine target canvas dimensions (limit max width for UI purposes)
    const MAX_WIDTH = 600;
    let w = originalImg.width;
    let h = originalImg.height;
    if (w > MAX_WIDTH) {
        h = Math.round((h / w) * MAX_WIDTH);
        w = MAX_WIDTH;
    }

    // Create main container wrapper
    const wrapper = document.createElement('div');
    wrapper.style.position = 'relative';
    wrapper.style.display = 'inline-block';
    wrapper.style.fontFamily = 'Arial, sans-serif';
    wrapper.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
    wrapper.style.borderRadius = '8px';
    wrapper.style.overflow = 'hidden';
    wrapper.style.backgroundColor = '#2c3e50';
    wrapper.style.maxWidth = w + 'px';

    // Container for the image and the scanner line
    const imageContainer = document.createElement('div');
    imageContainer.style.position = 'relative';
    imageContainer.style.display = 'block';
    imageContainer.style.width = w + 'px';
    imageContainer.style.height = h + 'px';
    
    // Canvas element
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = w;
    canvas.height = h;
    ctx.drawImage(originalImg, 0, 0, w, h);
    imageContainer.appendChild(canvas);

    // Create a dynamic style block for the scanner animation
    const styleBlock = document.createElement('style');
    const animName = 'scanAnim_' + Math.random().toString(36).substr(2, 9);
    styleBlock.textContent = `
        @keyframes ${animName} {
            0% { top: 0; }
            50% { top: calc(100% - 2px); }
            100% { top: 0; }
        }
    `;
    wrapper.appendChild(styleBlock);

    // Scanner line
    const scanLine = document.createElement('div');
    scanLine.style.position = 'absolute';
    scanLine.style.left = '0';
    scanLine.style.width = '100%';
    scanLine.style.height = '4px';
    scanLine.style.backgroundColor = '#00ffcc';
    scanLine.style.boxShadow = '0 0 15px #00ffcc, 0 0 30px #00ffcc';
    scanLine.style.display = 'none';
    scanLine.style.zIndex = '10';
    imageContainer.appendChild(scanLine);

    wrapper.appendChild(imageContainer);

    // UI Panel (controls and status)
    const panel = document.createElement('div');
    panel.style.padding = '15px';
    panel.style.backgroundColor = '#ececec';
    panel.style.textAlign = 'center';
    panel.style.borderTop = '2px solid #ccc';

    const btn = document.createElement('button');
    btn.innerHTML = 'Scan & Identify<br><small>(Сканировать и Озвучить)</small>';
    btn.style.padding = '10px 20px';
    btn.style.fontSize = '16px';
    btn.style.fontWeight = 'bold';
    btn.style.color = '#fff';
    btn.style.backgroundColor = '#3498db';
    btn.style.border = 'none';
    btn.style.borderRadius = '5px';
    btn.style.cursor = 'pointer';
    btn.style.transition = 'background 0.3s';
    btn.onmouseover = () => btn.style.backgroundColor = '#2980b9';
    btn.onmouseout = () => btn.style.backgroundColor = '#3498db';

    const statusMsg = document.createElement('p');
    statusMsg.textContent = 'Awaiting activation... (Ожидание)';
    statusMsg.style.margin = '15px 0 0 0';
    statusMsg.style.fontSize = '14px';
    statusMsg.style.color = '#333';
    statusMsg.style.lineHeight = '1.4';
    statusMsg.style.minHeight = '40px';

    panel.appendChild(btn);
    panel.appendChild(statusMsg);
    wrapper.appendChild(panel);

    // Helper to sequentially load scripts exactly once
    const loadScript = (src) => new Promise((resolve, reject) => {
        if (document.querySelector(`script[src="${src}"]`)) {
            resolve();
            return;
        }
        const script = document.createElement('script');
        script.src = src;
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
    });

    // Helper to safely invoke Web Speech API
    const speakText = (text, isMuted = false) => {
        if ('speechSynthesis' in window) {
            window.speechSynthesis.cancel(); // kill any buffered speech
            const utterance = new SpeechSynthesisUtterance(text);
            utterance.lang = lang;
            utterance.pitch = parseFloat(pitch);
            utterance.rate = parseFloat(rate);
            if (isMuted) utterance.volume = 0;
            window.speechSynthesis.speak(utterance);
        }
    };

    // Main interaction
    btn.onclick = async () => {
        // Disabled UI to prevent concurrent runs
        btn.disabled = true;
        btn.style.backgroundColor = '#95a5a6';
        btn.style.cursor = 'default';

        // 1. Prime the audio engine immediately on user click
        // Browser policy requires speech to be triggered synchronously with a user action.
        speakText('Initializing image scanner...', false);
        statusMsg.innerHTML = 'Loading AI Models...<br><small>(Загрузка ИИ библиотек...)</small>';

        try {
            // 2. Load TensorFlow.js and MobileNet
            await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3/dist/tf.min.js');
            await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet@2/dist/mobilenet.min.js');

            // 3. Begin "Scanner" animation visuals
            statusMsg.innerHTML = 'Scanning image content...<br><small>(Сканирование объекта...)</small>';
            scanLine.style.display = 'block';
            scanLine.style.animation = `${animName} 2s infinite ease-in-out`;
            
            // 4. Run classification
            const model = await window.mobilenet.load();
            const predictions = await model.classify(canvas);

            // 5. Finish and report
            scanLine.style.display = 'none';
            scanLine.style.animation = 'none';

            if (predictions && predictions.length > 0) {
                const bestMatch = predictions[0].className.split(',')[0]; // Simplify name
                const prob = Math.round(predictions[0].probability * 100);
                
                const resultText = `Identification complete. The object is ${bestMatch}, with ${prob} percent certainty.`;
                statusMsg.innerHTML = `<strong>Result:</strong> ${bestMatch} (${prob}%)<br><small>Audio dubbing playing...</small>`;
                
                // Speak the result out loud
                speakText(resultText);

            } else {
                statusMsg.textContent = 'Could not identify the image content.';
                speakText('Could not identify the image content.');
            }

        } catch (err) {
            statusMsg.textContent = 'Error occurred: ' + err.message;
            scanLine.style.display = 'none';
            scanLine.style.animation = 'none';
            console.error(err);
        }

        // Re-enable UI
        btn.disabled = false;
        btn.style.backgroundColor = '#3498db';
        btn.style.cursor = 'pointer';
    };

    return wrapper;
}

Free Image Tool Creator

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

Description

The Image Scanner and Audio Dubbing Tool is an interactive utility that uses artificial intelligence to identify objects within an image and provide verbal descriptions. By scanning the visual content, the tool can recognize various items and communicate the results through synthesized speech, including the object’s name and the level of certainty. This tool is particularly useful for accessibility purposes, such as assisting visually impaired users in identifying surroundings, or for educational and interactive demonstrations where users want to learn more about objects in their photos through audio feedback.

Leave a Reply

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