chordgenius / index.html
tushkum's picture
an app that helps me to find any song guitar chords with the help of ai chat, when i input the song name initials or any form of audio clip like mp3, wav etc, it can suggest the song detail and chords detail, the capo position, then i need to send the lyrics and chords to teleprompter 4k video recording in vertical or horizontal format; after recording transfer to ai video background changer and then audio auto tuner like reverb and gain and compression etc then export to gallery or download to gallery to watch video with song lyrics on screen, i want to make it professional, please use open source api and open ai or publik ai - Initial Deployment
c3a464b verified
raw
history blame
54.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChordGenius - AI Guitar Assistant</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/RecordRTC.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.gradient-bg {
background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 50%, #1d4ed8 100%);
}
.chord-highlight {
background-color: rgba(255, 255, 0, 0.3);
border-radius: 4px;
padding: 0 2px;
}
.teleprompter-text {
font-size: 2.5rem;
line-height: 1.5;
transition: transform 0.3s ease;
}
.waveform {
height: 100px;
background: linear-gradient(to right, #3b82f6, #1d4ed8);
border-radius: 8px;
}
@media (max-width: 768px) {
.teleprompter-text {
font-size: 1.8rem;
}
}
.recording-active {
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); }
100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); }
}
</style>
</head>
<body class="bg-gray-100 font-sans">
<div class="min-h-screen flex flex-col">
<!-- Header -->
<header class="gradient-bg text-white p-4 shadow-lg">
<div class="container mx-auto flex justify-between items-center">
<div class="flex items-center space-x-2">
<i class="fas fa-guitar text-3xl"></i>
<h1 class="text-2xl font-bold">ChordGenius</h1>
</div>
<nav class="hidden md:flex space-x-6">
<a href="#chord-finder" class="hover:text-blue-200 transition">Chord Finder</a>
<a href="#teleprompter" class="hover:text-blue-200 transition">Teleprompter</a>
<a href="#video-editor" class="hover:text-blue-200 transition">Video Editor</a>
</nav>
<button class="md:hidden text-2xl" id="mobile-menu-btn">
<i class="fas fa-bars"></i>
</button>
</div>
<!-- Mobile Menu -->
<div class="md:hidden hidden bg-blue-900 p-4" id="mobile-menu">
<div class="flex flex-col space-y-3">
<a href="#chord-finder" class="hover:text-blue-200 transition">Chord Finder</a>
<a href="#teleprompter" class="hover:text-blue-200 transition">Teleprompter</a>
<a href="#video-editor" class="hover:text-blue-200 transition">Video Editor</a>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-grow container mx-auto p-4">
<!-- Chord Finder Section -->
<section id="chord-finder" class="mb-12 bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-search mr-2 text-blue-600"></i> AI Chord Finder
</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Input Section -->
<div class="space-y-6">
<div>
<label class="block text-gray-700 mb-2 font-medium">Search by Song Name or Artist</label>
<div class="flex">
<input type="text" id="song-search" placeholder="e.g. 'Hotel California' or 'The Beatles'"
class="flex-grow p-3 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<button id="search-btn" class="bg-blue-600 text-white px-4 rounded-r-lg hover:bg-blue-700 transition">
<i class="fas fa-search"></i>
</button>
</div>
</div>
<div class="border-t pt-4">
<label class="block text-gray-700 mb-2 font-medium">Or Upload Audio File</label>
<div class="flex items-center space-x-4">
<label for="audio-upload" class="cursor-pointer bg-blue-100 text-blue-700 px-4 py-2 rounded-lg hover:bg-blue-200 transition flex items-center">
<i class="fas fa-upload mr-2"></i> Choose File
<input type="file" id="audio-upload" accept="audio/*" class="hidden">
</label>
<span id="file-name" class="text-gray-500">No file selected</span>
</div>
<div class="mt-4">
<button id="analyze-btn" class="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition flex items-center disabled:opacity-50" disabled>
<i class="fas fa-microphone-alt mr-2"></i> Analyze Audio
</button>
</div>
</div>
<div id="audio-visualizer" class="waveform hidden mt-4"></div>
<div id="ai-chat" class="mt-6 hidden">
<h3 class="text-lg font-semibold text-gray-700 mb-2">AI Chord Assistant</h3>
<div class="bg-gray-50 p-4 rounded-lg h-48 overflow-y-auto mb-2" id="chat-messages">
<div class="text-sm text-gray-600">AI: Hi! I can help you find chords for any song. Ask me anything about guitar chords!</div>
</div>
<div class="flex">
<input type="text" id="chat-input" placeholder="Ask about chords, capo positions..."
class="flex-grow p-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<button id="send-chat" class="bg-blue-600 text-white px-4 rounded-r-lg hover:bg-blue-700 transition">
<i class="fas fa-paper-plane"></i>
</button>
</div>
</div>
</div>
<!-- Results Section -->
<div>
<div id="loading-spinner" class="hidden flex justify-center items-center h-32">
<div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
</div>
<div id="song-results" class="hidden">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold text-gray-800" id="song-title">Song Title</h3>
<button id="send-to-teleprompter" class="bg-purple-600 text-white px-4 py-1 rounded-lg hover:bg-purple-700 transition flex items-center">
<i class="fas fa-arrow-right mr-2"></i> To Teleprompter
</button>
</div>
<div class="flex items-center space-x-4 mb-4">
<span class="text-gray-600" id="song-artist">Artist</span>
<span class="text-gray-600" id="song-year">Year</span>
</div>
<div class="mb-4">
<h4 class="font-semibold text-gray-700 mb-2">Key & Capo Information</h4>
<div class="bg-gray-50 p-3 rounded-lg">
<div class="grid grid-cols-2 gap-2">
<div>
<span class="text-gray-500">Key:</span>
<span class="font-medium" id="song-key">C Major</span>
</div>
<div>
<span class="text-gray-500">Capo:</span>
<span class="font-medium" id="song-capo">3rd fret</span>
</div>
<div>
<span class="text-gray-500">Difficulty:</span>
<span class="font-medium" id="song-difficulty">Intermediate</span>
</div>
<div>
<span class="text-gray-500">Tuning:</span>
<span class="font-medium" id="song-tuning">Standard</span>
</div>
</div>
</div>
</div>
<div>
<h4 class="font-semibold text-gray-700 mb-2">Chords Used</h4>
<div class="flex flex-wrap gap-2 mb-4" id="chord-bank">
<!-- Chords will be added here dynamically -->
</div>
<h4 class="font-semibold text-gray-700 mb-2">Lyrics with Chords</h4>
<div class="bg-gray-50 p-4 rounded-lg h-64 overflow-y-auto font-mono text-sm" id="song-lyrics">
<!-- Lyrics with chords will be added here -->
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Teleprompter Section -->
<section id="teleprompter" class="mb-12 bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-scroll mr-2 text-purple-600"></i> 4K Teleprompter
</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Controls -->
<div class="space-y-6">
<div>
<label class="block text-gray-700 mb-2 font-medium">Teleprompter Text</label>
<textarea id="teleprompter-input" rows="10" class="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Paste lyrics with chords here or use the 'To Teleprompter' button from Chord Finder"></textarea>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-gray-700 mb-2 font-medium">Scroll Speed</label>
<input type="range" id="scroll-speed" min="1" max="10" value="5" class="w-full">
<div class="flex justify-between text-xs text-gray-500">
<span>Slow</span>
<span>Fast</span>
</div>
</div>
<div>
<label class="block text-gray-700 mb-2 font-medium">Font Size</label>
<input type="range" id="font-size" min="1" max="5" value="3" class="w-full">
<div class="flex justify-between text-xs text-gray-500">
<span>Small</span>
<span>Large</span>
</div>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-gray-700 mb-2 font-medium">Text Color</label>
<select id="text-color" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="text-white">White</option>
<option value="text-yellow-300">Yellow</option>
<option value="text-green-400">Green</option>
<option value="text-blue-300">Blue</option>
</select>
</div>
<div>
<label class="block text-gray-700 mb-2 font-medium">Background</label>
<select id="bg-color" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="bg-black">Black</option>
<option value="bg-gray-800">Dark Gray</option>
<option value="bg-blue-900">Navy Blue</option>
<option value="bg-transparent">Transparent</option>
</select>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-gray-700 mb-2 font-medium">Orientation</label>
<select id="orientation" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="horizontal">Horizontal</option>
<option value="vertical">Vertical</option>
</select>
</div>
<div>
<label class="block text-gray-700 mb-2 font-medium">Mirror Mode</label>
<select id="mirror-mode" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="normal">Normal</option>
<option value="mirrored">Mirrored</option>
</select>
</div>
</div>
<div class="flex space-x-4 pt-4">
<button id="start-teleprompter" class="flex-grow bg-purple-600 text-white px-4 py-2 rounded-lg hover:bg-purple-700 transition flex items-center justify-center">
<i class="fas fa-play mr-2"></i> Start Teleprompter
</button>
<button id="reset-teleprompter" class="bg-gray-200 text-gray-800 px-4 py-2 rounded-lg hover:bg-gray-300 transition">
<i class="fas fa-redo"></i>
</button>
</div>
</div>
<!-- Preview -->
<div>
<div class="bg-black rounded-lg overflow-hidden relative" style="aspect-ratio: 16/9;">
<div id="teleprompter-display" class="h-full w-full flex items-center justify-center overflow-hidden relative">
<div id="teleprompter-text" class="teleprompter-text text-white text-center p-4">
Your teleprompter text will appear here. Adjust settings on the left to customize appearance.
</div>
</div>
</div>
<div class="mt-4 grid grid-cols-2 gap-4">
<button id="start-recording" class="bg-red-600 text-white px-4 py-2 rounded-lg hover:bg-red-700 transition flex items-center justify-center">
<i class="fas fa-circle mr-2"></i> Start Recording
</button>
<button id="stop-recording" class="bg-gray-600 text-white px-4 py-2 rounded-lg hover:bg-gray-700 transition flex items-center justify-center disabled:opacity-50" disabled>
<i class="fas fa-stop mr-2"></i> Stop Recording
</button>
</div>
<div class="mt-4 hidden" id="recording-status">
<div class="flex items-center text-red-600">
<i class="fas fa-circle mr-2"></i>
<span>Recording in progress...</span>
</div>
<div class="mt-2 text-sm text-gray-600">
<span id="recording-timer">00:00:00</span>
</div>
</div>
</div>
</div>
</section>
<!-- Video Editor Section -->
<section id="video-editor" class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center">
<i class="fas fa-film mr-2 text-green-600"></i> AI Video Editor
</h2>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Video Preview -->
<div class="lg:col-span-2">
<div class="bg-black rounded-lg overflow-hidden" style="aspect-ratio: 16/9;">
<video id="video-preview" controls class="w-full h-full" style="display: none;"></video>
<canvas id="video-canvas" class="w-full h-full" style="display: none;"></canvas>
<div id="no-video" class="h-full flex items-center justify-center text-gray-400">
<div class="text-center">
<i class="fas fa-video text-4xl mb-2"></i>
<p>Your recorded video will appear here</p>
</div>
</div>
</div>
<div class="mt-4 flex flex-wrap gap-2">
<button id="play-video" class="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition flex items-center disabled:opacity-50" disabled>
<i class="fas fa-play mr-2"></i> Play
</button>
<button id="pause-video" class="bg-yellow-500 text-white px-4 py-2 rounded-lg hover:bg-yellow-600 transition flex items-center disabled:opacity-50" disabled>
<i class="fas fa-pause mr-2"></i> Pause
</button>
<button id="apply-effects" class="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition flex items-center disabled:opacity-50" disabled>
<i class="fas fa-magic mr-2"></i> AI Enhance
</button>
<button id="export-video" class="bg-purple-600 text-white px-4 py-2 rounded-lg hover:bg-purple-700 transition flex items-center disabled:opacity-50" disabled>
<i class="fas fa-download mr-2"></i> Export
</button>
</div>
</div>
<!-- AI Effects Panel -->
<div>
<div class="bg-gray-50 rounded-lg p-4">
<h3 class="font-semibold text-gray-700 mb-3">AI Video Effects</h3>
<div class="space-y-4">
<div>
<label class="block text-gray-700 mb-2">Background Replacement</label>
<select id="bg-replacement" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="none">None</option>
<option value="blur">Blur Background</option>
<option value="studio">Studio Background</option>
<option value="nature">Nature Scene</option>
<option value="stage">Concert Stage</option>
<option value="custom">Custom Image</option>
</select>
<div id="custom-bg-upload" class="mt-2 hidden">
<label class="block text-gray-700 mb-1 text-sm">Upload Background</label>
<input type="file" id="bg-image-upload" accept="image/*" class="w-full text-sm">
</div>
</div>
<div>
<label class="block text-gray-700 mb-2">Lighting Adjustment</label>
<select id="lighting-effect" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="none">None</option>
<option value="warm">Warm Tone</option>
<option value="cool">Cool Tone</option>
<option value="dramatic">Dramatic Lighting</option>
<option value="soft">Soft Lighting</option>
</select>
</div>
<div>
<label class="block text-gray-700 mb-2">AI Audio Enhancement</label>
<select id="audio-effect" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="none">None</option>
<option value="studio">Studio Quality</option>
<option value="reverb">Add Reverb</option>
<option value="compression">Compression</option>
<option value="auto-tune">Auto-Tune</option>
<option value="custom">Custom Settings</option>
</select>
<div id="audio-custom-settings" class="mt-2 hidden space-y-2">
<div>
<label class="block text-gray-700 text-sm">Reverb</label>
<input type="range" id="reverb-level" min="0" max="100" value="0" class="w-full">
</div>
<div>
<label class="block text-gray-700 text-sm">Compression</label>
<input type="range" id="compression-level" min="0" max="100" value="50" class="w-full">
</div>
<div>
<label class="block text-gray-700 text-sm">Gain</label>
<input type="range" id="gain-level" min="-10" max="10" value="0" class="w-full">
</div>
</div>
</div>
<div>
<label class="block text-gray-700 mb-2">Text Overlay</label>
<div class="flex items-center space-x-2">
<input type="checkbox" id="show-chords" class="rounded text-blue-600">
<label for="show-chords">Show Chords</label>
</div>
<div class="flex items-center space-x-2 mt-1">
<input type="checkbox" id="show-lyrics" class="rounded text-blue-600" checked>
<label for="show-lyrics">Show Lyrics</label>
</div>
</div>
<button id="preview-effects" class="w-full bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition flex items-center justify-center disabled:opacity-50" disabled>
<i class="fas fa-eye mr-2"></i> Preview Effects
</button>
</div>
</div>
<div class="mt-4 bg-gray-50 rounded-lg p-4">
<h3 class="font-semibold text-gray-700 mb-3">Export Settings</h3>
<div class="space-y-3">
<div>
<label class="block text-gray-700 mb-1 text-sm">Resolution</label>
<select id="export-resolution" class="w-full p-2 border border-gray-300 rounded-lg text-sm">
<option value="1080">1080p (Full HD)</option>
<option value="720">720p (HD)</option>
<option value="4k" selected>4K (UHD)</option>
</select>
</div>
<div>
<label class="block text-gray-700 mb-1 text-sm">Format</label>
<select id="export-format" class="w-full p-2 border border-gray-300 rounded-lg text-sm">
<option value="mp4" selected>MP4</option>
<option value="mov">MOV</option>
<option value="webm">WebM</option>
</select>
</div>
<div>
<label class="block text-gray-700 mb-1 text-sm">Quality</label>
<select id="export-quality" class="w-full p-2 border border-gray-300 rounded-lg text-sm">
<option value="high">High</option>
<option value="medium" selected>Medium</option>
<option value="low">Low</option>
</select>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="gradient-bg text-white p-6 mt-12">
<div class="container mx-auto">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<h3 class="text-xl font-bold mb-4">ChordGenius</h3>
<p class="text-blue-200">Your AI-powered guitar companion for finding chords, creating teleprompter videos, and professional video editing.</p>
</div>
<div>
<h4 class="font-semibold mb-4">Features</h4>
<ul class="space-y-2">
<li><a href="#chord-finder" class="text-blue-200 hover:text-white transition">AI Chord Finder</a></li>
<li><a href="#teleprompter" class="text-blue-200 hover:text-white transition">4K Teleprompter</a></li>
<li><a href="#video-editor" class="text-blue-200 hover:text-white transition">AI Video Editor</a></li>
</ul>
</div>
<div>
<h4 class="font-semibold mb-4">Connect</h4>
<div class="flex space-x-4">
<a href="#" class="text-2xl text-blue-200 hover:text-white transition"><i class="fab fa-facebook"></i></a>
<a href="#" class="text-2xl text-blue-200 hover:text-white transition"><i class="fab fa-twitter"></i></a>
<a href="#" class="text-2xl text-blue-200 hover:text-white transition"><i class="fab fa-instagram"></i></a>
<a href="#" class="text-2xl text-blue-200 hover:text-white transition"><i class="fab fa-youtube"></i></a>
</div>
</div>
</div>
<div class="border-t border-blue-800 mt-8 pt-6 text-center text-blue-200">
<p>&copy; 2023 ChordGenius. All rights reserved.</p>
</div>
</div>
</footer>
</div>
<script>
// Mobile Menu Toggle
document.getElementById('mobile-menu-btn').addEventListener('click', function() {
const menu = document.getElementById('mobile-menu');
menu.classList.toggle('hidden');
});
// Sample data for demonstration
const sampleSongs = {
"hotel california": {
title: "Hotel California",
artist: "Eagles",
year: "1976",
key: "B minor",
capo: "No capo (or 7th fret for easier chords)",
difficulty: "Intermediate",
tuning: "Standard",
chords: ["Bm", "F#", "A", "E", "G", "D", "Em", "F#7"],
lyrics: `
[Intro]
Bm F# A E G D Em F#7
[Verse 1]
Bm F#
On a dark desert highway
A E
Cool wind in my hair
G D
Warm smell of colitas
Em F#7
Rising up through the air
[Chorus]
Bm F# A E
Welcome to the Hotel California
G D Em F#7
Such a lovely place (such a lovely place)
Bm F# A E
Plenty of room at the Hotel California
G D Em F#7
Any time of year (any time of year)
`
},
"wonderwall": {
title: "Wonderwall",
artist: "Oasis",
year: "1995",
key: "F# minor (capo 2)",
capo: "2nd fret",
difficulty: "Beginner",
tuning: "Standard",
chords: ["Em7", "G", "D", "A7sus4", "C", "D7"],
lyrics: `
[Intro]
Em7 G D A7sus4
[Verse 1]
Em7 G
Today is gonna be the day
D A7sus4
That they're gonna throw it back to you
Em7 G
By now you should've somehow
D A7sus4
Realized what you gotta do
[Chorus]
C D7
I don't believe that anybody
Em7 G
Feels the way I do
C D7
About you now
`
}
};
// Chord Finder Functionality
document.getElementById('search-btn').addEventListener('click', function() {
const searchTerm = document.getElementById('song-search').value.toLowerCase();
showLoading(true);
// Simulate API call with timeout
setTimeout(() => {
if (sampleSongs[searchTerm]) {
displaySongResults(sampleSongs[searchTerm]);
} else {
// If no exact match, try to find partial matches
const matches = Object.keys(sampleSongs).filter(song =>
song.includes(searchTerm) || sampleSongs[song].artist.toLowerCase().includes(searchTerm)
);
if (matches.length > 0) {
displaySongResults(sampleSongs[matches[0]]);
} else {
document.getElementById('chat-messages').innerHTML += `
<div class="text-sm text-gray-600 mt-2">AI: I couldn't find an exact match for "${searchTerm}". Try being more specific or upload an audio file for analysis.</div>
`;
showLoading(false);
}
}
}, 1500);
});
// File Upload Handling
document.getElementById('audio-upload').addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
document.getElementById('file-name').textContent = file.name;
document.getElementById('analyze-btn').disabled = false;
// Simple audio visualization for demo
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const fileReader = new FileReader();
fileReader.onload = function(e) {
audioContext.decodeAudioData(e.target.result).then(function(buffer) {
visualizeAudio(buffer);
});
};
fileReader.readAsArrayBuffer(file);
}
});
function visualizeAudio(buffer) {
const audioVisualizer = document.getElementById('audio-visualizer');
audioVisualizer.classList.remove('hidden');
// Simple waveform visualization
const canvas = document.createElement('canvas');
canvas.width = audioVisualizer.offsetWidth;
canvas.height = audioVisualizer.offsetHeight;
audioVisualizer.innerHTML = '';
audioVisualizer.appendChild(canvas);
const ctx = canvas.getContext('2d');
const data = buffer.getChannelData(0);
const step = Math.ceil(data.length / canvas.width);
const amp = canvas.height / 2;
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 2;
for (let i = 0; i < canvas.width; i++) {
const min = 1.0;
const max = -1.0;
for (let j = 0; j < step; j++) {
const datum = data[(i * step) + j];
if (datum < min) min = datum;
if (datum > max) max = datum;
}
ctx.moveTo(i, (1 + min) * amp);
ctx.lineTo(i, (1 + max) * amp);
}
ctx.stroke();
}
document.getElementById('analyze-btn').addEventListener('click', function() {
showLoading(true);
// Simulate AI audio analysis with timeout
setTimeout(() => {
displaySongResults(sampleSongs['hotel california']); // Default to Hotel California for demo
document.getElementById('chat-messages').innerHTML += `
<div class="text-sm text-gray-600 mt-2">AI: I've analyzed your audio file and detected the song "Hotel California" by Eagles. Here are the chords and lyrics.</div>
`;
}, 2000);
});
function showLoading(show) {
const loadingSpinner = document.getElementById('loading-spinner');
const songResults = document.getElementById('song-results');
if (show) {
loadingSpinner.classList.remove('hidden');
songResults.classList.add('hidden');
} else {
loadingSpinner.classList.add('hidden');
songResults.classList.remove('hidden');
}
}
function displaySongResults(song) {
document.getElementById('song-title').textContent = song.title;
document.getElementById('song-artist').textContent = song.artist;
document.getElementById('song-year').textContent = song.year;
document.getElementById('song-key').textContent = song.key;
document.getElementById('song-capo').textContent = song.capo;
document.getElementById('song-difficulty').textContent = song.difficulty;
document.getElementById('song-tuning').textContent = song.tuning;
// Display chords
const chordBank = document.getElementById('chord-bank');
chordBank.innerHTML = '';
song.chords.forEach(chord => {
const chordElement = document.createElement('div');
chordElement.className = 'bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-sm font-medium';
chordElement.textContent = chord;
chordBank.appendChild(chordElement);
});
// Display lyrics with chords
const lyricsElement = document.getElementById('song-lyrics');
lyricsElement.innerHTML = '';
// Process lyrics to highlight chords
const lines = song.lyrics.split('\n');
lines.forEach(line => {
const lineElement = document.createElement('div');
lineElement.className = 'mb-1';
// Simple chord detection (in real app, would need more sophisticated parsing)
const words = line.split(/(\[.*?\])|(\b[A-Za-z0-9#]+\b)/g).filter(Boolean);
words.forEach(word => {
if (song.chords.includes(word)) {
const chordSpan = document.createElement('span');
chordSpan.className = 'chord-highlight text-blue-600 font-bold';
chordSpan.textContent = word;
lineElement.appendChild(chordSpan);
} else {
lineElement.appendChild(document.createTextNode(word));
}
});
lyricsElement.appendChild(lineElement);
});
// Show AI chat
document.getElementById('ai-chat').classList.remove('hidden');
showLoading(false);
}
// AI Chat Functionality
document.getElementById('send-chat').addEventListener('click', function() {
const chatInput = document.getElementById('chat-input');
const message = chatInput.value.trim();
if (message) {
// Add user message to chat
const chatMessages = document.getElementById('chat-messages');
chatMessages.innerHTML += `
<div class="text-right text-sm text-blue-700 mb-2">You: ${message}</div>
`;
// Simulate AI response
setTimeout(() => {
let response = "I'm not sure how to answer that. Can you be more specific?";
if (message.toLowerCase().includes('capo')) {
const currentSong = document.getElementById('song-title').textContent;
const capoPosition = document.getElementById('song-capo').textContent;
response = `For ${currentSong}, the recommended capo position is ${capoPosition}.`;
} else if (message.toLowerCase().includes('chord') || message.toLowerCase().includes('play')) {
const chords = Array.from(document.querySelectorAll('#chord-bank div')).map(el => el.textContent).join(', ');
response = `The main chords used in this song are: ${chords}. Would you like me to explain how to play any of these chords?`;
} else if (message.toLowerCase().includes('easy') || message.toLowerCase().includes('simpl')) {
response = "You can simplify some chords by using power chords or open chord variations. For example, try playing Bm as Bm7 or just the root and fifth.";
}
chatMessages.innerHTML += `
<div class="text-sm text-gray-600 mt-2">AI: ${response}</div>
`;
chatMessages.scrollTop = chatMessages.scrollHeight;
}, 500);
chatInput.value = '';
chatMessages.scrollTop = chatMessages.scrollHeight;
}
});
// Send to Teleprompter
document.getElementById('send-to-teleprompter').addEventListener('click', function() {
const lyrics = document.getElementById('song-lyrics').textContent;
document.getElementById('teleprompter-input').value = lyrics;
// Scroll to teleprompter section
document.getElementById('teleprompter').scrollIntoView({ behavior: 'smooth' });
});
// Teleprompter Functionality
let teleprompterInterval;
let scrollPosition = 0;
document.getElementById('start-teleprompter').addEventListener('click', function() {
const text = document.getElementById('teleprompter-input').value;
if (!text) return;
const speed = document.getElementById('scroll-speed').value;
const fontSize = document.getElementById('font-size').value;
const textColor = document.getElementById('text-color').value;
const bgColor = document.getElementById('bg-color').value;
const orientation = document.getElementById('orientation').value;
const mirrorMode = document.getElementById('mirror-mode').value;
const teleprompterText = document.getElementById('teleprompter-text');
teleprompterText.innerHTML = text.replace(/\n/g, '<br>');
teleprompterText.className = `teleprompter-text ${textColor} text-center p-4`;
const teleprompterDisplay = document.getElementById('teleprompter-display');
teleprompterDisplay.className = `h-full w-full flex items-center justify-center overflow-hidden relative ${bgColor}`;
// Set font size based on slider (1-5)
const sizeMap = {1: '1.5rem', 2: '2rem', 3: '2.5rem', 4: '3rem', 5: '3.5rem'};
teleprompterText.style.fontSize = sizeMap[fontSize];
// Handle orientation
if (orientation === 'vertical') {
teleprompterDisplay.style.aspectRatio = '9/16';
} else {
teleprompterDisplay.style.aspectRatio = '16/9';
}
// Handle mirror mode
if (mirrorMode === 'mirrored') {
teleprompterText.style.transform = 'scaleX(-1)';
} else {
teleprompterText.style.transform = 'scaleX(1)';
}
// Start scrolling
scrollPosition = 0;
teleprompterText.style.transform += ` translateY(${scrollPosition}px)`;
clearInterval(teleprompterInterval);
teleprompterInterval = setInterval(() => {
scrollPosition -= 1;
teleprompterText.style.transform = (mirrorMode === 'mirrored' ? 'scaleX(-1)' : 'scaleX(1)') + ` translateY(${scrollPosition}px)`;
// Reset if scrolled past end
if (scrollPosition < -teleprompterText.offsetHeight) {
scrollPosition = teleprompterDisplay.offsetHeight;
}
}, 100 - (speed * 9));
});
document.getElementById('reset-teleprompter').addEventListener('click', function() {
clearInterval(teleprompterInterval);
scrollPosition = 0;
document.getElementById('teleprompter-text').style.transform = 'translateY(0)';
});
// Video Recording Functionality
let mediaRecorder;
let recordedChunks = [];
let recordingStartTime;
let timerInterval;
document.getElementById('start-recording').addEventListener('click', async function() {
try {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: {
width: { ideal: 3840 },
height: { ideal: 2160 },
frameRate: { ideal: 60 }
},
audio: true
});
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = function(e) {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
};
mediaRecorder.onstop = function() {
const blob = new Blob(recordedChunks, { type: 'video/webm' });
const videoUrl = URL.createObjectURL(blob);
const videoPreview = document.getElementById('video-preview');
videoPreview.src = videoUrl;
videoPreview.style.display = 'block';
document.getElementById('no-video').style.display = 'none';
// Enable video editor buttons
document.getElementById('play-video').disabled = false;
document.getElementById('pause-video').disabled = false;
document.getElementById('apply-effects').disabled = false;
document.getElementById('export-video').disabled = false;
document.getElementById('preview-effects').disabled = false;
// Stop all tracks
stream.getTracks().forEach(track => track.stop());
// Clear timer
clearInterval(timerInterval);
document.getElementById('recording-status').classList.add('hidden');
};
recordedChunks = [];
mediaRecorder.start(100); // Collect data every 100ms
recordingStartTime = Date.now();
// Update timer
timerInterval = setInterval(updateRecordingTimer, 1000);
// Update UI
document.getElementById('recording-status').classList.remove('hidden');
document.getElementById('start-recording').disabled = true;
document.getElementById('stop-recording').disabled = false;
document.getElementById('start-recording').classList.add('recording-active');
} catch (err) {
console.error('Error recording:', err);
alert('Could not start recording. Please make sure to select a window or screen to record.');
}
});
function updateRecordingTimer() {
const elapsed = Math.floor((Date.now() - recordingStartTime) / 1000);
const hours = Math.floor(elapsed / 3600).toString().padStart(2, '0');
const minutes = Math.floor((elapsed % 3600) / 60).toString().padStart(2, '0');
const seconds = (elapsed % 60).toString().padStart(2, '0');
document.getElementById('recording-timer').textContent = `${hours}:${minutes}:${seconds}`;
}
document.getElementById('stop-recording').addEventListener('click', function() {
if (mediaRecorder && mediaRecorder.state !== 'inactive') {
mediaRecorder.stop();
document.getElementById('start-recording').disabled = false;
document.getElementById('stop-recording').disabled = true;
document.getElementById('start-recording').classList.remove('recording-active');
}
});
// Video Editor Functionality
document.getElementById('play-video').addEventListener('click', function() {
const video = document.getElementById('video-preview');
video.play();
});
document.getElementById('pause-video').addEventListener('click', function() {
const video = document.getElementById('video-preview');
video.pause();
});
document.getElementById('bg-replacement').addEventListener('change', function() {
const value = this.value;
const customUpload = document.getElementById('custom-bg-upload');
if (value === 'custom') {
customUpload.classList.remove('hidden');
} else {
customUpload.classList.add('hidden');
}
});
document.getElementById('audio-effect').addEventListener('change', function() {
const value = this.value;
const customSettings = document.getElementById('audio-custom-settings');
if (value === 'custom') {
customSettings.classList.remove('hidden');
} else {
customSettings.classList.add('hidden');
}
});
document.getElementById('preview-effects').addEventListener('click', function() {
// In a real app, this would apply the selected effects to a preview
alert('In the full app, this would show a preview of your selected effects before applying them.');
});
document.getElementById('apply-effects').addEventListener('click', function() {
// Simulate AI processing
showLoading(true);
const videoCanvas = document.getElementById('video-canvas');
const videoPreview = document.getElementById('video-preview');
setTimeout(() => {
// In a real app, this would apply the selected effects using AI/WebGL
videoPreview.style.display = 'none';
videoCanvas.style.display = 'block';
const ctx = videoCanvas.getContext('2d');
videoCanvas.width = videoPreview.videoWidth;
videoCanvas.height = videoPreview.videoHeight;
// Draw a sample effect (in real app, would apply actual AI effects)
ctx.filter = 'contrast(1.2) brightness(1.1) saturate(1.3)';
ctx.drawImage(videoPreview, 0, 0, videoCanvas.width, videoCanvas.height);
showLoading(false);
alert('AI effects applied successfully! The video has been enhanced with better lighting and background.');
}, 2000);
});
document.getElementById('export-video').addEventListener('click', function() {
// In a real app, this would export the final video
alert('Video exported successfully! In the full app, this would save to your device or gallery.');
// Simulate download
const link = document.createElement('a');
link.href = document.getElementById('video-preview').src;
link.download = 'chordgenius-video.mp4';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
// Initialize the app
document.addEventListener('DOMContentLoaded', function() {
// Show AI chat by default with welcome message
document.getElementById('ai-chat').classList.remove('hidden');
// For demo purposes, show the Hotel California results
displaySongResults(sampleSongs['hotel california']);
});
</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=tushkum/chordgenius" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>