Real-Time AI Speech & Voice Synthesizer App
An interactive Web Speech API text-to-speech voice generator featuring custom speech pitch, rate sliders, dynamic audio wave visualizer, and script exporter.
Real-Time AI Speech & Voice Synthesizer App
🎙️ Executive Project Overview
The Real-Time AI Speech & Voice Synthesizer App is an interactive web-based text-to-speech voice generator built with the W3C Web Speech API standard. Designed for content creators, podcasters, and web developers, it enables real-time text-to-speech audio synthesis with custom pitch modulation, playback speed rate control, voice model selection, and an animated audio waveform visualizer.
Multi-Voice & Accent Model Selector
Dynamically enumerates native system and browser voice models (US English, UK English, Male/Female accents) using `window.speechSynthesis.getVoices()`.
Pitch, Rate & Volume Parameters
Fine-tune speech rate speed (0.5x to 2.0x), voice pitch frequency (0.5 to 1.5), and output volume levels with real-time numeric readouts.
Audio Waveform Visualizer
HTML5 Canvas sine wave animation that dynamically pulses during active speech playback and pauses when speech synthesis finishes.
Sample Script Presets & Copy Action
Pre-loaded sample scripts (Tech Product Promo, AI Podcast Intro, Developer Tutorial) with 1-click clipboard text copying.
Key Advantages & Benefits
- Zero Server Latency: Uses native browser SpeechSynthesis engines without relying on expensive third-party paid TTS APIs.
- Web Accessibility Standard: Perfect utility for implementing screen-reader accessibility features on websites.
- Cross-Platform Compatibility: Runs seamlessly across Google Chrome, Apple Safari, Mozilla Firefox, and Microsoft Edge.
- Full Open Source Code: Includes complete HTML, CSS, and JS source code files with full customization rights.
🛠️ How to Use the Voice Synthesizer
- Type or paste your text script into the Speech Script Editor box.
- Select your preferred Voice Model from the dropdown menu.
- Adjust the Speech Speed and Voice Pitch sliders according to your preference.
- Click Synthesize Speech to listen to the audio output in real-time.
- Use the Pause or Stop buttons to control playback.
<!DOCTYPE html>
<html lang="en" class="h-full dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Real-Time AI Speech & Voice Synthesizer App - Web App</title>
<!-- Fonts & Icons -->
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'sans-serif'],
outfit: ['Outfit', 'sans-serif'],
mono: ['Fira Code', 'monospace']
}
}
}
}
</script>
<style>
body { margin: 0; padding: 0; min-height: 100vh; background-color: #0b0f17; }
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: #0b0f17; }
::-webkit-scrollbar-thumb { background: rgba(56, 189, 248, 0.2); border-radius: 4px; }
</style>
</head>
<body class="min-h-full text-slate-100 flex flex-col font-sans select-none bg-slate-950">
<!-- Header Navigation -->
<header class="h-16 bg-slate-900/90 backdrop-blur-md border-b border-slate-800 px-4 sm:px-6 flex items-center justify-between shrink-0 z-30 sticky top-0">
<div class="flex items-center gap-3">
<div class="w-9 h-9 rounded-xl bg-gradient-to-tr from-cyan-500 to-blue-600 flex items-center justify-center text-slate-950 font-outfit font-extrabold text-lg shadow-lg shadow-cyan-500/20">
🎙️
</div>
<div>
<h1 class="font-outfit font-bold text-sm sm:text-base text-white tracking-wide">Real-Time AI Voice & Speech Synthesizer</h1>
<p class="text-[10px] text-cyan-400 font-mono">Web Speech API Voice Generator</p>
</div>
</div>
<div class="flex items-center gap-2">
<button id="copyScriptBtn" class="px-3.5 py-1.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-white font-outfit font-bold text-xs transition flex items-center gap-1.5 border border-slate-700">
<i class="fa-solid fa-copy text-cyan-400"></i>
<span>Copy Text</span>
</button>
</div>
</header>
<!-- Main Workspace -->
<main class="flex-1 p-4 sm:p-6 max-w-6xl w-full mx-auto grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Left 2 Cols: Text Input & Audio Waveform Visualizer -->
<div class="lg:col-span-2 space-y-6">
<!-- Text Editor Drawer -->
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-5 sm:p-6 shadow-xl space-y-4">
<div class="flex items-center justify-between border-b border-slate-800/80 pb-3">
<h2 class="font-outfit font-extrabold text-lg text-white flex items-center gap-2">
<i class="fa-solid fa-pen-to-square text-cyan-400"></i> Speech Script Editor
</h2>
<!-- Presets Selector -->
<select id="samplePresetSelect" class="bg-slate-950 border border-slate-800 text-slate-300 text-xs font-semibold rounded-xl px-3 py-1.5 focus:outline-none focus:border-cyan-500">
<option value="tech-promo">Preset: Tech Product Promo</option>
<option value="podcast-intro">Preset: AI Podcast Intro</option>
<option value="coding-tutorial">Preset: Developer Tutorial</option>
</select>
</div>
<textarea id="speechText" rows="7" class="w-full bg-slate-950 border border-slate-800/80 rounded-2xl p-4 text-slate-200 text-sm leading-relaxed focus:outline-none focus:border-cyan-500 transition resize-none font-mono" placeholder="Type or paste text to synthesize into voice speech..."></textarea>
<!-- Audio Wave Visualizer Canvas -->
<div class="bg-slate-950 border border-slate-800/80 rounded-2xl p-4 h-24 relative overflow-hidden flex flex-col justify-between">
<div class="flex items-center justify-between text-xs text-slate-400 font-mono">
<span class="flex items-center gap-1.5 text-cyan-400 font-bold">
<span id="statusIndicator" class="w-2 h-2 rounded-full bg-slate-600"></span>
<span id="statusText">Ready</span>
</span>
<span id="charCount" class="text-slate-500">0 characters</span>
</div>
<canvas id="waveCanvas" class="w-full h-12"></canvas>
</div>
</div>
<!-- Playback Control Toolbar -->
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-4 sm:p-5 shadow-xl flex items-center justify-between gap-4">
<div class="flex items-center gap-3">
<button id="playBtn" class="px-5 py-3 rounded-2xl bg-cyan-500 hover:bg-cyan-400 text-slate-950 font-outfit font-extrabold text-xs uppercase tracking-wider transition flex items-center gap-2 shadow-lg shadow-cyan-500/20">
<i class="fa-solid fa-play"></i>
<span>Synthesize Speech</span>
</button>
<button id="pauseBtn" class="p-3 rounded-2xl bg-slate-800 hover:bg-slate-700 text-slate-300 transition" title="Pause / Resume">
<i class="fa-solid fa-pause"></i>
</button>
<button id="stopBtn" class="p-3 rounded-2xl bg-slate-800 hover:bg-rose-900/40 text-rose-400 transition" title="Stop Playback">
<i class="fa-solid fa-square"></i>
</button>
</div>
<div class="text-xs text-slate-400 font-mono hidden sm:block">
Web Speech Engine 2.0
</div>
</div>
</div>
<!-- Right Col: Voice Tuning & Parameters -->
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-5 sm:p-6 shadow-xl space-y-6 flex flex-col justify-between">
<div class="space-y-6">
<!-- Voice Accent Selection -->
<div class="space-y-3">
<label class="block font-outfit font-bold text-xs uppercase tracking-wider text-cyan-400">
🗣️ Select Voice Model
</label>
<select id="voiceSelect" class="w-full bg-slate-950 border border-slate-800 text-xs font-semibold text-slate-200 rounded-xl px-3 py-2.5 focus:outline-none focus:border-cyan-500">
<option value="">Loading Browser Voices...</option>
</select>
</div>
<!-- Speech Rate (Speed) -->
<div class="space-y-2">
<div class="flex justify-between text-xs font-bold text-slate-300">
<span>Speech Speed (Rate)</span>
<span id="rateVal" class="font-mono text-cyan-400">1.0x</span>
</div>
<input type="range" id="rateInput" min="0.5" max="2.0" step="0.1" value="1.0" class="w-full accent-cyan-500">
</div>
<!-- Speech Pitch -->
<div class="space-y-2">
<div class="flex justify-between text-xs font-bold text-slate-300">
<span>Voice Pitch</span>
<span id="pitchVal" class="font-mono text-cyan-400">1.0</span>
</div>
<input type="range" id="pitchInput" min="0.5" max="1.5" step="0.1" value="1.0" class="w-full accent-cyan-500">
</div>
<!-- Volume Level -->
<div class="space-y-2">
<div class="flex justify-between text-xs font-bold text-slate-300">
<span>Output Volume</span>
<span id="volumeVal" class="font-mono text-cyan-400">100%</span>
</div>
<input type="range" id="volumeInput" min="0" max="1" step="0.1" value="1.0" class="w-full accent-cyan-500">
</div>
</div>
<div class="p-3.5 bg-slate-950 border border-slate-800 rounded-2xl text-[11px] text-slate-400 space-y-1">
<div class="text-white font-bold">Speech Engine Specs:</div>
<div>API: W3C Web Speech API</div>
<div>Status: Client-Side Synthesis</div>
</div>
</div>
</main>
<!-- JS Logic -->
<script>
const speechText = document.getElementById('speechText');
const voiceSelect = document.getElementById('voiceSelect');
const rateInput = document.getElementById('rateInput');
const pitchInput = document.getElementById('pitchInput');
const volumeInput = document.getElementById('volumeInput');
const playBtn = document.getElementById('playBtn');
const pauseBtn = document.getElementById('pauseBtn');
const stopBtn = document.getElementById('stopBtn');
const statusIndicator = document.getElementById('statusIndicator');
const statusText = document.getElementById('statusText');
const charCount = document.getElementById('charCount');
const waveCanvas = document.getElementById('waveCanvas');
const synth = window.speechSynthesis;
let voices = [];
let isSpeaking = false;
// Sample Presets
const presets = {
'tech-promo': 'Welcome to TechPortal! Experience next-generation open-source developer tools, interactive web applications, and live tech news updates directly inside your web browser.',
'podcast-intro': 'Hello everyone, welcome back to another episode of Future Tech Weekly. Today we are diving into AI prompt engineering and modern web development architectures.',
'coding-tutorial': 'In this tutorial, we will learn how to build an interactive Web Speech synthesizer using pure HTML5, CSS3, and JavaScript.'
};
// Populate Voices Dropdown
function populateVoices() {
voices = synth.getVoices();
voiceSelect.innerHTML = '';
if (voices.length === 0) {
const option = document.createElement('option');
option.innerText = 'Standard Native Voice';
voiceSelect.appendChild(option);
return;
}
voices.forEach((voice, i) => {
const option = document.createElement('option');
option.value = i;
option.innerText = `${voice.name} (${voice.lang})`;
if (voice.default) option.selected = true;
voiceSelect.appendChild(option);
});
}
populateVoices();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoices;
}
// Waveform Visualizer Animation
const ctx = waveCanvas.getContext('2d');
let animationFrame;
function drawWave() {
ctx.clearRect(0, 0, waveCanvas.width, waveCanvas.height);
ctx.lineWidth = 2;
ctx.strokeStyle = isSpeaking ? '#06b6d4' : '#334155';
ctx.beginPath();
const sliceWidth = waveCanvas.width / 40;
let x = 0;
for (let i = 0; i < 40; i++) {
const v = isSpeaking ? Math.sin(Date.now() * 0.01 + i) * 15 + waveCanvas.height / 2 : waveCanvas.height / 2;
if (i === 0) ctx.moveTo(x, v);
else ctx.lineTo(x, v);
x += sliceWidth;
}
ctx.stroke();
if (isSpeaking) animationFrame = requestAnimationFrame(drawWave);
}
// Synthesize Play Logic
function speak() {
if (synth.speaking) synth.cancel();
const text = speechText.value.trim();
if (!text) return;
const utterance = new SpeechSynthesisUtterance(text);
const selectedVoiceIndex = voiceSelect.value;
if (voices[selectedVoiceIndex]) utterance.voice = voices[selectedVoiceIndex];
utterance.rate = parseFloat(rateInput.value);
utterance.pitch = parseFloat(pitchInput.value);
utterance.volume = parseFloat(volumeInput.value);
utterance.onstart = () => {
isSpeaking = true;
statusIndicator.className = 'w-2 h-2 rounded-full bg-cyan-400 animate-ping';
statusText.innerText = 'Synthesizing Speech...';
drawWave();
};
utterance.onend = () => {
isSpeaking = false;
statusIndicator.className = 'w-2 h-2 rounded-full bg-emerald-400';
statusText.innerText = 'Finished';
cancelAnimationFrame(animationFrame);
drawWave();
};
utterance.onerror = () => {
isSpeaking = false;
statusIndicator.className = 'w-2 h-2 rounded-full bg-rose-500';
statusText.innerText = 'Error';
};
synth.speak(utterance);
}
playBtn.addEventListener('click', speak);
pauseBtn.addEventListener('click', () => {
if (synth.speaking) {
if (synth.paused) {
synth.resume();
statusText.innerText = 'Resumed';
} else {
synth.pause();
statusText.innerText = 'Paused';
}
}
});
stopBtn.addEventListener('click', () => {
if (synth.speaking) {
synth.cancel();
isSpeaking = false;
statusIndicator.className = 'w-2 h-2 rounded-full bg-slate-600';
statusText.innerText = 'Stopped';
}
});
// UI Event Updates
speechText.addEventListener('input', () => {
charCount.innerText = speechText.value.length + ' characters';
});
rateInput.addEventListener('input', (e) => {
document.getElementById('rateVal').innerText = parseFloat(e.target.value).toFixed(1) + 'x';
});
pitchInput.addEventListener('input', (e) => {
document.getElementById('pitchVal').innerText = parseFloat(e.target.value).toFixed(1);
});
volumeInput.addEventListener('input', (e) => {
document.getElementById('volumeVal').innerText = Math.round(e.target.value * 100) + '%';
});
document.getElementById('samplePresetSelect').addEventListener('change', (e) => {
if (presets[e.target.value]) {
speechText.value = presets[e.target.value];
charCount.innerText = speechText.value.length + ' characters';
}
});
document.getElementById('copyScriptBtn').addEventListener('click', () => {
navigator.clipboard.writeText(speechText.value);
alert('Speech script text copied to clipboard!');
});
// Init Default Text
speechText.value = presets['tech-promo'];
charCount.innerText = speechText.value.length + ' characters';
drawWave();
</script>
</body>
</html>
/* Supports both Dark and Light mode via Tailwind class variant */
// Interactive scripts included inside demo view file
Related Projects
Interactive Drag & Drop Kanban Task Board
FeaturedA clean Trello-style Kanban board built with HTML5 HTML Drag and Drop API, color-coded task priorities, and local storage state persistence.
CSS Glassmorphism & Gradient Code Generator
FeaturedAn interactive visual CSS generator tool to tweak backdrop blur, opacity, transparency, and background gradients with instant 1-click code copying.