Spaces:
Sleeping
Sleeping
| <html lang="en" data-bs-theme="dark"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <title>Bytez Spark AI</title> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <!-- PWA and Theme Settings --> | |
| <meta name="theme-color" content="#1a1a1a"> | |
| <link rel="manifest" href="/manifest.json"> | |
| <!-- Icons --> | |
| <link rel="icon" href="/static/favicon.ico" type="image/x-icon"> | |
| <link rel="apple-touch-icon" href="/static/icon-512x512.png"> | |
| <!-- Stylesheets --> | |
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --bs-body-bg: #111; | |
| --bs-body-color: #eee; | |
| } | |
| .card { | |
| background: #1a1a1a; | |
| border: 1px solid #333; | |
| border-radius: 1rem; | |
| } | |
| .btn-primary { | |
| background-color: #0d6efd; | |
| border-color: #0d6efd; | |
| } | |
| .form-control, .form-select { | |
| background-color: #222; | |
| border-color: #444; | |
| color: #eee; | |
| } | |
| .form-control:focus, .form-select:focus { | |
| background-color: #222; | |
| border-color: #0d6efd; | |
| box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25); | |
| color: #eee; | |
| } | |
| video { | |
| border-radius: 0.75rem; | |
| background-color: #000; | |
| } | |
| .container { | |
| max-width: 720px; | |
| } | |
| .page { | |
| display: none; | |
| } | |
| .page.active { | |
| display: block; | |
| } | |
| .form-label h5 { | |
| margin-bottom: 0.5rem; | |
| } | |
| #liveLog { | |
| background-color: #000; | |
| border: 1px solid #333; | |
| border-radius: 0.5rem; | |
| height: 150px; | |
| overflow-y: auto; | |
| font-family: monospace; | |
| font-size: 0.9em; | |
| padding: 10px; | |
| white-space: pre-wrap; | |
| margin-top: 1rem; | |
| text-align: left; | |
| } | |
| #liveLog p { | |
| margin: 0; | |
| padding: 2px 0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- आपके Body का हिस्सा यहाँ से शुरू होता है, इसमें कोई बदलाव नहीं है --> | |
| <div class="container py-4"> | |
| <div id="inputPage" class="page active"> | |
| <h2 class="text-center mb-4">🎬 AI Video Generator</h2> | |
| <div class="card p-4"> | |
| <div class="mb-3"> | |
| <label for="prompt" class="form-label"><h5>1. Describe your video (or use an image)</h5></label> | |
| <textarea id="prompt" class="form-control" rows="3" placeholder="e.g., A robot walking through a neon-lit city in the rain"></textarea> | |
| </div> | |
| <div class="mb-3"> | |
| <label for="imageUpload" class="form-label"><h5>2. Upload Image (Optional)</h5></label> | |
| <input type="file" id="imageUpload" class="form-control" accept="image/png, image/jpeg"> | |
| </div> | |
| <div class="row g-3"> | |
| <div class="col-md-6 mb-3"> | |
| <label for="num_clips" class="form-label"><h5>3. Number of clips</h5></label> | |
| <input id="num_clips" type="number" class="form-control" min="1" max="20" value="3"> | |
| </div> | |
| <div class="col-md-6 mb-3"> | |
| <label for="style" class="form-label"><h5>4. Style</h5></label> | |
| <select id="style" class="form-select"> | |
| <option value="none" selected>Default</option> | |
| <option value="cinematic">Cinematic</option> | |
| <option value="cartoon">Cartoon</option> | |
| <option value="realistic">Realistic</option> | |
| <option value="minimalist">Minimalist</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="mb-3"> | |
| <label for="bytezModelCustom" class="form-label"><h5>5. Custom AI Model (Optional)</h5></label> | |
| <input type="text" id="bytezModelCustom" class="form-control" placeholder="Default: ali-vilab/text-to-video-ms-1.7b"> | |
| </div> | |
| <div class="d-grid mt-2"> | |
| <button id="startBtn" class="btn btn-primary btn-lg">🚀 Generate Video</button> | |
| </div> | |
| </div> | |
| <div id="inputError" class="text-danger mt-3 text-center d-none"></div> | |
| </div> | |
| <div id="progressPage" class="page"> | |
| <div class="card p-4 text-center"> | |
| <div id="progressBox"> | |
| <h3 class="mb-3">Generating your video...</h3> | |
| <div class="d-flex justify-content-center align-items-center mb-3"> | |
| <div class="spinner-border me-3" role="status"></div> | |
| <div class="mono" id="statusText" style="font-size: 1.1rem;">Initializing...</div> | |
| </div> | |
| <div class="progress" role="progressbar" style="height: 10px"> | |
| <div id="bar" class="progress-bar progress-bar-striped progress-bar-animated" style="width: 2%"></div> | |
| </div> | |
| <div id="liveLogContainer"> | |
| <h6 class="text-secondary mt-3">Mission Control Log:</h6> | |
| <div id="liveLog"></div> | |
| </div> | |
| </div> | |
| <div id="errorBox" class="d-none"> | |
| <h3 class="text-danger">An Error Occurred</h3> | |
| <p id="errorMessage" class="mono bg-dark p-3 rounded"></p> | |
| <button class="btn btn-secondary" onclick="goHomeAndReset()">Try Again</button> | |
| </div> | |
| <div id="resultBox" class="d-none"> | |
| <h3 class="mb-3">✅ Your video is ready!</h3> | |
| <video id="player" width="100%" controls playsinline></video> | |
| <div class="d-grid gap-2 mt-3"> | |
| <a id="dl" class="btn btn-success btn-lg" download>⬇️ Download Video</a> | |
| <button class="btn btn-outline-secondary" onclick="goHomeAndReset()">Create Another Video</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const bytezModelCustomEl=document.getElementById("bytezModelCustom"),startBtn=document.getElementById("startBtn"),promptEl=document.getElementById("prompt"),clipsEl=document.getElementById("num_clips"),styleEl=document.getElementById("style"),imageUploadEl=document.getElementById("imageUpload"),liveLogEl=document.getElementById("liveLog"),inputPage=document.getElementById("inputPage"),progressPage=document.getElementById("progressPage"),progressBox=document.getElementById("progressBox"),statusText=document.getElementById("statusText"),bar=document.getElementById("bar"),errorBox=document.getElementById("errorBox"),errorMessage=document.getElementById("errorMessage"),inputError=document.getElementById("inputError"),resultBox=document.getElementById("resultBox"),player=document.getElementById("player"),dl=document.getElementById("dl");let pollTimer=null;function showPage(e){document.querySelectorAll(".page").forEach(e=>e.classList.remove("active")),document.getElementById(e).classList.add("active")}function resetUI(){inputError.classList.add("d-none"),errorBox.classList.add("d-none"),resultBox.classList.add("d-none"),progressBox.style.display="block",bar.style.width="2%",startBtn.disabled=!1,imageUploadEl.value=null,promptEl.value="",liveLogEl.innerHTML="",bytezModelCustomEl.value=""}function goHomeAndReset(){resetUI(),showPage("inputPage")}async function startJob(){inputError.classList.add("d-none"),liveLogEl.innerHTML="";const e=promptEl.value.trim(),t=imageUploadEl.files[0];if(!e&&!t)return inputError.textContent="Please provide a text prompt or upload an image.",void inputError.classList.remove("d-none");startBtn.disabled=!0,showPage("progressPage");try{const a=new FormData;a.append("prompt",e),a.append("num_clips",parseInt(clipsEl.value,10)),a.append("style",styleEl.value),t&&a.append("image",t);const o=bytezModelCustomEl.value.trim();a.append("bytez_model",o);const n=await fetch("/start",{method:"POST",body:a}),s=await n.json();if(!n.ok)throw new Error(s.error||"Failed to start job.");pollTimer=setInterval(pollProgress,1500)}catch(l){errorMessage.textContent=l.message,progressBox.style.display="none",errorBox.classList.remove("d-none"),startBtn.disabled=!1}}async function pollProgress(){try{const e=await fetch("/progress"),t=await e.json(),a=Math.max(1,t.total),o=Math.min(100,Math.floor(t.step/a*100));if(bar.style.width=o+"%",statusText.textContent=t.message,t.live_log&&(liveLogEl.innerHTML=t.live_log.map(e=>`<p>${e}</p>`).join(""),liveLogEl.scrollTop=liveLogEl.scrollHeight),t.status==="done"&&t.video_relpath){clearInterval(pollTimer);const n=`/${t.video_relpath.replace(/\\\\/g,"/")}`;player.src=n,dl.href=n,dl.download=`ai_video_${Date.now()}.mp4`,progressBox.style.display="none",resultBox.classList.remove("d-none")}else if(t.status==="error"){clearInterval(pollTimer),errorMessage.textContent=t.error||"An unknown error occurred.",progressBox.style.display="none",errorBox.classList.remove("d-none")}}catch(r){clearInterval(pollTimer),errorMessage.textContent="Connection to server lost. Please try again.",progressBox.style.display="none",errorBox.classList.remove("d-none")}}startBtn.addEventListener("click",startJob);if("serviceWorker" in navigator){window.addEventListener("load",()=>{navigator.serviceWorker.register("/service-worker.js").then(reg=>console.log("Service worker registered.")).catch(err=>console.log("Service worker registration failed: ",err));});} | |
| </script> | |
| </body> | |
| </html> |