Files
gui-video-clipper/chat-summaries/2026-09-21_22-06-fix-burnin-karaoke-preview-summary.md
cottongin 8ad2f1c800 chore: stage all pending work — caption styling, media server, processing modal, docs, summaries
Includes:
- Extended caption styling (font, shadow, dimmed color, bg toggle)
- Media server, subtitle downloader, VTT parser, processing modal
- Waveform tiers, thumbnail/timeline improvements, transport controls
- Hybrid download model, dependency management, clip export enhancements
- 21 chat summaries, 2 implementation plans, 2 design specs

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

4.1 KiB

Fix Burn-In Export and Re-Introduce Karaoke Preview

Date: 2026-09-21 22:06
Task: Implement graceful burn-in fallback and re-introduce karaoke word-by-word highlighting in preview captions.

Changes Made

1. Detect subtitles Filter Availability (Burn-In Guard)

Problem: The user's ffmpeg build (Homebrew 9.0.1_1) lacks libass, so the subtitles filter is unavailable. Attempting burn-in export caused ffmpeg to crash with a filter parse error.

Fix:

  • src-tauri/src/services/dependency_manager.rs — Added check_subtitles_filter() that runs ffmpeg -filters and checks for subtitles V->V in the output.
  • src-tauri/src/commands/dependencies.rs — Added check_subtitles_filter_available() Tauri command.
  • src-tauri/src/lib.rs — Registered the new command.
  • src/lib/bindings/dependencies.ts — Added checkSubtitlesFilterAvailable() frontend binding.
  • src/lib/components/ExportDialog.svelte — On mount, checks filter availability via the new command. If unavailable, the "Burn into video" checkbox is disabled with a help message telling the user how to install libass.

2. Parse Word-Level Timings from VTT

Problem: YouTube auto-generated VTT files contain word-level timestamps in <timestamp><c> word</c> patterns. The old parser stripped ALL tags, losing this timing data.

Fix:

  • src/lib/utils/vttParser.ts — Complete rewrite:
    • Added WordSegment interface ({ text: string; startTime: number }).
    • Added optional words?: WordSegment[] to VttCue.
    • Added parseWordTimings() that extracts <HH:MM:SS.mmm><c> word</c> patterns.
    • Added getActiveWords() helper that returns each word marked as spoken or upcoming based on currentTime.
    • The plain text field is preserved (stripped) for backward compat.

3. Render Karaoke Word-by-Word Highlights

Fix:

  • src/lib/components/VideoPlayer.svelte — Updated caption rendering:
    • When wordHighlight is enabled and the cue has word segments, each word is rendered as a separate <span>.
    • Spoken words display at full opacity; upcoming words display at 40% opacity.
    • CSS transition smooths the opacity change.
    • When disabled or no word data available, falls back to plain text rendering.

4. Add Word Highlight Toggle

Fix:

  • src/lib/stores/preferences.svelte.ts — Added wordHighlight: boolean to CaptionSettings interface (default: true).
  • src/lib/components/CaptionSettingsPanel.svelte — Added "Word-by-word highlight" checkbox toggle.

Files Modified

File Change
src-tauri/src/services/dependency_manager.rs Added check_subtitles_filter()
src-tauri/src/commands/dependencies.rs Added check_subtitles_filter_available command
src-tauri/src/lib.rs Registered new command
src/lib/bindings/dependencies.ts Added checkSubtitlesFilterAvailable() binding
src/lib/components/ExportDialog.svelte Conditional burn-in disable + help text
src/lib/utils/vttParser.ts Word-level timing parser + getActiveWords()
src/lib/components/VideoPlayer.svelte Karaoke word rendering
src/lib/stores/preferences.svelte.ts Added wordHighlight to CaptionSettings
src/lib/components/CaptionSettingsPanel.svelte Added word highlight toggle

Build Verification

  • cargo check — passes (only pre-existing warnings)
  • svelte-check — passes (only pre-existing vite.config.ts type errors)

Lessons Learned

  • YouTube VTT word-timing format: leading text has no <c> wrapper, only subsequent words do. The first word inherits the cue's start time.
  • The subtitles filter requires libass at ffmpeg compile time — it's not enough to have ffmpeg installed. Homebrew's default build may or may not include it depending on the formula version.

Follow-Up Items

  • Manual smoke test: Load a video with captions, verify karaoke highlighting works during playback.
  • Test export with captions enabled (muxed track) to confirm no regressions.
  • If user installs libass and reinstalls ffmpeg, burn-in should automatically become available next time ExportDialog opens.