karaoke-master / index.html
bibbler's picture
Add 2 files
31787df verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Karaoke Master</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&family=Roboto:wght@400;700&family=Montserrat:wght@400;700&family=Dancing+Script:wght@700&family=Open+Sans:wght@400;700&display=swap" rel="stylesheet">
<style>
.lyrics-container {
height: 400px;
overflow-y: auto;
scroll-behavior: smooth;
}
.highlight {
transition: color 0.3s ease;
}
.progress-bar {
transition: width 0.1s linear;
}
.word {
transition: all 0.3s ease;
display: inline-block;
white-space: pre-wrap;
}
.word.active {
transform: scale(1.1);
}
.font-poppins {
font-family: 'Poppins', sans-serif;
}
.font-roboto {
font-family: 'Roboto', sans-serif;
}
.font-montserrat {
font-family: 'Montserrat', sans-serif;
}
.font-dancing {
font-family: 'Dancing Script', cursive;
}
.font-opensans {
font-family: 'Open Sans', sans-serif;
}
</style>
</head>
<body class="bg-gray-900 text-white min-h-screen">
<div class="container mx-auto px-4 py-8">
<h1 class="text-4xl font-bold text-center mb-8 text-purple-400">
<i class="fas fa-microphone-alt mr-2"></i> Karaoke Master
</h1>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Controls Panel -->
<div class="bg-gray-800 p-6 rounded-xl shadow-lg">
<h2 class="text-2xl font-semibold mb-4 text-purple-300">
<i class="fas fa-sliders-h mr-2"></i> Controls
</h2>
<div class="space-y-6">
<div>
<label class="block text-sm font-medium mb-1">Highlight Speed</label>
<input type="range" id="speed" min="50" max="500" value="200" class="w-full accent-purple-500">
<div class="flex justify-between text-xs text-gray-400">
<span>Slow</span>
<span>Fast</span>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-1">Highlight Color</label>
<div class="flex space-x-2">
<button data-color="#f472b6" class="w-8 h-8 rounded-full bg-pink-400 border-2 border-transparent hover:border-white focus:border-white" onclick="setHighlightColor('#f472b6')"></button>
<button data-color="#60a5fa" class="w-8 h-8 rounded-full bg-blue-400 border-2 border-transparent hover:border-white focus:border-white" onclick="setHighlightColor('#60a5fa')"></button>
<button data-color="#34d399" class="w-8 h-8 rounded-full bg-green-400 border-2 border-transparent hover:border-white focus:border-white" onclick="setHighlightColor('#34d399')"></button>
<button data-color="#fbbf24" class="w-8 h-8 rounded-full bg-yellow-400 border-2 border-transparent hover:border-white focus:border-white" onclick="setHighlightColor('#fbbf24')"></button>
<button data-color="#f87171" class="w-8 h-8 rounded-full bg-red-400 border-2 border-transparent hover:border-white focus:border-white" onclick="setHighlightColor('#f87171')"></button>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-1">Text Size</label>
<select id="textSize" class="w-full bg-gray-700 border border-gray-600 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500">
<option value="text-sm">Small</option>
<option value="text-base" selected>Medium</option>
<option value="text-lg">Large</option>
<option value="text-xl">Extra Large</option>
</select>
</div>
<div>
<label class="block text-sm font-medium mb-1">Font Family</label>
<select id="fontFamily" class="w-full bg-gray-700 border border-gray-600 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500">
<option value="font-poppins">Poppins</option>
<option value="font-roboto" selected>Roboto</option>
<option value="font-montserrat">Montserrat</option>
<option value="font-dancing">Dancing Script</option>
<option value="font-opensans">Open Sans</option>
</select>
</div>
<div class="pt-4 border-t border-gray-700">
<div class="flex justify-between items-center mb-4">
<span class="text-sm font-medium">Time Elapsed:</span>
<span id="timeCounter" class="font-mono bg-gray-700 px-2 py-1 rounded">00:00.00</span>
</div>
<button id="playBtn" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-4 rounded-lg flex items-center justify-center">
<i class="fas fa-play mr-2"></i> Start Karaoke
</button>
<button id="pauseBtn" class="w-full mt-2 bg-gray-600 hover:bg-gray-700 text-white font-bold py-3 px-4 rounded-lg flex items-center justify-center hidden">
<i class="fas fa-pause mr-2"></i> Pause
</button>
<button id="stopBtn" class="w-full mt-2 bg-red-600 hover:bg-red-700 text-white font-bold py-3 px-4 rounded-lg flex items-center justify-center">
<i class="fas fa-stop mr-2"></i> Stop
</button>
</div>
</div>
</div>
<!-- Lyrics Display -->
<div class="lg:col-span-2">
<div class="bg-gray-800 rounded-xl shadow-lg overflow-hidden">
<div class="p-4 bg-gray-700 flex justify-between items-center">
<h2 class="text-xl font-semibold text-purple-300">
<i class="fas fa-music mr-2"></i> Lyrics Display
</h2>
<div class="w-1/2 bg-gray-600 rounded-full h-2.5">
<div id="progressBar" class="progress-bar h-2.5 rounded-full bg-purple-500" style="width: 0%"></div>
</div>
</div>
<div id="lyricsDisplay" class="lyrics-container p-6 text-center text-base leading-relaxed font-roboto">
<p class="text-gray-400 italic">Enter lyrics below to get started...</p>
</div>
</div>
<!-- Lyrics Input -->
<div class="mt-6 bg-gray-800 rounded-xl shadow-lg overflow-hidden">
<div class="p-4 bg-gray-700">
<h2 class="text-xl font-semibold text-purple-300">
<i class="fas fa-edit mr-2"></i> Lyrics Input
</h2>
</div>
<div class="p-4">
<textarea id="lyricsInput" rows="8" class="w-full bg-gray-700 border border-gray-600 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Enter your lyrics here..."></textarea>
<div class="mt-4 flex justify-between">
<button id="loadSampleBtn" class="bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded-lg">
<i class="fas fa-lightbulb mr-2"></i> Load Sample
</button>
<button id="updateLyricsBtn" class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded-lg">
<i class="fas fa-sync-alt mr-2"></i> Update Lyrics
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// DOM Elements
const lyricsInput = document.getElementById('lyricsInput');
const lyricsDisplay = document.getElementById('lyricsDisplay');
const playBtn = document.getElementById('playBtn');
const pauseBtn = document.getElementById('pauseBtn');
const stopBtn = document.getElementById('stopBtn');
const updateLyricsBtn = document.getElementById('updateLyricsBtn');
const loadSampleBtn = document.getElementById('loadSampleBtn');
const speedControl = document.getElementById('speed');
const textSizeSelect = document.getElementById('textSize');
const fontFamilySelect = document.getElementById('fontFamily');
const progressBar = document.getElementById('progressBar');
const timeCounter = document.getElementById('timeCounter');
// State variables
let words = [];
let currentWordIndex = 0;
let highlightInterval;
let isPlaying = false;
let highlightColor = '#f472b6'; // Default pink color
let startTime = 0;
let elapsedTime = 0;
let timeInterval;
// Initialize
document.addEventListener('DOMContentLoaded', () => {
// Event listeners
playBtn.addEventListener('click', startKaraoke);
pauseBtn.addEventListener('click', pauseKaraoke);
stopBtn.addEventListener('click', stopKaraoke);
updateLyricsBtn.addEventListener('click', updateLyricsDisplay);
loadSampleBtn.addEventListener('click', loadSampleLyrics);
textSizeSelect.addEventListener('change', updateTextSize);
fontFamilySelect.addEventListener('change', updateFontFamily);
// Set initial text size and font
updateTextSize();
updateFontFamily();
});
// Functions
function updateLyricsDisplay() {
const lyrics = lyricsInput.value.trim();
if (!lyrics) return;
// Split into paragraphs
const paragraphs = lyrics.split('\n\n');
// Clear and rebuild display
lyricsDisplay.innerHTML = '';
paragraphs.forEach(para => {
const paraElement = document.createElement('p');
paraElement.className = 'mb-4';
// Split into words and wrap each word in a span
const words = para.split(/(\s+)/).filter(word => word.trim().length > 0);
words.forEach(word => {
const wordSpan = document.createElement('span');
wordSpan.className = 'word';
wordSpan.textContent = word + ' ';
paraElement.appendChild(wordSpan);
});
lyricsDisplay.appendChild(paraElement);
});
// Store words for highlighting
words = Array.from(lyricsDisplay.querySelectorAll('.word'));
currentWordIndex = 0;
progressBar.style.width = '0%';
}
function startKaraoke() {
if (words.length === 0) {
alert('Please enter lyrics first!');
return;
}
if (isPlaying) return;
isPlaying = true;
playBtn.classList.add('hidden');
pauseBtn.classList.remove('hidden');
// Reset highlighting
words.forEach(word => {
word.classList.remove('active');
word.style.color = '';
});
currentWordIndex = 0;
progressBar.style.width = '0%';
// Start time counter
startTime = Date.now() - elapsedTime;
updateTimeCounter();
timeInterval = setInterval(updateTimeCounter, 10);
// Start highlighting words
const speed = parseInt(speedControl.value);
highlightInterval = setInterval(highlightNextWord, speed);
}
function pauseKaraoke() {
if (!isPlaying) return;
isPlaying = false;
pauseBtn.classList.add('hidden');
playBtn.classList.remove('hidden');
clearInterval(highlightInterval);
clearInterval(timeInterval);
}
function stopKaraoke() {
isPlaying = false;
clearInterval(highlightInterval);
clearInterval(timeInterval);
playBtn.classList.remove('hidden');
pauseBtn.classList.add('hidden');
// Reset all words
words.forEach(word => {
word.classList.remove('active');
word.style.color = '';
});
currentWordIndex = 0;
progressBar.style.width = '0%';
// Reset timer
elapsedTime = 0;
updateTimeCounter();
}
function highlightNextWord() {
// Reset previous word
if (currentWordIndex > 0) {
words[currentWordIndex - 1].classList.remove('active');
}
// Check if we've reached the end
if (currentWordIndex >= words.length) {
stopKaraoke();
return;
}
// Highlight current word
const currentWord = words[currentWordIndex];
currentWord.classList.add('active');
currentWord.style.color = highlightColor;
// Scroll to keep word visible
currentWord.scrollIntoView({ behavior: 'smooth', block: 'center' });
// Update progress
const progress = (currentWordIndex / words.length) * 100;
progressBar.style.width = `${progress}%`;
currentWordIndex++;
}
function setHighlightColor(color) {
highlightColor = color;
// Update active word if playing
if (isPlaying && currentWordIndex > 0) {
words[currentWordIndex - 1].style.color = color;
}
}
function updateTextSize() {
const size = textSizeSelect.value;
lyricsDisplay.className = `lyrics-container p-6 text-center ${size} leading-relaxed ${lyricsDisplay.className.split(' ').find(c => c.startsWith('font-')) || 'font-roboto'}`;
}
function updateFontFamily() {
const font = fontFamilySelect.value;
lyricsDisplay.className = `lyrics-container p-6 text-center ${textSizeSelect.value} leading-relaxed ${font}`;
}
function updateTimeCounter() {
if (isPlaying) {
elapsedTime = Date.now() - startTime;
}
const minutes = Math.floor(elapsedTime / 60000);
const seconds = Math.floor((elapsedTime % 60000) / 1000);
const milliseconds = Math.floor((elapsedTime % 1000) / 10);
timeCounter.textContent =
`${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(2, '0')}`;
}
function loadSampleLyrics() {
const sampleLyrics = `[Verse 1]
I see trees of green, red roses too
I see them bloom for me and you
And I think to myself what a wonderful world
[Verse 2]
I see skies of blue and clouds of white
The bright blessed days, the dark sacred nights
And I think to myself what a wonderful world
[Bridge]
The colors of the rainbow so pretty in the sky
Are also on the faces of people going by
I see friends shaking hands saying how do you do
They're really saying I love you
[Verse 3]
I hear babies cry, I watch them grow
They'll learn much more than I'll ever know
And I think to myself what a wonderful world
Yes, I think to myself what a wonderful world`;
lyricsInput.value = sampleLyrics;
updateLyricsDisplay();
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=bibbler/karaoke-master" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
</html>