Initial commit of video upscaler
This commit is contained in:
@@ -0,0 +1,576 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Antigravity AI Video Upscaler</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<!-- FontAwesome for modern icons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-container">
|
||||
<!-- Dashboard Header -->
|
||||
<header>
|
||||
<div class="logo-container">
|
||||
<div class="logo-icon">▲</div>
|
||||
<div class="logo-text">
|
||||
<h1>ANTIGRAVITY // UPSCALE</h1>
|
||||
<p>Open Source AI Video Enhancer</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<div class="theme-selector">
|
||||
<label for="theme-select"><i class="fa-solid fa-palette"></i> Theme</label>
|
||||
<select id="theme-select">
|
||||
<option value="cyberpunk" selected>Cyberpunk Neon</option>
|
||||
<option value="oled">OLED Obsidian</option>
|
||||
<option value="slate">Slate Gray</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="gpu-badge">
|
||||
<div class="gpu-dot"></div>
|
||||
<span id="gpu-info">GPU Active: Quadro P2000 (Vulkan)</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<!-- Step 1: Upload Video -->
|
||||
<div id="step-upload" class="step-container active">
|
||||
<div class="glass-card">
|
||||
<div id="drop-zone" class="upload-area">
|
||||
<input type="file" id="file-input" accept="video/*" style="display: none;">
|
||||
<span class="upload-icon"><i class="fa-solid fa-cloud-arrow-up"></i></span>
|
||||
<h3>Drag & Drop Video File</h3>
|
||||
<p>Supports MP4, MKV, AVI, MOV, WEBM (Max 500MB recommended for local upscaling)</p>
|
||||
<button type="button" class="btn" onclick="document.getElementById('file-input').click()">
|
||||
<i class="fa-solid fa-folder-open"></i> Browse Files
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 2: Configuration & Preview -->
|
||||
<div id="step-config" class="step-container">
|
||||
<div class="config-layout">
|
||||
<!-- Config Sidebar -->
|
||||
<div class="config-sidebar">
|
||||
<!-- Video Metadata Display -->
|
||||
<div class="glass-card meta-panel">
|
||||
<h4>Video Source Info</h4>
|
||||
<div class="meta-grid">
|
||||
<div class="meta-item">
|
||||
<span>File Name</span>
|
||||
<span id="meta-name" class="text-truncate">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Size</span>
|
||||
<span id="meta-size">-</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detailed Streams Accordion -->
|
||||
<div class="streams-accordions">
|
||||
<div class="accordion-item">
|
||||
<div class="accordion-header" onclick="this.parentElement.classList.toggle('open')">
|
||||
<span><i class="fa-solid fa-video"></i> Video Stream #0</span>
|
||||
<i class="fa-solid fa-chevron-down toggle-icon"></i>
|
||||
</div>
|
||||
<div class="accordion-content">
|
||||
<div class="secondary-grid">
|
||||
<div class="meta-item">
|
||||
<span>Codec</span>
|
||||
<span id="meta-res-codec">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Resolution</span>
|
||||
<span id="meta-res">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Frame Rate</span>
|
||||
<span id="meta-fps">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Duration</span>
|
||||
<span id="meta-duration">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Total Frames</span>
|
||||
<span id="meta-total-frames">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Aspect Ratio</span>
|
||||
<span id="meta-aspect-ratio">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<div class="accordion-header" onclick="this.parentElement.classList.toggle('open')">
|
||||
<span><i class="fa-solid fa-volume-high"></i> Audio Stream #1</span>
|
||||
<i class="fa-solid fa-chevron-down toggle-icon"></i>
|
||||
</div>
|
||||
<div class="accordion-content">
|
||||
<div class="secondary-grid">
|
||||
<div class="meta-item">
|
||||
<span>Codec</span>
|
||||
<span id="meta-audio-codec">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Channels</span>
|
||||
<span id="meta-audio-channels">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Sample Rate</span>
|
||||
<span id="meta-audio-samplerate">-</span>
|
||||
</div>
|
||||
<div class="meta-item">
|
||||
<span>Bitrate</span>
|
||||
<span id="meta-audio-bitrate">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Trimming Controls Panel -->
|
||||
<div class="glass-card trimming-panel">
|
||||
<h4 style="font-family: var(--font-heading); color: var(--primary); font-size: 1.1rem; margin-bottom: 0.5rem;"><i class="fa-solid fa-scissors"></i> Video Trimming</h4>
|
||||
<p style="font-size: 0.75rem; color: var(--text-muted); margin-bottom: 0.75rem;">Specify range to upscale only a portion of the video.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="trim-start-range">Trim Start: <span id="trim-start-value" class="badge">0.00s</span></label>
|
||||
<div class="range-slider">
|
||||
<input type="range" id="trim-start-range" min="0" max="100" step="0.05" value="0">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" style="margin-top: 1rem;">
|
||||
<label for="trim-end-range">Trim End: <span id="trim-end-value" class="badge">10.00s</span></label>
|
||||
<div class="range-slider">
|
||||
<input type="range" id="trim-end-range" min="0" max="100" step="0.05" value="10">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Config Parameters Form -->
|
||||
<div class="glass-card settings-panel">
|
||||
<h4 style="font-family: var(--font-heading); color: var(--primary);">Upscaling Profile</h4>
|
||||
|
||||
<!-- Model Selection -->
|
||||
<div class="form-group">
|
||||
<label for="model-select">AI Upscaling Model</label>
|
||||
<select id="model-select">
|
||||
<option value="realesr-animevideov3">Real-ESRGAN Anime Video V3 (Fast / Anime & Video)</option>
|
||||
<option value="realesrgan-x4plus" selected>Real-ESRGAN X4 Plus (Ultra Quality / Real World)</option>
|
||||
<option value="realesrgan-x4plus-anime">Real-ESRGAN X4 Plus Anime (Ultra Quality / Illustration)</option>
|
||||
<option value="realesrnet-x4plus">Real-ESRNet X4 Plus (Alternate / Real World)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Scale Factor -->
|
||||
<div class="form-group">
|
||||
<label for="scale-range">Scale Factor <span id="scale-value" class="badge">4x</span></label>
|
||||
<div class="range-slider">
|
||||
<input type="range" id="scale-range" min="2" max="4" step="1" value="4">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Advanced Settings Toggle Header -->
|
||||
<div class="advanced-settings-header" onclick="this.classList.toggle('open'); document.getElementById('advanced-settings-content').classList.toggle('open')">
|
||||
<span><i class="fa-solid fa-sliders"></i> Advanced Options</span>
|
||||
<i class="fa-solid fa-chevron-down"></i>
|
||||
</div>
|
||||
|
||||
<!-- Collapsible Content -->
|
||||
<div id="advanced-settings-content" class="advanced-settings-content">
|
||||
<!-- GPU Device Selection -->
|
||||
<div class="form-group">
|
||||
<label for="gpu-select">Vulkan GPU Selector</label>
|
||||
<select id="gpu-select">
|
||||
<option value="auto" selected>Auto Detect Device</option>
|
||||
<option value="0">GPU Device #0</option>
|
||||
<option value="1">GPU Device #1</option>
|
||||
<option value="2">GPU Device #2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- GPU Tile Size -->
|
||||
<div class="form-group">
|
||||
<label for="tile-range">GPU Tile Size <span id="tile-value" class="badge">256</span></label>
|
||||
<div class="range-slider">
|
||||
<input type="range" id="tile-range" min="64" max="512" step="64" value="256">
|
||||
</div>
|
||||
<p style="font-size: 0.72rem; color: var(--text-muted); margin-top: 2px;">
|
||||
Halves automatically in case of Vulkan VRAM allocation faults.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- CRF Quality Slider -->
|
||||
<div class="form-group">
|
||||
<label for="crf-range">Constant Rate Factor (CRF) <span id="crf-value" class="badge">18</span></label>
|
||||
<div class="range-slider">
|
||||
<input type="range" id="crf-range" min="0" max="51" step="1" value="18">
|
||||
</div>
|
||||
<p style="font-size: 0.72rem; color: var(--text-muted); margin-top: 2px;">
|
||||
0 (lossless) to 51 (worst). Default 18 (visually pristine).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Speed/Quality Preset -->
|
||||
<div class="form-group">
|
||||
<label for="preset-select">FFmpeg H.264 Encoder Preset</label>
|
||||
<select id="preset-select">
|
||||
<option value="ultrafast">Ultrafast (High Speed / Large Size)</option>
|
||||
<option value="superfast">Superfast</option>
|
||||
<option value="veryfast">Veryfast</option>
|
||||
<option value="faster">Faster</option>
|
||||
<option value="fast">Fast</option>
|
||||
<option value="medium" selected>Medium (Balanced)</option>
|
||||
<option value="slow">Slow (Max H.264 Quality Compression)</option>
|
||||
<option value="slower">Slower</option>
|
||||
<option value="veryslow">Veryslow (Maximum Compression)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Output Video container -->
|
||||
<div class="form-group">
|
||||
<label for="transcode-select">Output Container Format</label>
|
||||
<select id="transcode-select">
|
||||
<option value="mp4" selected>MP4 (MPEG-4 H.264 Wrapper)</option>
|
||||
<option value="mkv">MKV (Matroska Video Container)</option>
|
||||
<option value="mov">MOV (QuickTime Video Wrapper)</option>
|
||||
<option value="avi">AVI (Legacy Audio Video Interleave)</option>
|
||||
<option value="webm">WebM (VP9 / Web Native HTML5)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Pre-filters selection checkboxes -->
|
||||
<div class="filter-group">
|
||||
<span style="font-weight: 600; font-size: 0.85rem; display: block; color: var(--primary);">Pre-Filters & Enhancing</span>
|
||||
<div class="filter-checkboxes">
|
||||
<label class="checkbox-container">
|
||||
<input type="checkbox" id="filter-denoise"> Denoise (hqdn3d)
|
||||
</label>
|
||||
<label class="checkbox-container">
|
||||
<input type="checkbox" id="filter-sharpen"> Sharpen (unsharp)
|
||||
</label>
|
||||
<label class="checkbox-container">
|
||||
<input type="checkbox" id="filter-fps"> Double FPS (60FPS Interpolate)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Webhook Notify Input -->
|
||||
<div class="form-group">
|
||||
<label for="webhook-url">Webhook Notification Callback</label>
|
||||
<input type="text" id="webhook-url" placeholder="https://your-server.com/webhook" style="background: rgba(255, 255, 255, 0.04); border: 1px solid var(--border-color); color: var(--text-main); padding: 0.8rem 1rem; border-radius: 10px; font-family: var(--font-body); font-size: 0.95rem; outline: none; transition: border 0.3s; width: 100%;">
|
||||
</div>
|
||||
|
||||
<!-- Custom Model Upload Input -->
|
||||
<div class="form-group">
|
||||
<label>Upload Custom Model (.param + .bin)</label>
|
||||
<div class="model-upload-zone" onclick="document.getElementById('custom-model-input').click()">
|
||||
<input type="file" id="custom-model-input" accept=".param,.bin" multiple style="display: none;">
|
||||
<i class="fa-solid fa-cubes-stacked"></i>
|
||||
<p>Select both model files to load into realesrgan</p>
|
||||
<span id="model-upload-filename" style="font-size: 0.72rem; color: var(--primary); font-weight: bold; word-break: break-all;">No files selected</span>
|
||||
</div>
|
||||
<div class="upload-model-btn-container" style="display: none;" id="upload-model-btn-wrapper">
|
||||
<button type="button" class="btn btn-secondary btn-small" id="upload-model-btn" style="width: 100%;">
|
||||
<i class="fa-solid fa-cloud-arrow-up"></i> Upload Model Files
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Preserve Audio Toggle -->
|
||||
<div class="toggle-container">
|
||||
<div>
|
||||
<span style="font-weight: 600; font-size: 0.9rem; display: block;">Preserve Audio</span>
|
||||
<span style="font-size: 0.75rem; color: var(--text-muted);">Copy audio streams into upscaled video</span>
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="audio-toggle" checked>
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action -->
|
||||
<button type="button" id="start-upscale-btn" class="btn" style="margin-top: 1rem;">
|
||||
<i class="fa-solid fa-play"></i> Start Full Upscale
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Comparison Preview Area -->
|
||||
<div class="glass-card preview-panel">
|
||||
<div class="preview-header">
|
||||
<h3>Clarity Preview</h3>
|
||||
<button type="button" id="prev-btn" class="btn btn-secondary" onclick="window.location.reload()">
|
||||
<i class="fa-solid fa-arrow-left"></i> Change Video
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Timeline Selection -->
|
||||
<div class="timeline-picker">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; width: 100%; margin-bottom: 0.25rem;">
|
||||
<label for="timeline-slider" style="margin: 0; padding-bottom: 0;">
|
||||
Select Frame Position: <span id="timeline-time" style="color: var(--primary); font-weight: bold;">0.00s</span>
|
||||
</label>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
<button type="button" id="generate-preview-btn" class="btn btn-secondary btn-small" style="padding: 0.4rem 1rem !important;">
|
||||
<i class="fa-solid fa-wand-magic-sparkles"></i> Frame Preview
|
||||
</button>
|
||||
<button type="button" id="generate-video-preview-btn" class="btn btn-primary btn-small" style="padding: 0.4rem 1rem !important;">
|
||||
<i class="fa-solid fa-video"></i> 5s Video Preview
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="range" id="timeline-slider" min="0" max="100" step="0.1" value="10">
|
||||
</div>
|
||||
|
||||
<!-- Interactive Comparison Container -->
|
||||
<div style="position: relative;">
|
||||
<!-- Placeholder -->
|
||||
<div id="preview-placeholder-box" class="preview-placeholder">
|
||||
<i class="fa-solid fa-image-portrait"></i>
|
||||
<h4>Clarity Preview Frame</h4>
|
||||
<p>Extracts a single frame at the chosen timestamp and runs the AI model to show side-by-side comparative clarity enhancement.</p>
|
||||
<p style="font-size: 0.82rem; color: var(--text-muted); margin-top: 0.5rem;">Click "Render Preview Frame" above to generate the comparative view.</p>
|
||||
</div>
|
||||
|
||||
<!-- Interactive Slider (Hidden by default) -->
|
||||
<div id="comparison-slider-container" class="comparison-wrapper" style="display: none;">
|
||||
<img id="img-original" class="comparison-image original" src="" alt="Before Upscaling" style="--zoom: 1; --pan-x: 0px; --pan-y: 0px;">
|
||||
<div id="img-upscaled-wrapper" class="upscaled-wrapper">
|
||||
<img id="img-upscaled" class="comparison-image upscaled" src="" alt="After Upscaling" style="--zoom: 1; --pan-x: 0px; --pan-y: 0px;">
|
||||
</div>
|
||||
|
||||
<!-- Video Elements for Synced Video Preview -->
|
||||
<video id="video-preview-original" class="comparison-image original" loop muted playsinline style="display: none; --zoom: 1; --pan-x: 0px; --pan-y: 0px;"></video>
|
||||
<div id="video-preview-upscaled-wrapper" class="upscaled-wrapper" style="display: none;">
|
||||
<video id="video-preview-upscaled" class="comparison-image upscaled" loop muted playsinline style="--zoom: 1; --pan-x: 0px; --pan-y: 0px;"></video>
|
||||
</div>
|
||||
|
||||
<div id="slider-split" class="slider-bar">
|
||||
<div class="slider-handle"></div>
|
||||
</div>
|
||||
|
||||
<span class="badge-orig">Before (Low Res)</span>
|
||||
<span class="badge-up">After (AI Upscaled)</span>
|
||||
</div>
|
||||
|
||||
<!-- Zoom & Pan Controls -->
|
||||
<div id="zoom-pan-controls" class="zoom-pan-bar" style="display: none;">
|
||||
<div class="zoom-control-item">
|
||||
<label for="zoom-slider">Zoom: <span id="zoom-val">1.0x</span></label>
|
||||
<input type="range" id="zoom-slider" min="1" max="5" step="0.1" value="1">
|
||||
</div>
|
||||
<div class="zoom-control-item">
|
||||
<label for="pan-x-slider">Pan X: <span id="pan-x-val">0px</span></label>
|
||||
<input type="range" id="pan-x-slider" min="-300" max="300" step="1" value="0">
|
||||
</div>
|
||||
<div class="zoom-control-item">
|
||||
<label for="pan-y-slider">Pan Y: <span id="pan-y-val">0px</span></label>
|
||||
<input type="range" id="pan-y-slider" min="-300" max="300" step="1" value="0">
|
||||
</div>
|
||||
<button type="button" id="reset-zoom-pan-btn" class="btn btn-secondary btn-small">
|
||||
<i class="fa-solid fa-arrows-to-eye"></i> Reset
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Video Preview Playback Controls -->
|
||||
<div id="video-preview-controls" class="zoom-pan-bar" style="display: none; justify-content: center; align-items: center; gap: 1rem; margin-top: 1rem;">
|
||||
<button type="button" id="vprep-play-btn" class="btn btn-primary btn-circular">
|
||||
<i class="fa-solid fa-play"></i>
|
||||
</button>
|
||||
<div class="time-scrubber-container">
|
||||
<span id="vprep-time-current">0:00</span>
|
||||
<input type="range" id="vprep-scrubber" min="0" max="5" step="0.05" value="0">
|
||||
<span id="vprep-time-duration">0:05</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loader overlay -->
|
||||
<div id="preview-loader" class="preview-loading">
|
||||
<div class="spinner" style="margin-bottom: 1rem;"></div>
|
||||
<h4 id="preview-loader-title" style="font-family: var(--font-heading); margin-bottom: 0.5rem;">Orchestrating Vulkan GPU...</h4>
|
||||
<div id="preview-loader-progress-container" style="width: 100%; max-width: 250px; height: 6px; background: rgba(255,255,255,0.1); border-radius: 3px; overflow: hidden; margin: 0.5rem 0; display: none;">
|
||||
<div id="preview-loader-progress-bar" style="width: 0%; height: 100%; background: var(--primary); transition: width 0.3s ease;"></div>
|
||||
</div>
|
||||
<p id="preview-loader-text" style="color: var(--text-muted); font-size: 0.85rem;">Extracting and upscaling frame. Please wait...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 3: Processing Progress -->
|
||||
<div id="step-progress" class="step-container">
|
||||
<div class="glass-card progress-card">
|
||||
<div class="progress-header">
|
||||
<div>
|
||||
<h2 style="font-family: var(--font-heading); margin-bottom: 0.5rem;">Upscaling Video Pipeline</h2>
|
||||
<p style="color: var(--text-muted); font-size: 0.9rem;">Job ID: <span id="job-id-display" style="font-family: monospace; color: var(--text-main);">-</span></p>
|
||||
</div>
|
||||
<span id="status-badge" class="status-badge queued">Queued</span>
|
||||
</div>
|
||||
|
||||
<!-- Progress Bar -->
|
||||
<div>
|
||||
<div style="display: flex; justify-content: space-between; font-weight: bold; margin-bottom: 0.5rem; font-size: 0.95rem;">
|
||||
<span>Progress</span>
|
||||
<span id="progress-percent" style="color: var(--primary);">0%</span>
|
||||
</div>
|
||||
<div class="bar-container">
|
||||
<div id="progress-bar-fill" class="bar-fill"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistics grid -->
|
||||
<div class="progress-stats">
|
||||
<div class="stat-card">
|
||||
<span>Status</span>
|
||||
<span id="stat-status">Queued</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>Processed Frames</span>
|
||||
<span id="stat-frames">0 / 0</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span>Estimated ETA</span>
|
||||
<span id="stat-eta" style="color: var(--primary);">Calculating...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Realtime Logs Panel -->
|
||||
<div>
|
||||
<h4 style="font-family: var(--font-heading); margin-bottom: 0.5rem; color: var(--text-muted); font-size: 0.9rem;">Pipeline Live Activity Logs</h4>
|
||||
<div id="log-terminal" class="log-panel">
|
||||
<div class="log-line">Waiting for worker thread...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action control -->
|
||||
<div style="display: flex; justify-content: flex-end;">
|
||||
<button type="button" id="cancel-upscale-btn" class="btn btn-danger">
|
||||
<i class="fa-solid fa-circle-stop"></i> Abort Upscaling Job
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 4: Finished/Completed -->
|
||||
<div id="step-finished" class="step-container">
|
||||
<div class="glass-card finished-card">
|
||||
<div class="success-icon">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
<h2>Video Enhancement Completed!</h2>
|
||||
<p style="color: var(--text-muted); max-width: 500px; margin: 0 auto;">
|
||||
Your video was successfully upscaled and optimized using the Real-ESRGAN Vulkan backend model. Original audio streams have been merged.
|
||||
</p>
|
||||
|
||||
<div class="action-buttons">
|
||||
<a id="download-link" href="#" class="btn">
|
||||
<i class="fa-solid fa-download"></i> Download Upscaled Video
|
||||
</a>
|
||||
<button type="button" id="finished-play-comparison-btn" class="btn btn-secondary">
|
||||
<i class="fa-solid fa-film"></i> Compare Playback
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="window.location.reload()">
|
||||
<i class="fa-solid fa-rotate-left"></i> Process Another File
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Active Jobs & Queue Section -->
|
||||
<section class="queue-section glass-card" style="margin-top: 3rem;">
|
||||
<div class="queue-header" style="display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border-color); padding-bottom: 0.75rem; margin-bottom: 1rem;">
|
||||
<h2><i class="fa-solid fa-list-check"></i> Active Jobs & Pipeline Queue</h2>
|
||||
<button type="button" id="refresh-queue-btn" class="btn btn-secondary btn-small">
|
||||
<i class="fa-solid fa-arrows-rotate"></i> Refresh Queue
|
||||
</button>
|
||||
</div>
|
||||
<p style="color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1.5rem;">Monitor running and queued jobs in the queue pipeline. Preview jobs are marked as well.</p>
|
||||
|
||||
<div id="queue-list" class="queue-list" style="display: flex; flex-direction: column; gap: 0.75rem;">
|
||||
<!-- Dynamically populated queue items -->
|
||||
<div class="queue-empty-state" style="text-align: center; padding: 2rem; border: 1px dashed var(--border-color); border-radius: 12px; color: var(--text-muted);">
|
||||
<i class="fa-solid fa-list-ul" style="font-size: 2rem; margin-bottom: 0.5rem; color: var(--primary);"></i>
|
||||
<p>No active or queued jobs at the moment.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Completed Video Gallery -->
|
||||
<section class="gallery-section glass-card" style="margin-top: 3rem;">
|
||||
<div class="gallery-header">
|
||||
<h2><i class="fa-solid fa-photo-film"></i> Completed Enhancements</h2>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
<button type="button" id="refresh-gallery-btn" class="btn btn-secondary btn-small">
|
||||
<i class="fa-solid fa-arrows-rotate"></i> Refresh
|
||||
</button>
|
||||
<button type="button" id="purge-all-btn" class="btn btn-danger btn-small">
|
||||
<i class="fa-solid fa-trash-can-arrow-up"></i> Purge All Data
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p style="color: var(--text-muted); font-size: 0.9rem; margin-bottom: 1.5rem;">Access all your upscaled videos, play them side-by-side with original sources, or manage the storage.</p>
|
||||
|
||||
<div id="gallery-grid" class="gallery-grid">
|
||||
<!-- Dynamically populated completed items -->
|
||||
<div class="gallery-empty-state">
|
||||
<i class="fa-solid fa-photo-film"></i>
|
||||
<p>No completed jobs found. Start upscaling a video above to see it in the gallery!</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Synced Video Playback Modal -->
|
||||
<div id="video-modal" class="modal-overlay" style="display: none;">
|
||||
<div class="modal-card">
|
||||
<div class="modal-header">
|
||||
<h3><i class="fa-solid fa-film"></i> Side-by-Side Synced Video Comparison</h3>
|
||||
<button type="button" class="close-btn" id="modal-close-btn">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="video-compare-wrapper">
|
||||
<div class="video-container">
|
||||
<h4>Original (Before)</h4>
|
||||
<video id="modal-video-original" playsinline></video>
|
||||
</div>
|
||||
<div class="video-container">
|
||||
<h4>Upscaled (AI Enhanced)</h4>
|
||||
<video id="modal-video-upscaled" playsinline></video>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Synced Controls -->
|
||||
<div class="video-sync-controls">
|
||||
<button type="button" id="modal-play-btn" class="btn btn-circular">
|
||||
<i class="fa-solid fa-play"></i>
|
||||
</button>
|
||||
<div class="time-scrubber-container">
|
||||
<span id="modal-time-current">00:00</span>
|
||||
<input type="range" id="modal-time-slider" min="0" max="100" value="0" step="0.01">
|
||||
<span id="modal-time-duration">00:00</span>
|
||||
</div>
|
||||
<button type="button" id="modal-mute-btn" class="btn btn-secondary btn-circular">
|
||||
<i class="fa-solid fa-volume-high"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Javascript Orchestration -->
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user