videoAI / index.html
sravya's picture
Upload 33 files
54ed165 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Video Generator - Free Hailuo Clone</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
padding: 40px;
max-width: 600px;
width: 100%;
}
h1 {
color: #333;
margin-bottom: 10px;
font-size: 28px;
text-align: center;
}
.subtitle {
color: #666;
text-align: center;
margin-bottom: 30px;
font-size: 14px;
}
.input-group {
margin-bottom: 20px;
}
label {
display: block;
color: #555;
margin-bottom: 8px;
font-weight: 500;
}
#prompt {
width: 100%;
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 10px;
font-size: 16px;
transition: border-color 0.3s;
font-family: inherit;
}
#prompt:focus {
outline: none;
border-color: #667eea;
}
.char-counter {
text-align: right;
font-size: 12px;
color: #999;
margin-top: 5px;
}
button {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
button:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4);
}
button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.status {
margin-top: 20px;
padding: 12px;
border-radius: 8px;
text-align: center;
font-size: 14px;
display: none;
}
.status.info {
background: #e3f2fd;
color: #1976d2;
display: block;
}
.status.success {
background: #e8f5e9;
color: #388e3c;
display: block;
}
.status.error {
background: #ffebee;
color: #d32f2f;
display: block;
}
.loader {
border: 3px solid #f3f3f3;
border-top: 3px solid #667eea;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 20px auto;
display: none;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.video-container {
margin-top: 20px;
display: none;
}
video {
width: 100%;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}
.download-btn {
margin-top: 10px;
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
display: none;
}
.example-prompts {
margin-top: 20px;
padding: 15px;
background: #f5f5f5;
border-radius: 10px;
}
.example-prompts h3 {
font-size: 14px;
color: #666;
margin-bottom: 10px;
}
.example-prompt {
display: inline-block;
padding: 6px 12px;
margin: 4px;
background: white;
border: 1px solid #ddd;
border-radius: 20px;
font-size: 12px;
cursor: pointer;
transition: all 0.2s;
}
.example-prompt:hover {
background: #667eea;
color: white;
border-color: #667eea;
}
</style>
</head>
<body>
<div class="container">
<h1>🎬 AI Video Generator</h1>
<p class="subtitle">Create amazing videos from text using AI</p>
<div class="input-group">
<label for="prompt">Enter your prompt:</label>
<textarea
id="prompt"
rows="3"
placeholder="Describe the video you want to create (e.g., A golden retriever running through a field of flowers at sunset)"
maxlength="500"
></textarea>
<div class="char-counter">
<span id="char-count">0</span>/500 characters
</div>
</div>
<button id="generate-btn" onclick="generateVideo()">
Generate Video
</button>
<div class="loader" id="loader"></div>
<div class="status" id="status"></div>
<div class="video-container" id="video-container">
<video id="video-output" controls></video>
<button class="download-btn" id="download-btn" onclick="downloadVideo()">
Download Video
</button>
</div>
<div class="example-prompts">
<h3>💡 Try these examples:</h3>
<span class="example-prompt" onclick="setPrompt('A dog running in a park')">🐕 Dog in park</span>
<span class="example-prompt" onclick="setPrompt('Ocean waves crashing on a beach at sunset')">🌊 Ocean sunset</span>
<span class="example-prompt" onclick="setPrompt('A bird flying through clouds')">🦅 Bird flying</span>
<span class="example-prompt" onclick="setPrompt('City street with cars at night')">🌃 City night</span>
</div>
</div>
<script>
const promptInput = document.getElementById('prompt');
const charCount = document.getElementById('char-count');
const generateBtn = document.getElementById('generate-btn');
const loader = document.getElementById('loader');
const status = document.getElementById('status');
const videoContainer = document.getElementById('video-container');
const videoOutput = document.getElementById('video-output');
const downloadBtn = document.getElementById('download-btn');
let currentVideoUrl = null;
// Character counter
promptInput.addEventListener('input', () => {
const length = promptInput.value.length;
charCount.textContent = length;
if (length > 450) {
charCount.style.color = '#d32f2f';
} else {
charCount.style.color = '#999';
}
});
// Enable Enter key to submit (Ctrl+Enter for textarea)
promptInput.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.key === 'Enter') {
generateVideo();
}
});
function setPrompt(text) {
promptInput.value = text;
promptInput.dispatchEvent(new Event('input'));
}
function showStatus(message, type) {
status.textContent = message;
status.className = 'status ' + type;
}
function hideStatus() {
status.style.display = 'none';
}
async function generateVideo() {
const prompt = promptInput.value.trim();
// Validation
if (!prompt) {
showStatus('Please enter a prompt', 'error');
return;
}
if (prompt.length < 3) {
showStatus('Prompt must be at least 3 characters long', 'error');
return;
}
// UI updates
generateBtn.disabled = true;
generateBtn.textContent = 'Generating...';
loader.style.display = 'block';
videoContainer.style.display = 'none';
downloadBtn.style.display = 'none';
showStatus('🎨 Creating your video... This may take 10-60 seconds', 'info');
try {
const response = await fetch('http://localhost:5000/generate-video', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt })
});
const data = await response.json();
if (!response.ok || data.error) {
throw new Error(data.error || 'Failed to generate video');
}
// Success
currentVideoUrl = data.video_url;
videoOutput.src = currentVideoUrl;
videoContainer.style.display = 'block';
downloadBtn.style.display = 'block';
showStatus('✅ Video generated successfully!', 'success');
// Auto-play video
videoOutput.play().catch(() => {
// Autoplay might be blocked by browser
});
} catch (error) {
console.error('Error:', error);
showStatus('❌ Error: ' + error.message, 'error');
} finally {
generateBtn.disabled = false;
generateBtn.textContent = 'Generate Video';
loader.style.display = 'none';
}
}
async function downloadVideo() {
if (!currentVideoUrl) return;
try {
showStatus('📥 Preparing download...', 'info');
const response = await fetch(currentVideoUrl);
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `ai-video-${Date.now()}.mp4`;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
showStatus('✅ Download started!', 'success');
} catch (error) {
console.error('Download error:', error);
showStatus('❌ Failed to download video', 'error');
}
}
// Check server health on load
window.addEventListener('load', async () => {
try {
const response = await fetch('http://localhost:5000/health');
const data = await response.json();
if (data.status === 'healthy' && data.client_initialized) {
console.log('✅ Server is healthy and ready');
} else {
showStatus('⚠️ Server may not be fully initialized', 'error');
}
} catch (error) {
showStatus('⚠️ Cannot connect to server. Make sure backend is running on port 5000', 'error');
}
});
</script>
</body>
</html>