anycoder-79d7d0e1 / index.html
Wahso's picture
Upload index.html with huggingface_hub
f7266ee verified
Raw
History Blame Contribute Delete
18.9 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Video Subtitle OCR - Extract Hard Subtitles</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@300;400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="app-container">
<!-- Header -->
<header class="app-header">
<div class="header-content">
<div class="logo">
<svg width="32" height="32" viewBox="0 0 32 32" fill="none">
<rect width="32" height="32" rx="8" fill="#6366f1"/>
<path d="M8 12h16M8 16h16M8 20h12" stroke="white" stroke-width="2" stroke-linecap="round"/>
</svg>
<h1>Video Subtitle OCR</h1>
</div>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-badge">
Built with anycoder
</a>
</div>
</header>
<!-- Main Content -->
<main class="main-content">
<!-- Setup Page -->
<div id="setup-page" class="page active">
<div class="setup-container">
<!-- Video Upload Section -->
<section class="upload-section">
<h2>1. Upload Video</h2>
<div class="upload-zone" id="upload-zone">
<input type="file" id="video-input" accept="video/*" hidden>
<div class="upload-content">
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17,8 12,3 7,8"/>
<line x1="12" y1="3" x2="12" y2="15"/>
</svg>
<p>Drag & drop video here or <span class="browse">browse</span></p>
<p class="upload-hint">Supports MP4, WebM, MOV, AVI (max 2GB)</p>
</div>
</div>
</section>
<!-- Video Preview & Subtitle Area -->
<section class="preview-section" id="preview-section" style="display: none;">
<h2>2. Adjust Subtitle Area</h2>
<div class="video-wrapper">
<video id="video-preview" controls></video>
<canvas id="subtitle-overlay" class="subtitle-overlay"></canvas>
<div id="subtitle-box" class="subtitle-box">
<div class="resize-handle nw"></div>
<div class="resize-handle ne"></div>
<div class="resize-handle sw"></div>
<div class="resize-handle se"></div>
</div>
</div>
<!-- Subtitle Area Controls -->
<div class="subtitle-controls">
<div class="control-group">
<label>Horizontal Position (X)</label>
<input type="range" id="x-position" min="0" max="100" value="10">
<span class="value" id="x-value">10%</span>
</div>
<div class="control-group">
<label>Vertical Position (Y)</label>
<input type="range" id="y-position" min="0" max="100" value="75">
<span class="value" id="y-value">75%</span>
</div>
<div class="control-group">
<label>Width</label>
<input type="range" id="width" min="10" max="100" value="80">
<span class="value" id="width-value">80%</span>
</div>
<div class="control-group">
<label>Height</label>
<input type="range" id="height" min="5" max="50" value="15">
<span class="value" id="height-value">15%</span>
</div>
<div class="control-group checkbox">
<label>
<input type="checkbox" id="aspect-lock" checked>
Lock Aspect Ratio
</label>
</div>
</div>
<div class="quick-actions">
<button id="reset-box" class="btn-secondary">Reset Box</button>
<button id="auto-detect" class="btn-secondary">Auto-Detect Subtitles</button>
</div>
</section>
<!-- Language Selection -->
<section class="language-section" id="language-section" style="display: none;">
<h2>3. Select Language</h2>
<div class="language-grid">
<button class="lang-btn active" data-lang="eng">English</button>
<button class="lang-btn" data-lang="jpn">Japanese</button>
<button class="lang-btn" data-lang="kor">Korean</button>
<button class="lang-btn" data-lang="chi_sim">Chinese (Simplified)</button>
<button class="lang-btn" data-lang="chi_tra">Chinese (Traditional)</button>
<button class="lang-btn" data-lang="tha">Thai</button>
</div>
</section>
<!-- Time Range Selection -->
<section class="time-section" id="time-section" style="display: none;">
<h2>4. Select Time Range</h2>
<div class="time-controls">
<div class="time-input-group">
<label>Start Time</label>
<div class="time-input">
<input type="number" id="start-hours" min="0" max="99" value="0" placeholder="HH">
<span>:</span>
<input type="number" id="start-minutes" min="0" max="59" value="0" placeholder="MM">
<span>:</span>
<input type="number" id="start-seconds" min="0" max="59" value="0" placeholder="SS">
<span>.</span>
<input type="number" id="start-ms" min="0" max="999" value="0" placeholder="mmm">
</div>
<button id="set-start-current" class="btn-small">Set to Current</button>
</div>
<div class="time-input-group">
<label>End Time</label>
<div class="time-input">
<input type="number" id="end-hours" min="0" max="99" value="0" placeholder="HH">
<span>:</span>
<input type="number" id="end-minutes" min="0" max="59" value="0" placeholder="MM">
<span>:</span>
<input type="number" id="end-seconds" min="0" max="59" value="0" placeholder="SS">
<span>.</span>
<input type="number" id="end-ms" min="0" max="999" value="0" placeholder="mmm">
</div>
<button id="set-end-current" class="btn-small">Set to Current</button>
</div>
</div>
<div class="time-slider-container">
<div class="range-slider" id="time-range-slider">
<div class="range-track"></div>
<div class="range-fill" id="range-fill"></div>
<div class="range-thumb start" id="start-thumb"></div>
<div class="range-thumb end" id="end-thumb"></div>
</div>
<div class="time-labels">
<span id="slider-start-time">00:00:00.000</span>
<span id="slider-end-time">00:00:00.000</span>
</div>
</div>
</section>
<!-- Process Button -->
<section class="process-section" id="process-section" style="display: none;">
<button id="process-btn" class="btn-primary btn-large">
<span class="btn-text">Process Video</span>
<span class="btn-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="5,3 19,12 5,21 5,3"/>
</svg>
</span>
</button>
<p class="process-hint">This may take a few minutes depending on video length</p>
</section>
</div>
</div>
<!-- Processing Page -->
<div id="processing-page" class="page">
<div class="processing-container">
<div class="processing-animation">
<div class="spinner"></div>
<div class="processing-video" id="processing-preview"></div>
</div>
<h2>Processing Video...</h2>
<div class="progress-container">
<div class="progress-bar" id="progress-bar">
<div class="progress-fill" id="progress-fill"></div>
</div>
<div class="progress-info">
<span id="progress-text">Initializing OCR model...</span>
<span id="progress-percent">0%</span>
</div>
</div>
<div class="processing-stats">
<div class="stat">
<span class="stat-label">Frames Processed</span>
<span class="stat-value" id="frames-processed">0</span>
</div>
<div class="stat">
<span class="stat-label">Subtitles Found</span>
<span class="stat-value" id="subtitles-found">0</span>
</div>
<div class="stat">
<span class="stat-label">Time Elapsed</span>
<span class="stat-value" id="time-elapsed">00:00</span>
</div>
</div>
<button id="cancel-process" class="btn-secondary">Cancel</button>
</div>
</div>
<!-- Results Page -->
<div id="results-page" class="page">
<div class="results-container">
<!-- Video Player with Active Subtitle Highlighting -->
<section class="result-video-section">
<h2>Preview with Subtitles</h2>
<div class="video-wrapper result-video-wrapper">
<video id="result-video" controls></video>
<div id="active-subtitle" class="active-subtitle-display"></div>
</div>
<div class="playback-controls">
<button id="prev-subtitle" class="btn-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="19,20 9,12 19,4 19,20"/>
<line x1="5" y1="19" x2="5" y2="5"/>
</svg>
</button>
<button id="sync-subtitle" class="btn-icon" title="Sync to current subtitle">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<polyline points="12,6 12,12 16,14"/>
</svg>
</button>
<button id="next-subtitle" class="btn-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="5,4 15,12 5,20 5,4"/>
<line x1="19" y1="5" x2="19" y2="19"/>
</svg>
</button>
</div>
</section>
<!-- Subtitle List -->
<section class="subtitle-list-section">
<div class="section-header">
<h2>Extracted Subtitles</h2>
<div class="view-toggle">
<button class="toggle-btn active" data-view="list">List</button>
<button class="toggle-btn" data-view="json">JSON</button>
</div>
</div>
<!-- List View -->
<div id="subtitle-list-view" class="subtitle-list">
<div class="list-header">
<span>#</span>
<span>Time</span>
<span>Subtitle Text</span>
<span>Status</span>
</div>
<div id="subtitles-container" class="subtitles-container">
<!-- Subtitles will be inserted here -->
</div>
</div>
<!-- JSON View -->
<div id="subtitle-json-view" class="json-view" style="display: none;">
<pre id="json-output"></pre>
<button id="copy-json" class="btn-secondary btn-small">Copy JSON</button>
</div>
</section>
<!-- Export Section -->
<section class="export-section">
<h2>Export Subtitles</h2>
<div class="export-buttons">
<button id="export-srt" class="btn-primary">
<svg width="20" height="20" 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"/>
<polyline points="7,10 12,15 17,10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
Download SRT
</button>
<button id="export-txt" class="btn-secondary">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14,2 14,8 20,8"/>
<line x1="16" y1="13" x2="8" y2="13"/>
<line x1="16" y1="17" x2="8" y2="17"/>
<polyline points="10,9 9,9 8,9"/>
</svg>
Download TXT
</button>
<button id="export-json" class="btn-secondary">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14,2 14,8 20,8"/>
<line x1="16" y1="13" x2="8" y2="13"/>
<line x1="16" y1="17" x2="8" y2="17"/>
<polyline points="10,9 9,9 8,9"/>
</svg>
Download JSON
</button>
</div>
</section>
<!-- Start Over -->
<section class="start-over-section">
<button id="start-over" class="btn-secondary btn-large">Process Another Video</button>
</section>
</div>
</div>
</main>
<!-- Loading Overlay -->
<div id="loading-overlay" class="loading-overlay">
<div class="loading-content">
<div class="spinner"></div>
<p>Loading OCR model...</p>
<div class="model-progress">
<div class="model-progress-bar" id="model-progress-bar"></div>
</div>
</div>
</div>
<!-- Error Toast -->
<div id="error-toast" class="error-toast">
<span id="error-message"></span>
<button id="error-close">&times;</button>
</div>
</div>
<script type="module" src="index.js"></script>
</body>
</html>