| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>AI Video Frame Captioning</title> |
| <link rel="stylesheet" href="style.css"> |
| <link rel="preconnect" href="https://fonts.googleapis.com"> |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> |
| </head> |
| <body> |
| <div class="container"> |
| <header> |
| <h1>π¬ AI Video Frame Captioning</h1> |
| <p class="subtitle">Extract frames from videos and generate detailed AI captions</p> |
| </header> |
|
|
| <main> |
| <div class="upload-section"> |
| <div class="upload-area" id="uploadArea"> |
| <svg class="upload-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> |
| <polyline points="7 10 12 15 17 10"></polyline> |
| <line x1="12" y1="15" x2="12" y2="3"></line> |
| </svg> |
| <h3>Drop video file here or click to browse</h3> |
| <p>Supports MP4, WebM, OGG (Max 100MB)</p> |
| <input type="file" id="videoInput" accept="video/*" hidden> |
| </div> |
| </div> |
|
|
| <div id="videoSection" class="video-section hidden"> |
| <div class="video-container"> |
| <video id="videoPlayer" controls></video> |
| <canvas id="frameCanvas" class="hidden"></canvas> |
| </div> |
| |
| <div class="controls"> |
| <div class="control-group"> |
| <label for="frameInterval">Capture frame every:</label> |
| <select id="frameInterval"> |
| <option value="1">1 second</option> |
| <option value="2">2 seconds</option> |
| <option value="5" selected>5 seconds</option> |
| <option value="10">10 seconds</option> |
| <option value="30">30 seconds</option> |
| </select> |
| </div> |
| |
| <div class="control-group"> |
| <label for="deviceSelect">Processing device:</label> |
| <select id="deviceSelect"> |
| <option value="wasm">CPU (WASM)</option> |
| <option value="webgpu">GPU (WebGPU)</option> |
| </select> |
| </div> |
|
|
| <button id="processBtn" class="process-btn"> |
| <span class="btn-text">Generate Captions</span> |
| <div class="spinner hidden"></div> |
| </button> |
| </div> |
| </div> |
|
|
| <div id="progressSection" class="progress-section hidden"> |
| <div class="progress-bar"> |
| <div id="progressFill" class="progress-fill"></div> |
| </div> |
| <p id="progressText">Initializing model...</p> |
| </div> |
|
|
| <div id="resultsSection" class="results-section hidden"> |
| <h2>π Generated Captions</h2> |
| <div id="framesList" class="frames-list"></div> |
| |
| <div class="export-buttons"> |
| <button id="exportJson" class="export-btn">Export as JSON</button> |
| <button id="exportSrt" class="export-btn">Export as SRT</button> |
| <button id="exportTxt" class="export-btn">Export as TXT</button> |
| </div> |
| </div> |
| </main> |
|
|
| <footer> |
| <p>Powered by Transformers.js and FastVLM-0.5B</p> |
| </footer> |
| </div> |
|
|
| <script type="module" src="index.js"></script> |
| </body> |
| </html> |