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>
4.1 KiB
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— Addedcheck_subtitles_filter()that runsffmpeg -filtersand checks forsubtitles V->Vin the output.src-tauri/src/commands/dependencies.rs— Addedcheck_subtitles_filter_available()Tauri command.src-tauri/src/lib.rs— Registered the new command.src/lib/bindings/dependencies.ts— AddedcheckSubtitlesFilterAvailable()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
WordSegmentinterface ({ text: string; startTime: number }). - Added optional
words?: WordSegment[]toVttCue. - Added
parseWordTimings()that extracts<HH:MM:SS.mmm><c> word</c>patterns. - Added
getActiveWords()helper that returns each word marked asspokenor upcoming based oncurrentTime. - The plain
textfield is preserved (stripped) for backward compat.
- Added
3. Render Karaoke Word-by-Word Highlights
Fix:
src/lib/components/VideoPlayer.svelte— Updated caption rendering:- When
wordHighlightis 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.
- When
4. Add Word Highlight Toggle
Fix:
src/lib/stores/preferences.svelte.ts— AddedwordHighlight: booleantoCaptionSettingsinterface (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-existingvite.config.tstype 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
subtitlesfilter 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.