diff --git a/src/lib/components/VideoPlayer.svelte b/src/lib/components/VideoPlayer.svelte
index c444a27..36842e3 100644
--- a/src/lib/components/VideoPlayer.svelte
+++ b/src/lib/components/VideoPlayer.svelte
@@ -1,12 +1,122 @@
- {#if session.status === 'ready' && session.streamUrl}
+ {#if session.status === 'ready' && session.previewStatus === 'complete' && videoSrc}
+ onerror={handleError}
+ onloadeddata={handleLoadedData}
+ preload="metadata"
+ playsinline
+ >
+ {#if activeCues.length > 0}
+
+ {#each activeCues as cue}
+ {#if preferences.captionSettings.wordHighlight && cue.words}{#each getActiveWords(cue, session.currentTime) as word}{word.text}{' '}{/each}{:else}{cue.text}{/if}
+ {/each}
+
+ {/if}
+ {#if parsedCues.length > 0}
+
+
+
+
+ {/if}
+ {#if showCaptionSettings}
+
(showCaptionSettings = false)} />
+ {/if}
+ {#if session.showUpgradeToast}
+
+ Higher quality preview available
+
+
+
+ {/if}
+ {#if videoError}
+ {videoError}
+ {/if}
+ {:else if session.status === 'ready' && session.previewStatus === 'downloading'}
+
+
Downloading preview…
+
+
{Math.round(session.previewProgress * 100)}%
+
{:else if session.status === 'resolving'}
Loading video…
{:else if session.status === 'error'}
{session.error ?? 'Failed to load video.'}
+ {:else if session.status === 'ready' && session.previewStatus === 'idle'}
+ Preparing download…
{:else}
Paste a URL above to load a video
{/if}
@@ -74,8 +267,9 @@
align-items: center;
justify-content: center;
background: #000;
- min-height: 200px;
+ min-height: 0;
position: relative;
+ overflow: hidden;
}
video {
@@ -84,6 +278,77 @@
object-fit: contain;
}
+ .caption-overlay {
+ position: absolute;
+ left: 0;
+ right: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 2px;
+ pointer-events: none;
+ z-index: 5;
+ padding: 0 10%;
+ }
+
+ .caption-text {
+ display: inline-block;
+ padding: 4px 10px;
+ border-radius: 3px;
+ line-height: 1.4;
+ text-align: center;
+ white-space: pre-wrap;
+ max-width: 80%;
+ }
+
+ .caption-word {
+ transition: opacity 0.1s ease;
+ }
+
+ .caption-word.spoken {
+ opacity: 1;
+ }
+
+ .cc-controls {
+ position: absolute;
+ bottom: 12px;
+ right: 12px;
+ display: flex;
+ gap: 4px;
+ z-index: 10;
+ }
+
+ .cc-toggle,
+ .cc-settings-btn {
+ background: rgba(0, 0, 0, 0.7);
+ color: #ccc;
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ border-radius: 4px;
+ padding: 4px 8px;
+ font-size: 12px;
+ font-weight: 700;
+ cursor: pointer;
+ letter-spacing: 0.5px;
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
+ }
+
+ .cc-toggle:hover,
+ .cc-settings-btn:hover {
+ background: rgba(0, 0, 0, 0.9);
+ color: #fff;
+ }
+
+ .cc-toggle.active {
+ background: rgba(255, 255, 255, 0.9);
+ color: #000;
+ border-color: rgba(255, 255, 255, 0.9);
+ }
+
+ .cc-settings-btn {
+ font-weight: 400;
+ font-size: 14px;
+ }
+
.placeholder {
color: var(--text-muted);
font-size: 16px;
@@ -92,4 +357,84 @@
.placeholder.error {
color: var(--danger);
}
+
+ .video-overlay-error {
+ position: absolute;
+ bottom: 8px;
+ left: 8px;
+ right: 8px;
+ padding: 6px 10px;
+ background: rgba(0, 0, 0, 0.8);
+ color: var(--danger);
+ font-size: 12px;
+ border-radius: 4px;
+ z-index: 20;
+ }
+
+ .progress-bar {
+ width: 200px;
+ height: 6px;
+ background: var(--bg-tertiary);
+ border-radius: 3px;
+ margin: 12px auto 6px;
+ overflow: hidden;
+ }
+
+ .progress-fill {
+ height: 100%;
+ background: var(--accent, #89b4fa);
+ border-radius: 3px;
+ transition: width 0.3s ease;
+ }
+
+ .progress-text {
+ font-size: 13px;
+ color: var(--text-secondary);
+ }
+
+ .upgrade-toast {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ background: var(--bg-primary, #1e1e2e);
+ border: 1px solid var(--border, #353550);
+ border-radius: 6px;
+ padding: 8px 12px;
+ font-size: 12px;
+ color: var(--text-primary, #cdd6f4);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
+ z-index: 15;
+ }
+
+ .upgrade-btn {
+ background: #89b4fa;
+ color: #1e1e2e;
+ border: none;
+ border-radius: 4px;
+ padding: 4px 10px;
+ font-size: 11px;
+ font-weight: 600;
+ cursor: pointer;
+ }
+
+ .upgrade-btn:hover {
+ background: #b4d0fb;
+ }
+
+ .dismiss-btn {
+ background: none;
+ border: none;
+ color: var(--text-secondary, #6c7086);
+ cursor: pointer;
+ font-size: 14px;
+ padding: 2px 4px;
+ line-height: 1;
+ }
+
+ .dismiss-btn:hover {
+ color: var(--text-primary, #cdd6f4);
+ }