Please bookmark this page to avoid losing your image tool!

Image To Audio Auto Dubbing And World Language Translator 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, sourceLang = "eng+rus", defaultTargetLang = "en") {
    // Container setup
    const container = document.createElement("div");
    container.style.fontFamily = "system-ui, -apple-system, sans-serif";
    container.style.maxWidth = "900px";
    container.style.margin = "0 auto";
    container.style.padding = "20px";
    container.style.boxSizing = "border-box";
    container.style.display = "flex";
    container.style.flexDirection = "column";
    container.style.gap = "20px";
    container.style.backgroundColor = "#f9f9f9";
    container.style.border = "1px solid #ddd";
    container.style.borderRadius = "8px";

    // Title
    const title = document.createElement("h3");
    title.innerText = "Auto-Dubbing & Extracted Text Translator";
    title.style.margin = "0";
    title.style.color = "#333";
    container.appendChild(title);

    // Canvas to hold and display the image safely
    const imgContainer = document.createElement("div");
    imgContainer.style.textAlign = "center";
    imgContainer.style.backgroundColor = "#000";
    imgContainer.style.borderRadius = "6px";
    imgContainer.style.overflow = "hidden";
    
    const canvas = document.createElement("canvas");
    canvas.width = originalImg.width;
    canvas.height = originalImg.height;
    canvas.style.maxWidth = "100%";
    canvas.style.maxHeight = "400px";
    canvas.style.objectFit = "contain";
    const ctx = canvas.getContext("2d");
    ctx.drawImage(originalImg, 0, 0);
    imgContainer.appendChild(canvas);
    container.appendChild(imgContainer);

    // Status bar
    const statusDiv = document.createElement("div");
    statusDiv.style.fontWeight = "600";
    statusDiv.style.color = "#0056b3";
    statusDiv.style.padding = "10px";
    statusDiv.style.backgroundColor = "#e6f2ff";
    statusDiv.style.borderLeft = "4px solid #0056b3";
    statusDiv.innerText = "Status: Initializing Tesseract OCR...";
    container.appendChild(statusDiv);

    // Two-column Layout for Text input/output
    const gridContainer = document.createElement("div");
    gridContainer.style.display = "grid";
    gridContainer.style.gridTemplateColumns = "repeat(auto-fit, minmax(300px, 1fr))";
    gridContainer.style.gap = "20px";

    // Extracted Text Column
    const extractedCol = document.createElement("div");
    const extractedLabel = document.createElement("label");
    extractedLabel.innerText = "Extracted Text (Original):";
    extractedLabel.style.display = "block";
    extractedLabel.style.fontWeight = "bold";
    extractedLabel.style.marginBottom = "8px";
    const extractedTextarea = document.createElement("textarea");
    extractedTextarea.style.width = "100%";
    extractedTextarea.style.height = "150px";
    extractedTextarea.style.padding = "10px";
    extractedTextarea.style.boxSizing = "border-box";
    extractedTextarea.style.border = "1px solid #ccc";
    extractedTextarea.style.borderRadius = "4px";
    extractedTextarea.style.resize = "vertical";
    extractedCol.appendChild(extractedLabel);
    extractedCol.appendChild(extractedTextarea);

    // Translated Text Column
    const translatedCol = document.createElement("div");
    const translatedLabel = document.createElement("label");
    translatedLabel.innerText = "Translated Text (Dubbing Script):";
    translatedLabel.style.display = "block";
    translatedLabel.style.fontWeight = "bold";
    translatedLabel.style.marginBottom = "8px";
    const translatedTextarea = document.createElement("textarea");
    translatedTextarea.style.width = "100%";
    translatedTextarea.style.height = "150px";
    translatedTextarea.style.padding = "10px";
    translatedTextarea.style.boxSizing = "border-box";
    translatedTextarea.style.border = "1px solid #ccc";
    translatedTextarea.style.borderRadius = "4px";
    translatedTextarea.style.resize = "vertical";
    translatedCol.appendChild(translatedLabel);
    translatedCol.appendChild(translatedTextarea);

    gridContainer.appendChild(extractedCol);
    gridContainer.appendChild(translatedCol);
    container.appendChild(gridContainer);

    // Controls
    const controlsContainer = document.createElement("div");
    controlsContainer.style.display = "flex";
    controlsContainer.style.flexWrap = "wrap";
    controlsContainer.style.gap = "10px";
    controlsContainer.style.alignItems = "center";
    controlsContainer.style.padding = "15px";
    controlsContainer.style.backgroundColor = "#fff";
    controlsContainer.style.border = "1px solid #ddd";
    controlsContainer.style.borderRadius = "6px";

    const langLabel = document.createElement("label");
    langLabel.innerText = "Target Dubbing Language: ";
    langLabel.style.fontWeight = "600";

    const langSelect = document.createElement("select");
    langSelect.style.padding = "6px";
    langSelect.style.borderRadius = "4px";
    
    // Most common languages for translation and speech synthesis
    const languages = {
        "en": "English", "es": "Spanish", "fr": "French", "de": "German", 
        "ru": "Russian", "it": "Italian", "pt": "Portuguese", "zh-CN": "Chinese (Simplified)", 
        "ja": "Japanese", "ko": "Korean", "ar": "Arabic", "hi": "Hindi"
    };

    for (const [code, name] of Object.entries(languages)) {
        const option = document.createElement("option");
        option.value = code;
        option.innerText = name;
        if (code === defaultTargetLang) option.selected = true;
        langSelect.appendChild(option);
    }

    // Buttons
    const btnStyle = "padding: 8px 16px; border: none; border-radius: 4px; font-weight: bold; cursor: pointer; color: white;";
    
    const translateBtn = document.createElement("button");
    translateBtn.innerText = "🔄 Retranslate";
    translateBtn.style.cssText = `${btnStyle} background-color: #6c757d;`;
    translateBtn.disabled = true;

    const playBtn = document.createElement("button");
    playBtn.innerText = "🔊 Play Auto-Dubbing";
    playBtn.style.cssText = `${btnStyle} background-color: #28a745;`;
    playBtn.disabled = true;

    const stopBtn = document.createElement("button");
    stopBtn.innerText = "⏹ Stop Audio";
    stopBtn.style.cssText = `${btnStyle} background-color: #dc3545;`;
    stopBtn.disabled = true;

    controlsContainer.appendChild(langLabel);
    controlsContainer.appendChild(langSelect);
    controlsContainer.appendChild(translateBtn);
    controlsContainer.appendChild(playBtn);
    controlsContainer.appendChild(stopBtn);
    container.appendChild(controlsContainer);

    // --- Logic & Pipeline ---

    // Free translation using Google Translate Web API Endpoints
    const translateText = async (text, targetLang) => {
        if (!text.trim()) return "";
        try {
            const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}`;
            const res = await fetch(url);
            const json = await res.json();
            return json[0].map(item => item[0]).join('');
        } catch (err) {
            console.error(err);
            return "Error: Could not translate text. Please try again.";
        }
    };

    // Load Tesseract.js dynamically
    const loadScript = (src) => {
        return new Promise((resolve, reject) => {
            const script = document.createElement("script");
            script.src = src;
            script.onload = resolve;
            script.onerror = reject;
            document.head.appendChild(script);
        });
    };

    const processPipeline = async () => {
        try {
            if (!window.Tesseract) {
                await loadScript("https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js");
            }

            statusDiv.innerText = `Status: Reading image text (${sourceLang})...`;
            
            // Tesseract OCR
            const result = await window.Tesseract.recognize(
                canvas,
                sourceLang,
                {
                    logger: m => {
                        if (m.status === 'recognizing text') {
                            const progress = (m.progress * 100).toFixed(0);
                            statusDiv.innerText = `Status: Recognizing text... ${progress}%`;
                        }
                    }
                }
            );

            const extractedText = result.data.text;
            extractedTextarea.value = extractedText;

            if (!extractedText.trim()) {
                statusDiv.innerText = "Status: No text found in image.";
                statusDiv.style.backgroundColor = "#fff3cd";
                statusDiv.style.borderLeftColor = "#ffc107";
                statusDiv.style.color = "#856404";
                return;
            }

            statusDiv.innerText = "Status: Translating text...";
            
            // Translate
            const targetLang = langSelect.value;
            const translatedText = await translateText(extractedText, targetLang);
            translatedTextarea.value = translatedText;

            statusDiv.innerText = "Status: Done. Ready for auto-dubbing.";
            statusDiv.style.backgroundColor = "#d4edda";
            statusDiv.style.borderLeftColor = "#28a745";
            statusDiv.style.color = "#155724";

            // Enabled Controls
            translateBtn.disabled = false;
            playBtn.disabled = false;
            stopBtn.disabled = false;
            
        } catch (error) {
            statusDiv.innerText = `Status: Pipeline Error - ${error.message}`;
            statusDiv.style.backgroundColor = "#f8d7da";
            statusDiv.style.borderLeftColor = "#dc3545";
            statusDiv.style.color = "#721c24";
        }
    };

    // Auto-start pipeline
    processPipeline();

    // Event Listeners
    translateBtn.addEventListener("click", async () => {
        translateBtn.disabled = true;
        playBtn.disabled = true;
        statusDiv.innerText = "Status: Translating...";
        statusDiv.style.backgroundColor = "#e6f2ff";
        statusDiv.style.borderLeftColor = "#0056b3";
        statusDiv.style.color = "#0056b3";

        const textToTranslate = extractedTextarea.value;
        const targetLang = langSelect.value;
        
        translatedTextarea.value = await translateText(textToTranslate, targetLang);
        
        statusDiv.innerText = "Status: Translation Updated. Ready for playback.";
        statusDiv.style.backgroundColor = "#d4edda";
        statusDiv.style.borderLeftColor = "#28a745";
        statusDiv.style.color = "#155724";
        translateBtn.disabled = false;
        playBtn.disabled = false;
    });

    playBtn.addEventListener("click", () => {
        const textToPlay = translatedTextarea.value;
        if (!textToPlay.trim()) return;

        // Cancel previous speech if running
        window.speechSynthesis.cancel(); 

        const utterance = new SpeechSynthesisUtterance(textToPlay);
        utterance.lang = langSelect.value;
        utterance.rate = 0.9; // Slightly slower for clearer dubbing
        
        utterance.onstart = () => {
            statusDiv.innerText = "Status: Playing audio...";
        };
        utterance.onend = () => {
            statusDiv.innerText = "Status: Audio playback complete. Ready.";
        };
        utterance.onerror = (e) => {
            console.error("Speech Synthesis Error:", e);
            statusDiv.innerText = "Status: Audio playback interrupted or error.";
        };

        window.speechSynthesis.speak(utterance);
    });

    stopBtn.addEventListener("click", () => {
        if (window.speechSynthesis.speaking) {
            window.speechSynthesis.cancel();
            statusDiv.innerText = "Status: Audio stopped. Ready.";
        }
    });

    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

This tool provides an automated pipeline for extracting, translating, and converting text from images into spoken audio. Using Optical Character Recognition (OCR), it identifies text within an uploaded image, allows for translation into multiple world languages, and utilizes speech synthesis to provide an ‘auto-dubbing’ effect. This tool is useful for accessibility purposes, such as helping visually impaired users understand text-based images, or for language learners who want to hear the spoken pronunciation of foreign text found in photos, signs, or documents.

Leave a Reply

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