Files
gui-video-clipper/chat-summaries/2026-09-22_14-50-v0.1.2-polish-summary.md
cottongin 9499d776fd fix: about dialog, cache paths, keyframes, reprocess always uses low-res
- Replace native macOS About menu with custom Svelte dialog via Tauri event
- Inline SVG icon in AboutDialog (fixes broken image in webview)
- Align cache directory with Tauri $APPDATA, add to asset protocol scope
- Fix ffprobe 8.x keyframe parsing (skip_frame nokey, flexible parser)
- Copy caption files into cache dir when outside cache path
- Add -y flag to ffmpeg thumbnail extraction (prevent hang on re-extract)
- Reprocess always uses preview (low-res) file, never HQ export
- Prefer cached preview file for analysis even when HQ is cached
- Guard upgrade toast when already on HQ

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-22 16:16:00 -04:00

5.2 KiB

v0.1.2 Polish — Placeholders, Auto-Upgrade, Analysis Cache

Date: 2026-09-22 14:50 ET Duration: ~20 minutes (brainstorm) + ~20 minutes (execution) Version: 0.1.1 → 0.1.2 Commits: 2f81011..925a3fc (11 commits)

Task Description

Three polish features for v0.1.2:

  1. Fix misleading "Generating Waveform…" / "Generating Thumbnails…" placeholder text shown in the timeline before any video is loaded
  2. Automatically use cached HQ video files instead of prompting user to "Upgrade" when the export file is already downloaded
  3. Cache video analysis results (waveforms, keyframes, thumbnails, captions) to avoid reprocessing the same video on reload

Changes Made

Feature 1: Idle-State Placeholder Text

  • src/lib/timeline/renderer.ts: Added hasVideo boolean parameter to drawTimeline() and showLabel to drawPlaceholderLane(). When no video is loaded, timeline lanes show empty backgrounds without misleading "Generating…" text.
  • src/lib/components/Timeline.svelte: Passes session.status === 'ready' as the hasVideo argument.

Feature 2: Auto-Use Cached HQ Video

  • src/lib/stores/videoSession.svelte.ts: Restructured beginDownload() to check export (HQ) cache before preview cache. When HQ file exists on disk, it's used directly as the active video — no preview download, no upgrade toast. The upgrade toast is preserved for mid-session HQ completions (to avoid jarring video source swaps during playback).

Feature 3: Analysis Cache System

New Rust service (src-tauri/src/services/cache_manager.rs):

  • Cache stored at ~/Library/Application Support/gui-video-clipper/cache/
  • Videos keyed by SHA-256 URL hash (first 16 hex chars)
  • JSON manifest per video with waveform tiers, keyframe positions, thumbnail spritesheets, caption paths
  • Functions: load_manifest, save_manifest, clear_cache_entry, clear_all_cache, get_cache_stats
  • 5 unit tests for URL hashing and path computation

New IPC commands (src-tauri/src/commands/cache.rs):

  • load_cached_analysis / save_analysis_to_cache / clear_video_cache / clear_all_cache / get_cache_stats / get_thumbnail_cache_dir / get_caption_cache_dir
  • Path resolution: manifest stores relative paths, IPC layer resolves to absolute for frontend

Updated extract_thumbnails: Added optional output_dir parameter so thumbnails can be directed to cache directory instead of random temp dir.

TypeScript bindings (src/lib/bindings/cache.ts): Full wrapper layer for all cache IPC commands.

Frontend integration (src/lib/stores/videoSession.svelte.ts):

  • triggerPostDownloadProcessing() checks cache first — on hit, populates session state instantly and skips ffmpeg. On miss, extracts normally then saves to cache.
  • Thumbnails directed to cache dir via getThumbnailCacheDir
  • New reprocessCurrentVideo() export: clears cache entry and re-runs extraction

Preferences panel: Cache management section showing total size and entry count with "Clear All Cache" button.

StatusBar: Per-video "↻" reprocess button visible when processing is complete.

Dependency added: sha2 = "0.10" for URL hashing.

Files Changed (15 files)

New Files (3)

  • src-tauri/src/services/cache_manager.rs
  • src-tauri/src/commands/cache.rs
  • src/lib/bindings/cache.ts

Modified Files (12)

  • src/lib/timeline/renderer.ts
  • src/lib/components/Timeline.svelte
  • src/lib/stores/videoSession.svelte.ts
  • src-tauri/src/services/mod.rs
  • src-tauri/src/commands/mod.rs
  • src-tauri/src/lib.rs
  • src-tauri/Cargo.toml + Cargo.lock
  • src-tauri/src/commands/media_analysis.rs
  • src/lib/bindings/mediaAnalysis.ts
  • src/lib/components/PreferencesPanel.svelte
  • src/lib/components/StatusBar.svelte
  • VERSION, package.json, tauri.conf.json

Test Results

  • Rust: 56 tests pass, 0 warnings
  • Frontend: svelte-check 0 errors/warnings, vitest 31/31 pass

Follow-Up Items

  • HQ+toast edge case: When video loaded with cached HQ file, triggerPostDownloadProcessing can still set showUpgradeToast = true even though playback is already HQ. Cosmetic — toast appears but does nothing harmful. Could add a guard activeVideoPath !== exportFilePath in a future pass.
  • now_iso8601 naming: Function in cache_manager.rs returns Unix epoch seconds, not ISO 8601. Cosmetic naming issue.
  • Caption cache dir: getCaptionCacheDir is wired but not used yet — captions still go to temp dir. The manifest stores whatever path captions end up at. Could wire caption output to cache dir in a future pass for full persistence.
  • Project files: Cache manifest structure is designed as forward-looking scaffold for future project file save/load. No UI implemented yet.

Lessons Learned

  • Checking export cache before preview cache in beginDownload() was a clean refactor that simplified the flow — early return avoids duplicate logic.
  • Inlining waveform/keyframe data in JSON manifests works well for the data sizes involved (~2 MB worst case). No need for binary serialization.
  • The #![allow(dead_code)] at module scope in cache_manager.rs was pragmatic but broader than ideal — individual annotations would be more precise. Resolved naturally once Task 5 wired up the commands.