| <!DOCTYPE html> |
| <html lang="en"> |
|
|
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Caption Burner V3</title> |
| <style> |
| body { |
| background: #111; |
| color: white; |
| get_font-family: sans-serif; |
| display: flex; |
| justify-content: center; |
| padding-top: 50px; |
| } |
| |
| .box { |
| width: 500px; |
| padding: 20px; |
| border: 1px solid #333; |
| border-radius: 8px; |
| background: #222; |
| } |
| |
| input, |
| select, |
| button { |
| width: 100%; |
| margin-bottom: 10px; |
| padding: 10px; |
| box-sizing: border-box; |
| } |
| |
| button { |
| background: limegreen; |
| cursor: pointer; |
| border: none; |
| font-weight: bold; |
| } |
| |
| pre { |
| background: #000; |
| padding: 10px; |
| font-size: 0.8rem; |
| overflow: auto; |
| } |
| </style> |
| </head> |
|
|
| <body> |
|
|
| <div class="box"> |
| <h2>🔥 Caption Layer Generator</h2> |
|
|
| <label>Space URL</label> |
| <input id="serverUrl" value="https://adxabhi-cap.hf.space" placeholder="Space URL"> |
|
|
| <label>Style</label> |
| <select id="styleSelector"> |
| <option value="hormozi">Hormozi (Yellow)</option> |
| <option value="netflix">Netflix (Red)</option> |
| <option value="neon">Neon (Glowing)</option> |
| </select> |
|
|
| <label>Transcript JSON</label> |
| <textarea id="transcriptBox" rows="10" style="width:100%; background:#111; color:#0f0; font-family:monospace;">[ |
| { "text": "THIS IS", "start": 0.0, "end": 1.0 }, |
| { "text": "A TRANSPARENT", "start": 1.0, "end": 2.5 }, |
| { "text": "OVERLAY", "start": 2.5, "end": 4.0 } |
| ]</textarea> |
|
|
| <button onclick="testConnection()" style="background:#555">Test Connection</button> |
| <button onclick="start()">Generate Layer</button> |
|
|
| <div id="status">Waiting...</div> |
| <div id="resultArea" style="margin-top:20px;"></div> |
| </div> |
|
|
| <script> |
| async function testConnection() { |
| const server = document.getElementById('serverUrl').value.trim().replace(/\/$/, ""); |
| const status = document.getElementById('status'); |
| status.innerText = `Testing GET ${server}/ ...`; |
| try { |
| const res = await fetch(`${server}/`); |
| const txt = await res.text(); |
| status.innerText = `Server OK: ${res.status} (${txt})`; |
| } catch (e) { |
| status.innerText = `Connection Failed: ${e.message}`; |
| } |
| } |
| |
| async function start() { |
| const server = document.getElementById('serverUrl').value.trim().replace(/\/$/, ""); |
| const style = document.getElementById('styleSelector').value; |
| const transcriptText = document.getElementById('transcriptBox').value; |
| const status = document.getElementById('status'); |
| const resArea = document.getElementById('resultArea'); |
| |
| let transcript; |
| try { |
| transcript = JSON.parse(transcriptText); |
| } catch (e) { |
| alert("Invalid JSON!"); |
| return; |
| } |
| |
| status.innerText = `POSTing to ${server}/jobs ...`; |
| resArea.innerHTML = ""; |
| |
| try { |
| const res = await fetch(`${server}/jobs`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ |
| video_url: "dummy", |
| transcript: transcript, |
| style: style |
| }) |
| }); |
| |
| if (!res.ok) { |
| const txt = await res.text(); |
| status.innerText = `Error ${res.status}: ${txt}`; |
| console.error("Fetch Error:", res.status, txt); |
| return; |
| } |
| |
| const data = await res.json(); |
| const jobId = data.job_id; |
| console.log("Job ID:", jobId); |
| |
| const interval = setInterval(async () => { |
| const r = await fetch(`${server}/jobs/${jobId}`); |
| const job = await r.json(); |
| |
| status.innerText = `Status: ${job.status} (${job.progress})`; |
| |
| if (job.status === 'completed') { |
| clearInterval(interval); |
| const url = job.result[0]; |
| const assUrl = job.result[1]; |
| resArea.innerHTML = ` |
| <p style="color:#0f0">Success!</p> |
| <a href="${url}" target="_blank" style="color:yellow; word-break:break-all;">VIDEO: ${url}</a> |
| <br> |
| <a href="${assUrl}" target="_blank" style="color:cyan; word-break:break-all;">DEBUG ASS: ${assUrl}</a> |
| <br><br> |
| <video src="${url}" controls style="width:100%; background: checkerboard;"></video> |
| `; |
| } |
| if (job.status === 'failed') { |
| clearInterval(interval); |
| status.innerText = "Error: " + job.error; |
| } |
| }, 3000); |
| } catch (e) { |
| status.innerText = `Network Error: ${e.message}`; |
| console.error(e); |
| } |
| } |
| </script> |
| </body> |
|
|
| </html> |