Spaces:
Running
Running
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>AI Video Generator Studio</title> | |
| <!-- Importation de la police Inter (Moderne et clean) --> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <!-- Importation des icônes FontAwesome --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| /* ========================================= | |
| VARIABLES CSS & RESET | |
| ========================================= */ | |
| :root { | |
| --bg-body: #09090b; | |
| --bg-sidebar: #121214; | |
| --bg-card: #18181b; | |
| --bg-input: #27272a; | |
| --primary: #8b5cf6; /* Violet */ | |
| --primary-hover: #7c3aed; | |
| --accent: #ec4899; /* Rose */ | |
| --text-main: #ffffff; | |
| --text-secondary: #a1a1aa; | |
| --border: #27272a; | |
| --success: #10b981; | |
| --radius-md: 12px; | |
| --radius-lg: 16px; | |
| --header-height: 70px; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| outline: none; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: var(--bg-body); | |
| color: var(--text-main); | |
| height: 100vh; | |
| overflow: hidden; /* Prevent body scroll, handle inside containers */ | |
| display: flex; | |
| } | |
| /* Lien obligatoire "Built with anycoder" */ | |
| .anycoder-credit { | |
| position: fixed; | |
| bottom: 10px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| font-size: 0.8rem; | |
| color: var(--text-secondary); | |
| z-index: 1000; | |
| text-decoration: none; | |
| opacity: 0.6; | |
| transition: opacity 0.3s; | |
| background: rgba(0,0,0,0.5); | |
| padding: 4px 12px; | |
| border-radius: 20px; | |
| backdrop-filter: blur(4px); | |
| } | |
| .anycoder-credit:hover { | |
| opacity: 1; | |
| color: var(--primary); | |
| } | |
| /* ========================================= | |
| LAYOUT PRINCIPAL | |
| ========================================= */ | |
| .app-container { | |
| display: flex; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| /* SIDEBAR */ | |
| .sidebar { | |
| width: 260px; | |
| background-color: var(--bg-sidebar); | |
| border-right: 1px solid var(--border); | |
| display: flex; | |
| flex-direction: column; | |
| padding: 20px; | |
| transition: transform 0.3s ease; | |
| } | |
| .logo { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| color: var(--text-main); | |
| margin-bottom: 40px; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .logo i { | |
| color: var(--primary); | |
| } | |
| .nav-menu { | |
| list-style: none; | |
| flex: 1; | |
| } | |
| .nav-item { | |
| margin-bottom: 8px; | |
| } | |
| .nav-link { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| padding: 12px 16px; | |
| color: var(--text-secondary); | |
| text-decoration: none; | |
| border-radius: var(--radius-md); | |
| transition: all 0.2s; | |
| font-weight: 500; | |
| } | |
| .nav-link:hover, .nav-link.active { | |
| background-color: var(--bg-input); | |
| color: var(--text-main); | |
| } | |
| .nav-link.active { | |
| border-left: 3px solid var(--primary); | |
| } | |
| .user-profile { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| padding-top: 20px; | |
| border-top: 1px solid var(--border); | |
| } | |
| .avatar-small { | |
| width: 36px; | |
| height: 36px; | |
| border-radius: 50%; | |
| background: linear-gradient(45deg, var(--primary), var(--accent)); | |
| } | |
| /* MAIN CONTENT */ | |
| .main-content { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| position: relative; | |
| } | |
| .top-bar { | |
| height: var(--header-height); | |
| border-bottom: 1px solid var(--border); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 30px; | |
| } | |
| .page-title { | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| } | |
| .credits { | |
| background: rgba(139, 92, 246, 0.1); | |
| color: var(--primary); | |
| padding: 6px 12px; | |
| border-radius: 20px; | |
| font-size: 0.85rem; | |
| font-weight: 600; | |
| } | |
| /* SCROLLABLE AREA */ | |
| .content-scroll { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 30px; | |
| } | |
| /* ========================================= | |
| GENERATOR SECTION | |
| ========================================= */ | |
| .generator-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 400px; | |
| gap: 30px; | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| } | |
| /* INPUT AREA */ | |
| .input-card { | |
| background-color: var(--bg-card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-lg); | |
| padding: 24px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 20px; | |
| } | |
| .form-group { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 8px; | |
| } | |
| .form-label { | |
| font-size: 0.9rem; | |
| color: var(--text-secondary); | |
| font-weight: 500; | |
| } | |
| textarea.prompt-input { | |
| width: 100%; | |
| height: 120px; | |
| background-color: var(--bg-input); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| padding: 16px; | |
| color: var(--text-main); | |
| font-family: inherit; | |
| font-size: 1rem; | |
| resize: none; | |
| transition: border-color 0.2s; | |
| } | |
| textarea.prompt-input:focus { | |
| border-color: var(--primary); | |
| } | |
| /* OPTIONS CONTROLS */ | |
| .controls-row { | |
| display: flex; | |
| gap: 20px; | |
| flex-wrap: wrap; | |
| } | |
| .control-group { | |
| flex: 1; | |
| min-width: 140px; | |
| } | |
| select, .custom-select-trigger { | |
| width: 100%; | |
| background-color: var(--bg-input); | |
| border: 1px solid var(--border); | |
| color: var(--text-main); | |
| padding: 10px 14px; | |
| border-radius: var(--radius-md); | |
| cursor: pointer; | |
| appearance: none; /* Hide default arrow for custom styling if needed */ | |
| } | |
| /* Style Chips for Ratios */ | |
| .ratio-options { | |
| display: flex; | |
| background: var(--bg-input); | |
| padding: 4px; | |
| border-radius: var(--radius-md); | |
| gap: 4px; | |
| } | |
| .ratio-btn { | |
| flex: 1; | |
| background: transparent; | |
| border: none; | |
| color: var(--text-secondary); | |
| padding: 8px; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| font-size: 0.85rem; | |
| transition: all 0.2s; | |
| } | |
| .ratio-btn.active { | |
| background-color: var(--bg-card); | |
| color: var(--text-main); | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.2); | |
| } | |
| .generate-btn { | |
| background: linear-gradient(135deg, var(--primary), var(--accent)); | |
| color: white; | |
| border: none; | |
| padding: 16px; | |
| border-radius: var(--radius-md); | |
| font-size: 1rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: transform 0.1s, opacity 0.2s; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| } | |
| .generate-btn:hover { | |
| opacity: 0.9; | |
| } | |
| .generate-btn:active { | |
| transform: scale(0.98); | |
| } | |
| .generate-btn:disabled { | |
| background: var(--bg-input); | |
| color: var(--text-secondary); | |
| cursor: not-allowed; | |
| } | |
| /* PREVIEW AREA */ | |
| .preview-card { | |
| background-color: var(--bg-card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-lg); | |
| padding: 24px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| min-height: 400px; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .video-placeholder { | |
| width: 100%; | |
| aspect-ratio: 16/9; | |
| background-color: #000; | |
| border-radius: var(--radius-md); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| /* Animation when "video" is playing */ | |
| .video-active { | |
| background-image: url('https://picsum.photos/seed/ai-video/800/450'); | |
| background-size: cover; | |
| background-position: center; | |
| } | |
| .video-overlay { | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient(to top, rgba(0,0,0,0.6), transparent); | |
| display: flex; | |
| align-items: flex-end; | |
| padding: 15px; | |
| } | |
| .play-btn { | |
| width: 60px; | |
| height: 60px; | |
| background: rgba(255,255,255,0.2); | |
| backdrop-filter: blur(5px); | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-size: 1.5rem; | |
| border: none; | |
| cursor: pointer; | |
| transition: transform 0.2s; | |
| } | |
| .play-btn:hover { | |
| transform: scale(1.1); | |
| background: var(--primary); | |
| } | |
| /* Loading State */ | |
| .loading-overlay { | |
| position: absolute; | |
| inset: 0; | |
| background: rgba(15, 23, 42, 0.9); | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| z-index: 10; | |
| display: none; /* Hidden by default */ | |
| } | |
| .loading-overlay.active { | |
| display: flex; | |
| } | |
| .spinner { | |
| width: 40px; | |
| height: 40px; | |
| border: 3px solid rgba(139, 92, 246, 0.3); | |
| border-radius: 50%; | |
| border-top-color: var(--primary); | |
| animation: spin 1s ease-in-out infinite; | |
| margin-bottom: 20px; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| .progress-bar { | |
| width: 80%; | |
| height: 6px; | |
| background-color: var(--bg-input); | |
| border-radius: 3px; | |
| overflow: hidden; | |
| margin-bottom: 10px; | |
| } | |
| .progress-fill { | |
| height: 100%; | |
| width: 0%; | |
| background: linear-gradient(90deg, var(--primary), var(--accent)); | |
| transition: width 0.3s linear; | |
| } | |
| .status-text { | |
| font-size: 0.9rem; | |
| color: var(--text-secondary); | |
| animation: pulse 1.5s infinite; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| } | |
| /* HISTORY SECTION */ | |
| .history-section { | |
| margin-top: 40px; | |
| max-width: 1400px; | |
| margin-left: auto; | |
| margin-right: auto; | |
| } | |
| .section-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .history-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | |
| gap: 20px; | |
| } | |
| .history-item { | |
| background-color: var(--bg-card); | |
| border-radius: var(--radius-md); | |
| overflow: hidden; | |
| border: 1px solid var(--border); | |
| transition: transform 0.2s; | |
| cursor: pointer; | |
| } | |
| .history-item:hover { | |
| transform: translateY(-5px); | |
| border-color: var(--primary); | |
| } | |
| .history-thumb { | |
| width: 100%; | |
| height: 140px; | |
| background-color: #000; | |
| background-size: cover; | |
| background-position: center; | |
| position: relative; | |
| } | |
| .history-info { | |
| padding: 12px; | |
| } | |
| .history-prompt { | |
| font-size: 0.85rem; | |
| color: var(--text-main); | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| margin-bottom: 4px; | |
| } | |
| .history-meta { | |
| font-size: 0.75rem; | |
| color: var(--text-secondary); | |
| display: flex; | |
| justify-content: space-between; | |
| } | |
| /* ========================================= | |
| RESPONSIVE DESIGN | |
| ========================================= */ | |
| @media (max-width: 900px) { | |
| .generator-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| .preview-card { | |
| min-height: 300px; | |
| order: -1; /* Put preview on top on mobile */ | |
| } | |
| } | |
| @media (max-width: 768px) { | |
| .sidebar { | |
| position: fixed; | |
| left: -100%; | |
| top: 0; | |
| bottom: 0; | |
| z-index: 100; | |
| width: 80%; | |
| box-shadow: 10px 0 20px rgba(0,0,0,0.5); | |
| } | |
| .sidebar.active { | |
| left: 0; | |
| } | |
| .menu-toggle { | |
| display: block; | |
| font-size: 1.2rem; | |
| background: none; | |
| border: none; | |
| color: var(--text-main); | |
| cursor: pointer; | |
| margin-right: 15px; | |
| } | |
| .content-scroll { | |
| padding: 15px; | |
| } | |
| } | |
| @media (min-width: 769px) { | |
| .menu-toggle { | |
| display: none; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Lien crédit obligatoire --> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-credit"> | |
| Built with anycoder <i class="fas fa-external-link-alt"></i> | |
| </a> | |
| <div class="app-container"> | |
| <!-- SIDEBAR --> | |
| <aside class="sidebar" id="sidebar"> | |
| <div class="logo"> | |
| <i class="fas fa-video"></i> | |
| <span>VideoGen AI</span> | |
| </div> | |
| <ul class="nav-menu"> | |
| <li class="nav-item"> | |
| <a href="#" class="nav-link active"> | |
| <i class="fas fa-wand-magic-sparkles"></i> | |
| <span>Créer</span> | |
| </a> | |
| </li> | |
| <li class="nav-item"> | |
| <a href="#" class="nav-link"> | |
| <i class="fas fa-clock-rotate-left"></i> | |
| <span>Historique</span> | |
| </a> | |
| </li> | |
| <li class="nav-item"> | |
| <a href="#" class="nav-link"> | |
| <i class="fas fa-bookmark"></i> | |
| <span>Favoris</span> | |
| </a> | |
| </li> | |
| <li class="nav-item"> | |
| <a href="#" class="nav-link"> | |
| <i class="fas fa-gear"></i> | |
| <span>Paramètres</span> | |
| </a> | |
| </li> | |
| </ul> | |
| <div class="user-profile"> | |
| <div class="avatar-small"></div> | |
| <div> | |
| <div style="font-size: 0.9rem; font-weight: 600;">Mon Compte</div> | |
| <div style="font-size: 0.75rem; color: var(--text-secondary);">Plan Pro</div> | |
| </div> | |
| </div> | |
| </aside> | |
| <!-- MAIN CONTENT --> | |
| <main class="main-content"> | |
| <!-- Top Bar --> | |
| <header class="top-bar"> | |
| <div style="display: flex; align-items: center;"> | |
| <button class="menu-toggle" id="menuToggle"><i class="fas fa-bars"></i></button> | |
| <h1 class="page-title">Nouvelle Vidéo</h1> | |
| </div> | |
| <div class="credits"> | |
| <i class="fas fa-coins"></i> 120 Crédits restants | |
| </div> | |
| </header> | |
| <!-- Scrollable Content --> | |
| <div class="content-scroll"> | |
| <div class="generator-grid"> | |
| <!-- INPUT COLUMN --> | |
| <div class="input-card"> | |
| <div class="form-group"> | |
| <label class="form-label">Votre prompt</label> | |
| <textarea class="prompt-input" id="promptInput" placeholder="Décrivez la vidéo que vous souhaitez générer... (ex: Un astronaute marchant sur Mars au coucher du soleil, style cinématographique 4K)"></textarea> | |
| </div> | |
| <div class="controls-row"> | |
| <div class="control-group"> | |
| <label class="form-label">Style</label> | |
| <select id="styleSelect"> | |
| <option value="cinematic">Cinématique</option> | |
| <option value="anime">Anime</option> | |
| <option value="3d">Rendu 3D</option> | |
| <option value="cyberpunk">Cyberpunk</option> | |
| <option value="realistic">Réaliste</option> | |
| </select> | |
| </div> | |
| <div class="control-group"> | |
| <label class="form-label">Durée</label> | |
| <select id="durationSelect"> | |
| <option value="5">5 secondes</option> | |
| <option value="10">10 secondes</option> | |
| <option value="15">15 secondes</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Format</label> | |
| <div class="ratio-options"> | |
| <button class="ratio-btn active" data-ratio="16:9">16:9</button> | |
| <button class="ratio-btn" data-ratio="9:16">9:16</button> | |
| <button class="ratio-btn" data-ratio="1:1">1:1</button> | |
| </div> | |
| </div> | |
| <button class="generate-btn" id="generateBtn"> | |
| <i class="fas fa-sparkles"></i> Générer la vidéo | |
| </button> | |
| </div> | |
| <!-- PREVIEW COLUMN --> | |
| <div class="preview-card"> | |
| <div class="loading-overlay" id="loadingOverlay"> | |
| <div class="spinner"></div> | |
| <div class="progress-bar"> | |
| <div class="progress-fill" id="progressFill"></div> | |
| </div> | |
| <div class="status-text" id="statusText">Initialisation...</div> | |
| </div> | |
| <div class="video-placeholder" id="videoPlaceholder"> | |
| <div style="text-align: center; color: var(--text-secondary);"> | |
| <i class="fas fa-film" style="font-size: 3rem; margin-bottom: 15px; opacity: 0.5;"></i> | |
| <p>Aperçu de la vidéo</p> | |
| </div> | |
| </div> | |
| <div id="videoControls" style="width: 100%; margin-top: 20px; display: none; justify-content: space-between; align-items: center;"> | |
| <div style="font-size: 0.9rem; color: var(--text-secondary);"> | |
| <i class="fas fa-check-circle" style="color: var(--success);"></i> Généré avec succès | |
| </div> | |
| <button style="background: var(--bg-input); border: none; color: white; padding: 8px 16px; border-radius: 6px; cursor: pointer;"> | |
| <i class="fas fa-download"></i> Télécharger | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- HISTORY GRID --> | |
| <div class="history-section"> | |
| <div class="section-header"> | |
| <h2>Générations récentes</h2> | |
| <a href="#" style="color: var(--primary); text-decoration: none; font-size: 0.9rem;">Voir tout</a> | |
| </div> | |
| <div class="history-grid" id="historyGrid"> | |
| <!-- Items injectés via JS --> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| // ========================================= | |
| // DOM ELEMENTS | |
| // ========================================= | |
| const promptInput = document.getElementById('promptInput'); | |
| const generateBtn = document.getElementById('generateBtn'); | |
| const loadingOverlay = document.getElementById('loadingOverlay'); | |
| const progressFill = document.getElementById('progressFill'); | |
| const statusText = document.getElementById('statusText'); | |
| const videoPlaceholder = document.getElementById('videoPlaceholder'); | |
| const videoControls = document.getElementById('videoControls'); | |
| const historyGrid = document.getElementById('historyGrid'); | |
| const ratioBtns = document.querySelectorAll('.ratio-btn'); | |
| const menuToggle = document.getElementById('menuToggle'); | |
| const sidebar = document.getElementById('sidebar'); | |
| // ========================================= | |
| // STATE & DATA | |
| // ========================================= | |
| let isGenerating = false; | |
| const historyData = [ | |
| { | |
| id: 1, | |
| prompt: "Ville futuriste avec voitures volantes, nuit", | |
| style: "Cyberpunk", | |
| duration: "5s", | |
| thumb: "https://picsum.photos/seed/cyber1/400/250" | |
| }, | |
| { | |
| id: 2, | |
| prompt: "Chat buvant du café dans un café parisien", | |
| style: "Réaliste", | |
| duration: "10s", | |
| thumb: "https://picsum.photos/seed/cat2/400/250" | |
| }, | |
| { | |
| id: 3, | |
| prompt: "Dragon cracheur de feu sur une montagne", | |
| style: "Cinématique", | |
| duration: "5s", | |
| thumb: "https://picsum.photos/seed/dragon3/400/250" | |
| } | |
| ]; | |
| // ========================================= | |
| // FUNCTIONS | |
| // ========================================= | |
| // 1. Gestion du menu mobile | |
| menuToggle.addEventListener('click', () => { | |
| sidebar.classList.toggle('active'); | |
| }); | |
| // Clic hors sidebar pour fermer | |
| document.addEventListener('click', (e) => { | |
| if (window.innerWidth <= 768) { | |
| if (!sidebar.contains(e.target) && !menuToggle.contains(e.target)) { | |
| sidebar.classList.remove('active'); | |
| } | |
| } | |
| }); | |
| // 2. Gestion des boutons de ratio | |
| ratioBtns.forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| ratioBtns.forEach(b => b.classList.remove('active')); | |
| btn.classList.add('active'); | |
| // Changer l'aspect ratio du placeholder visuellement | |
| const ratio = btn.dataset.ratio; | |
| if(ratio === '16:9') videoPlaceholder.style.aspectRatio = '16/9'; | |
| if(ratio === '9:16') videoPlaceholder.style.aspectRatio = '9/16'; | |
| if(ratio === '1:1') videoPlaceholder.style.aspectRatio = '1/1'; | |
| }); | |
| }); | |
| // 3. Rendu de l'historique | |
| function renderHistory() { | |
| historyGrid.innerHTML = ''; | |
| historyData.forEach(item => { | |
| const div = document.createElement('div'); | |
| div.className = 'history-item'; | |
| div.innerHTML = ` | |
| <div class="history-thumb" style="background-image: url('${item.thumb}');"> | |
| <div style="position:absolute; bottom:8px; right:8px; background:rgba(0,0,0,0.7); color:white; font-size:0.7rem; padding:2px 6px; border-radius:4px;">${item.duration}</div> | |
| </div> | |
| <div class="history-info"> | |
| <div class="history-prompt">${item.prompt}</div> | |
| <div class="history-meta"> | |
| <span>${item.style}</span> | |
| <span>Il y a 2h</span> | |
| </div> | |
| </div> | |
| `; | |
| div.onclick = () => loadVideoToPreview(item); | |
| historyGrid.appendChild(div); | |
| }); | |
| } | |
| // 4. Charger une vidéo depuis l'historique | |
| function loadVideoToPreview(item) { | |
| videoPlaceholder.innerHTML = ` | |
| <div class="video-overlay"> | |
| <h3 style="color:white; margin-bottom:10px;">${item.prompt}</h3> | |
| <button class="play-btn"><i class="fas fa-play"></i></button> | |
| </div> | |
| `; | |
| videoPlaceholder.style.backgroundImage = `url('${item.thumb}')`; | |
| videoPlaceholder.classList.add('video-active'); | |
| videoControls.style.display = 'flex'; | |
| // Reset placeholder text logic | |
| videoPlaceholder.querySelector('div[style*="text-align"]').style.display = 'none'; | |
| } | |
| // 5. Simulation de la génération | |
| generateBtn.addEventListener('click', () => { | |
| const prompt = promptInput.value.trim(); | |
| if (!prompt) { | |
| promptInput.focus(); | |
| promptInput.style.borderColor = 'var(--accent)'; | |
| setTimeout(() => promptInput.style.borderColor = 'var(--border)', 2000); | |
| return; | |
| } | |
| if (isGenerating) return; | |
| isGenerating = true; | |
| // UI Updates | |
| generateBtn.disabled = true; | |
| generateBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Génération...'; | |
| loadingOverlay.classList.add('active'); | |
| videoControls.style.display = 'none'; | |
| videoPlaceholder.classList.remove('video-active'); | |
| videoPlaceholder.style.backgroundImage = 'none'; | |
| // Reset Placeholder to default but hide text while loading | |
| videoPlaceholder.innerHTML = ` | |
| <div style="text-align: center; color: var(--text-secondary); opacity: 0;"> | |
| <i class="fas fa-film" style="font-size: 3rem; margin-bottom: 15px;"></i> | |
| <p>Aperçu de la vidéo</p> | |
| </div> | |
| `; | |
| // Simulation des étapes | |
| const steps = [ | |
| { pct: 0, text: "Analyse du prompt..." }, | |
| { pct: 20, text: "Génération des keyframes..." }, | |
| { pct: 45, text: "Interpolation des mouvements..." }, | |
| { pct: 70, text: "Rendu des textures..." }, | |
| { pct: 90, text: "Encodage final..." }, | |
| { pct: 100, text: "Terminé !" } | |
| ]; | |
| let stepIndex = 0; | |
| const interval = setInterval(() => { | |
| if (stepIndex >= steps.length) { | |
| clearInterval(interval); | |
| finishGeneration(prompt); | |
| return; | |
| } | |
| const step = steps[stepIndex]; | |
| progressFill.style.width = step.pct + '%'; | |
| statusText.textContent = step.text; | |
| stepIndex++; | |
| }, 600); // 600ms par étape (environ 3.6s total) | |
| }); | |
| function finishGeneration(prompt) { | |
| isGenerating = false; | |
| // Masquer le loader | |
| loadingOverlay.classList.remove('active'); | |
| // Réafficher le bouton | |
| generateBtn.disabled = false; | |
| generateBtn.innerHTML = '<i class="fas fa-sparkles"></i> Générer la vidéo'; | |
| // Afficher le résultat (Simulation) | |
| const randomSeed = Math.floor(Math.random() * 1000); | |
| const thumbUrl = `https://picsum.photos/seed/${randomSeed}/800/450`; | |
| videoPlaceholder.style.backgroundImage = `url('${thumbUrl}')`; | |
| videoPlaceholder.classList.add('video-active'); | |
| videoPlaceholder.innerHTML = ` | |
| <div class="video-overlay"> | |
| <h3 style="color:white; margin-bottom:10px; font-size:0.9rem;">Résultat généré</h3> | |
| <button class="play-btn"><i class="fas fa-play"></i></button> | |
| </div> | |
| `; | |
| videoControls.style.display = 'flex'; | |
| // Ajouter à l'historique | |
| const newItem = { | |
| id: Date.now(), | |
| prompt: prompt, | |
| style: document.getElementById('styleSelect').value, | |
| duration: document.getElementById('durationSelect').value + 's', | |
| thumb: thumbUrl | |
| }; | |
| historyData.unshift(newItem); // Ajouter au début | |
| renderHistory(); | |
| } | |
| // Init | |
| renderHistory(); | |
| </script> | |
| </body> | |
| </html> |