260 lines
9 KiB
HTML
260 lines
9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="description" content="Server-side video compression tool using FFmpeg. Browse, select, and compress large video files." />
|
|
<title>VideoPress — FFmpeg Compressor</title>
|
|
<link rel="stylesheet" href="/static/css/main.css" />
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<!-- Fallback font stack if Google Fonts unavailable -->
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Skip navigation for accessibility -->
|
|
<a href="#main-content" class="skip-link">Skip to main content</a>
|
|
|
|
<header class="app-header" role="banner">
|
|
<div class="header-inner">
|
|
<div class="logo" aria-label="VideoPress FFmpeg Compressor">
|
|
<span class="logo-icon" aria-hidden="true">▶</span>
|
|
<span class="logo-text">Video<strong>Press</strong></span>
|
|
</div>
|
|
<div class="header-actions">
|
|
<button
|
|
id="theme-toggle"
|
|
class="btn-icon"
|
|
aria-label="Toggle dark/light mode"
|
|
title="Toggle dark/light mode"
|
|
>
|
|
<span class="theme-icon" aria-hidden="true" id="theme-icon">◑</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<main id="main-content" class="app-main" role="main">
|
|
|
|
<!-- STEP 1: Directory & Filter Configuration -->
|
|
<section class="card" id="section-config" aria-labelledby="config-heading">
|
|
<h2 id="config-heading" class="card-title">
|
|
<span class="step-badge" aria-hidden="true">01</span>
|
|
Configure Source
|
|
</h2>
|
|
|
|
<div class="config-grid">
|
|
<!-- Directory Browser -->
|
|
<div class="field-group">
|
|
<label for="dir-input" class="field-label">Server Directory</label>
|
|
<div class="dir-input-row">
|
|
<input
|
|
type="text"
|
|
id="dir-input"
|
|
class="text-input"
|
|
placeholder="/path/to/videos"
|
|
value="/"
|
|
aria-describedby="dir-hint"
|
|
autocomplete="off"
|
|
spellcheck="false"
|
|
/>
|
|
<button class="btn btn-secondary" id="browse-btn" aria-label="Browse server directories">
|
|
Browse
|
|
</button>
|
|
</div>
|
|
<p id="dir-hint" class="field-hint">Enter or browse to a directory on the server where videos are stored.</p>
|
|
</div>
|
|
|
|
<!-- Minimum File Size -->
|
|
<div class="field-group">
|
|
<label for="min-size-input" class="field-label">
|
|
Minimum File Size
|
|
<span class="field-unit">(GB)</span>
|
|
</label>
|
|
<input
|
|
type="number"
|
|
id="min-size-input"
|
|
class="text-input"
|
|
min="0.1"
|
|
max="1000"
|
|
step="0.1"
|
|
value="1.0"
|
|
aria-describedby="size-hint"
|
|
/>
|
|
<p id="size-hint" class="field-hint">Only files larger than this threshold will be listed.</p>
|
|
</div>
|
|
|
|
<!-- Suffix -->
|
|
<div class="field-group">
|
|
<label for="suffix-input" class="field-label">
|
|
Output Filename Suffix
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="suffix-input"
|
|
class="text-input"
|
|
value="_new"
|
|
placeholder="_new"
|
|
aria-describedby="suffix-hint"
|
|
maxlength="64"
|
|
/>
|
|
<p id="suffix-hint" class="field-hint">
|
|
Appended before the file extension. E.g. <code>movie_new.mp4</code>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-footer">
|
|
<button class="btn btn-primary btn-lg" id="scan-btn" aria-describedby="scan-status">
|
|
<span class="btn-icon-prefix" aria-hidden="true">⊙</span>
|
|
Scan for Files
|
|
</button>
|
|
<span id="scan-status" class="status-text" aria-live="polite" aria-atomic="true"></span>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Directory Browser Modal -->
|
|
<div
|
|
id="browser-modal"
|
|
class="modal-backdrop"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="browser-modal-title"
|
|
hidden
|
|
>
|
|
<div class="modal-panel">
|
|
<div class="modal-header">
|
|
<h3 id="browser-modal-title" class="modal-title">Browse Server Directory</h3>
|
|
<button class="btn-icon" id="close-browser" aria-label="Close directory browser">✕</button>
|
|
</div>
|
|
<div class="browser-path-bar">
|
|
<span class="browser-path-label" aria-label="Current path:">
|
|
<span id="browser-current-path" aria-live="polite">/</span>
|
|
</span>
|
|
</div>
|
|
<div id="browser-list" class="browser-list" role="listbox" aria-label="Directory contents" tabindex="0">
|
|
<p class="browser-loading">Loading…</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-secondary" id="browser-cancel">Cancel</button>
|
|
<button class="btn btn-primary" id="browser-select">Select This Directory</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- STEP 2: File List -->
|
|
<section class="card" id="section-files" aria-labelledby="files-heading" hidden>
|
|
<h2 id="files-heading" class="card-title">
|
|
<span class="step-badge" aria-hidden="true">02</span>
|
|
Select Files to Compress
|
|
</h2>
|
|
|
|
<div class="files-toolbar" role="toolbar" aria-label="File selection controls">
|
|
<div class="toolbar-left">
|
|
<button class="btn btn-sm btn-outline" id="select-all-btn" aria-label="Mark all files for compression">
|
|
☑ Select All
|
|
</button>
|
|
<button class="btn btn-sm btn-outline" id="deselect-all-btn" aria-label="Unmark all files">
|
|
☐ Deselect All
|
|
</button>
|
|
</div>
|
|
<div class="toolbar-right">
|
|
<span id="selection-summary" class="selection-summary" aria-live="polite" aria-atomic="true">
|
|
0 of 0 selected
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-wrapper" role="region" aria-label="Video files list" tabindex="0">
|
|
<table class="file-table" id="file-table" aria-describedby="files-heading">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col" class="col-check">
|
|
<span class="sr-only">Select</span>
|
|
</th>
|
|
<th scope="col" class="col-name">File Name</th>
|
|
<th scope="col" class="col-size">Size (GB)</th>
|
|
<th scope="col" class="col-bitrate">Current Bitrate</th>
|
|
<th scope="col" class="col-target">Target Bitrate</th>
|
|
<th scope="col" class="col-codec">Codec</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="file-tbody">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card-footer">
|
|
<button class="btn btn-primary btn-lg" id="compress-btn" disabled>
|
|
<span class="btn-icon-prefix" aria-hidden="true">⚡</span>
|
|
Compress Selected Files
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- STEP 3: Compression Progress -->
|
|
<section class="card" id="section-progress" aria-labelledby="progress-heading" hidden>
|
|
<h2 id="progress-heading" class="card-title">
|
|
<span class="step-badge" aria-hidden="true">03</span>
|
|
Compression Progress
|
|
</h2>
|
|
|
|
<div class="progress-overview" role="region" aria-label="Overall progress">
|
|
<div class="overview-stats">
|
|
<div class="stat-chip">
|
|
<span class="stat-label">Total Files</span>
|
|
<span class="stat-value" id="prog-total">—</span>
|
|
</div>
|
|
<div class="stat-chip">
|
|
<span class="stat-label">Completed</span>
|
|
<span class="stat-value" id="prog-done">0</span>
|
|
</div>
|
|
<div class="stat-chip">
|
|
<span class="stat-label">Status</span>
|
|
<span class="stat-value" id="prog-status" aria-live="polite">Waiting</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overall-bar-wrap" aria-label="Overall compression progress">
|
|
<div class="overall-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" id="overall-bar">
|
|
<div class="overall-bar-fill" id="overall-bar-fill" style="width:0%"></div>
|
|
</div>
|
|
<span class="overall-pct" id="overall-pct" aria-hidden="true">0%</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="file-progress-list" class="file-progress-list" aria-label="Individual file progress" role="list">
|
|
</div>
|
|
|
|
<div class="card-footer">
|
|
<button class="btn btn-danger" id="cancel-btn" aria-label="Cancel all compression operations">
|
|
✕ Cancel Compression
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Results summary (shown after done/cancelled) -->
|
|
<section class="card" id="section-results" aria-labelledby="results-heading" hidden>
|
|
<h2 id="results-heading" class="card-title">
|
|
<span class="step-badge" aria-hidden="true">04</span>
|
|
Results
|
|
</h2>
|
|
<div id="results-content" class="results-content"></div>
|
|
<div class="card-footer">
|
|
<button class="btn btn-secondary" id="restart-btn">
|
|
↺ Start New Session
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
</main>
|
|
|
|
<footer class="app-footer" role="contentinfo">
|
|
<p>VideoPress uses <strong>FFmpeg</strong> for video compression. Files are processed on the server.</p>
|
|
</footer>
|
|
|
|
<!-- Live region for screen reader announcements -->
|
|
<div id="sr-announce" class="sr-only" aria-live="assertive" aria-atomic="true"></div>
|
|
|
|
<script src="/static/js/app.js"></script>
|
|
</body>
|
|
</html>
|