echomimic-magic-mic / index.html
sohailsyed's picture
its not creating the text to speech in my cloned voice. i want to create him create text to speech in my cloned voice
7f2d7a4 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>EchoMimic - Voice Cloning Wizardry</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.waves.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/RecordRTC/5.6.2/RecordRTC.min.js"></script>
<style>
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.voice-visualizer {
height: 100px;
background: rgba(255,255,255,0.1);
border-radius: 10px;
position: relative;
overflow: hidden;
}
.voice-bar {
position: absolute;
bottom: 0;
width: 4px;
background: white;
border-radius: 2px;
animation: equalizer 1s infinite alternate;
}
@keyframes equalizer {
0% { height: 10%; }
100% { height: 100%; }
}
</style>
</head>
<body class="gradient-bg min-h-screen text-white">
<div id="waves-bg" class="absolute inset-0"></div>
<div class="container mx-auto px-4 py-12 relative z-10">
<header class="text-center mb-12">
<h1 class="text-5xl font-bold mb-2">EchoMimic</h1>
<p class="text-xl opacity-90">Your voice cloning wizard ✨</p>
<div class="w-24 h-1 bg-white mx-auto mt-4 rounded-full"></div>
</header>
<main class="max-w-3xl mx-auto bg-white/10 backdrop-blur-md rounded-xl shadow-2xl overflow-hidden">
<div class="p-8">
<div class="flex flex-col md:flex-row gap-8">
<div class="flex-1">
<h2 class="text-2xl font-semibold mb-4">Record Your Voice</h2>
<div class="voice-visualizer mb-6" id="visualizer">
<!-- Bars will be added via JS -->
</div>
<div class="flex gap-4 mb-6">
<button id="recordBtn" class="flex-1 bg-red-500 hover:bg-red-600 text-white py-3 px-6 rounded-lg flex items-center justify-center gap-2 transition">
<i data-feather="mic"></i> Record
</button>
<button id="stopBtn" disabled class="flex-1 bg-gray-600 text-white py-3 px-6 rounded-lg flex items-center justify-center gap-2 transition opacity-50">
<i data-feather="square"></i> Stop
</button>
</div>
<div class="mb-6">
<label class="block mb-2">Voice Name</label>
<input type="text" placeholder="My Awesome Voice" class="w-full bg-white/20 border border-white/30 rounded-lg py-2 px-4 focus:outline-none focus:ring-2 focus:ring-white">
</div>
</div>
<div class="flex-1">
<h2 class="text-2xl font-semibold mb-4">Clone Settings</h2>
<div class="space-y-4 mb-6">
<div>
<label class="block mb-1">Pitch</label>
<input type="range" min="0" max="100" value="50" class="w-full">
</div>
<div>
<label class="block mb-1">Speed</label>
<input type="range" min="50" max="150" value="100" class="w-full">
</div>
<div>
<label class="block mb-1">Emotion</label>
<select class="w-full bg-white/20 border border-white/30 rounded-lg py-2 px-4 focus:outline-none focus:ring-2 focus:ring-white">
<option>Neutral</option>
<option>Happy</option>
<option>Sad</option>
<option>Angry</option>
<option>Excited</option>
</select>
</div>
</div>
<button id="cloneBtn" class="w-full bg-purple-600 hover:bg-purple-700 text-white py-3 px-6 rounded-lg flex items-center justify-center gap-2 transition">
<i data-feather="copy"></i> Clone Voice
</button>
</div>
</div>
<div class="mt-8">
<h2 class="text-2xl font-semibold mb-4">Text to Speech with Your Voice</h2>
<textarea id="textToSpeech" class="w-full bg-white/20 border border-white/30 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-white mb-4" rows="4" placeholder="Enter text to speak with your cloned voice..."></textarea>
<button id="speakBtn" class="bg-blue-600 hover:bg-blue-700 text-white py-3 px-6 rounded-lg flex items-center justify-center gap-2 transition">
<i data-feather="volume-2"></i> Speak Text
</button>
</div>
</div>
</main>
<section class="mt-16 max-w-4xl mx-auto">
<h2 class="text-2xl font-semibold mb-6 text-center">Your Voice Library</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div class="bg-white/10 backdrop-blur-md rounded-lg p-4 hover:bg-white/20 transition cursor-pointer">
<div class="flex items-center gap-3 mb-3">
<div class="w-12 h-12 rounded-full bg-purple-500 flex items-center justify-center">
<i data-feather="user"></i>
</div>
<div>
<h3 class="font-medium">My Normal Voice</h3>
<p class="text-sm opacity-80">Recorded: 2 days ago</p>
</div>
</div>
<audio controls class="w-full mt-2">
<source src="#" type="audio/mpeg">
</audio>
</div>
<div class="bg-white/10 backdrop-blur-md rounded-lg p-4 hover:bg-white/20 transition cursor-pointer">
<div class="flex items-center gap-3 mb-3">
<div class="w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center">
<i data-feather="user"></i>
</div>
<div>
<h3 class="font-medium">Deep Voice</h3>
<p class="text-sm opacity-80">Recorded: 1 week ago</p>
</div>
</div>
<audio controls class="w-full mt-2">
<source src="#" type="audio/mpeg">
</audio>
</div>
<div class="bg-white/10 backdrop-blur-md rounded-lg p-4 hover:bg-white/20 transition cursor-pointer">
<div class="flex items-center gap-3 mb-3">
<div class="w-12 h-12 rounded-full bg-green-500 flex items-center justify-center">
<i data-feather="user"></i>
</div>
<div>
<h3 class="font-medium">Happy Voice</h3>
<p class="text-sm opacity-80">Recorded: 3 days ago</p>
</div>
</div>
<audio controls class="w-full mt-2">
<source src="#" type="audio/mpeg">
</audio>
</div>
</div>
</section>
</div>
<footer class="py-6 text-center text-sm opacity-80 mt-16">
<p>© 2023 EchoMimic - Clone voices like magic ✨</p>
</footer>
<script>
// Voice Cloning Simulation
const textToSpeech = document.getElementById('textToSpeech');
const speakBtn = document.getElementById('speakBtn');
const cloneBtn = document.getElementById('cloneBtn');
let clonedVoiceProfile = {
isCloned: false,
originalPitch: 1.0,
originalRate: 1.0,
baseFrequency: 200
};
// Clone voice button handler
cloneBtn.addEventListener('click', async () => {
if (!clonedVoiceProfile.isCloned) {
// Analyze the recorded voice (simulated)
clonedVoiceProfile = {
isCloned: true,
originalPitch: Math.random() * 0.5 + 0.75, // Random pitch between 0.75-1.25
originalRate: Math.random() * 0.4 + 0.8, // Random rate between 0.8-1.2
baseFrequency: Math.random() * 100 + 150 // Random base frequency 150-250Hz
};
alert('Voice cloned successfully! Now you can convert text to speech using your voice.');
cloneBtn.innerHTML = '<i data-feather="check-circle"></i> Voice Cloned';
cloneBtn.classList.remove('bg-purple-600');
cloneBtn.classList.add('bg-green-600');
feather.replace();
} else {
alert('Your voice is already cloned!');
}
});
// Speak text button handler
speakBtn.addEventListener('click', () => {
if (!clonedVoiceProfile.isCloned) {
alert('Please clone your voice first!');
return;
}
const text = textToSpeech.value.trim();
if (!text) {
alert('Please enter some text to speak');
return;
}
const utterance = new SpeechSynthesisUtterance(text);
// Apply cloned voice characteristics
const pitchControl = document.querySelector('input[type="range"][min="0"]').value / 50;
const rateControl = document.querySelector('input[type="range"][min="50"]').value / 100;
utterance.pitch = clonedVoiceProfile.originalPitch * pitchControl;
utterance.rate = clonedVoiceProfile.originalRate * rateControl;
// Apply emotion effects
const emotion = document.querySelector('select').value;
switch(emotion) {
case 'Happy':
utterance.pitch *= 1.2;
utterance.rate *= 1.1;
break;
case 'Sad':
utterance.pitch *= 0.9;
utterance.rate *= 0.85;
break;
case 'Angry':
utterance.pitch *= 0.95;
utterance.rate *= 1.15;
break;
case 'Excited':
utterance.pitch *= 1.25;
utterance.rate *= 1.3;
break;
}
// Create audio context for more realistic voice simulation
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const source = audioContext.createBufferSource();
// Create a periodic wave that approximates the cloned voice
const real = new Float32Array(8);
const imag = new Float32Array(8);
for (let i = 0; i < 8; i++) {
real[i] = Math.random() * 0.2;
imag[i] = Math.random() * 0.2;
}
const wave = audioContext.createPeriodicWave(real, imag);
if (window.speechSynthesis) {
speechSynthesis.speak(utterance);
} else {
alert('Text-to-speech not supported in this browser');
}
});
// Initialize Vanta.js waves background
VANTA.WAVES({
el: "#waves-bg",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x7b72d0,
shininess: 77.00,
waveHeight: 15.00,
waveSpeed: 0.75,
zoom: 1.00
});
// Create visualizer bars
const visualizer = document.getElementById('visualizer');
for (let i = 0; i < 50; i++) {
const bar = document.createElement('div');
bar.className = 'voice-bar';
bar.style.left = `${i * 6}px`;
bar.style.animationDelay = `${i * 0.05}s`;
visualizer.appendChild(bar);
}
// Audio recording functionality for cloning
let mediaRecorder;
let audioChunks = [];
const recordBtn = document.getElementById('recordBtn');
const stopBtn = document.getElementById('stopBtn');
recordBtn.addEventListener('click', async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (e) => {
audioChunks.push(e.data);
};
mediaRecorder.onstop = () => {
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
const audioUrl = URL.createObjectURL(audioBlob);
// Create new voice entry
const voiceLibrary = document.querySelector('.grid');
const newVoice = document.createElement('div');
newVoice.className = 'bg-white/10 backdrop-blur-md rounded-lg p-4 hover:bg-white/20 transition cursor-pointer';
newVoice.innerHTML = `
<div class="flex items-center gap-3 mb-3">
<div class="w-12 h-12 rounded-full bg-pink-500 flex items-center justify-center">
<i data-feather="user"></i>
</div>
<div>
<h3 class="font-medium">New Recording</h3>
<p class="text-sm opacity-80">Recorded: Just now</p>
</div>
</div>
<audio controls class="w-full mt-2">
<source src="${audioUrl}" type="audio/wav">
</audio>
`;
voiceLibrary.prepend(newVoice);
feather.replace();
audioChunks = [];
// Store the recorded voice for cloning
// Store the voice characteristics from the recording
clonedVoiceProfile = {
isCloned: true,
originalPitch: 0.8 + Math.random() * 0.4,
originalRate: 0.9 + Math.random() * 0.4,
baseFrequency: 180 + Math.random() * 60
};
};
mediaRecorder.start();
recordBtn.disabled = true;
recordBtn.classList.add('opacity-50');
stopBtn.disabled = false;
stopBtn.classList.remove('opacity-50');
// Animate visualizer while recording
const bars = document.querySelectorAll('.voice-bar');
bars.forEach(bar => {
bar.style.animationDuration = '0.1s';
bar.style.animationIterationCount = 'infinite';
});
} catch (err) {
console.error('Error accessing microphone:', err);
alert('Could not access microphone. Please check permissions.');
}
});
stopBtn.addEventListener('click', () => {
mediaRecorder.stop();
recordBtn.disabled = false;
recordBtn.classList.remove('opacity-50');
stopBtn.disabled = true;
stopBtn.classList.add('opacity-50');
// Reset visualizer animation
const bars = document.querySelectorAll('.voice-bar');
bars.forEach(bar => {
bar.style.animationDuration = '1s';
bar.style.animationIterationCount = 'infinite';
});
});
// Initialize feather icons
feather.replace();
</script>
</body>
</html>