Files
gui-video-clipper/chat-summaries/2026-09-21_12-56-fix-playback-codec-timeline-pan-summary.md

55 lines
3.2 KiB
Markdown
Raw Normal View History

# Fix: Video Codec Compatibility + Timeline Pan/Scroll + Minimap
**Date:** 2026-09-21 12:56
**Task:** Fix video playback (black screen despite play state), add timeline panning when zoomed, add minimap overview.
## Root Causes & Fixes
### 1. Video playback: WKWebView doesn't support VP9/WebM
The downloaded file was VP9+Opus in WebM container (yt-dlp format 399+251). Apple's WKWebView on macOS does NOT support VP9 codec. The `<video>` element accepted `.play()` but had no decodable frames.
**Fix:** Added `-f "bv*[vcodec^=avc1]+ba[acodec^=mp4a]/bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4]/b"` to the yt-dlp download command in `download_manager.rs`. This selects H.264 (avc1) video + AAC (mp4a) audio, producing an MP4 file playable by WKWebView. Deleted the cached WebM file.
### 2. Timeline: no scroll/pan when zoomed
Mouse wheel only triggered zoom. No way to scroll horizontally when zoomed in.
**Fix in `Timeline.svelte`:**
- **Horizontal scroll → pan:** `deltaX` from trackpad/shift+wheel now calls `panBy()` to shift the visible window
- **Vertical scroll → zoom** (unchanged)
**New `panBy()` in `interactions.ts`:** Computes new `visibleStart`/`visibleEnd` from pixel delta, clamped to `[0, duration]`.
### 3. Minimap overview bar
Added a minimap canvas that appears when zoomed in:
- Shows the full waveform at a glance
- Highlights the current viewport with a blue border
- Dims regions outside the viewport
- Click to center viewport, drag to pan
- Playhead indicator
### 4. Other fixes applied this session (cumulative)
- **stdout/stderr swap:** yt-dlp sends status messages to stdout, not stderr
- **`[Merger]` path parsing:** Correctly captures final merged file path
- **"Already downloaded" parsing:** Handles `has already been downloaded` message
- **Cache check:** `checkCachedDownload(title)` checks temp dir before invoking yt-dlp
- **Parallel processing:** Waveform/thumbnails/keyframes results applied individually as they complete
- **Asset protocol scope:** Added `/private/var/**` and `/var/**` for macOS symlink paths
## Files Changed
- `src-tauri/src/services/download_manager.rs` — H.264 format selection
- `src/lib/components/Timeline.svelte` — Minimap + horizontal pan support
- `src/lib/timeline/interactions.ts` — Added `panBy()` function
- `src-tauri/src/commands/video.rs` — Cache check, diagnostic logging
- `src-tauri/src/commands/media_analysis.rs` — Diagnostic logging
- `src-tauri/src/lib.rs` — Registered `check_cached_download` command
- `src-tauri/tauri.conf.json` — Expanded asset protocol scope
- `src/lib/stores/videoSession.svelte.ts` — Cache check before download, parallel results
- `src/lib/bindings/video.ts` — `checkCachedDownload` binding
- `src/lib/components/VideoPlayer.svelte` — Local file playback with progress UI
## Lessons Learned
1. **WKWebView codec support is limited.** VP9/AV1/WebM don't work. Must use H.264+AAC in MP4.
2. **macOS `/var` is a symlink to `/private/var`.** Asset protocol scope must cover both paths.
3. **`Promise.allSettled` blocks all results until the slowest completes.** Use individual `.then()` chains when you want progressive rendering.
4. **yt-dlp sends status to stdout, warnings to stderr.** Not the other way around.