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>
65 lines
4.0 KiB
Markdown
65 lines
4.0 KiB
Markdown
# Styled Burn-In and Granular Export Progress
|
|
|
|
**Date:** 2026-09-21 23:00
|
|
**Task:** Apply user's caption style settings to burned-in subtitles via ffmpeg's ASS force_style, and add granular per-clip progress reporting during export.
|
|
|
|
## Changes Made
|
|
|
|
### 1. CaptionStyle Model (Rust + TS)
|
|
|
|
- **`src-tauri/src/models.rs`** — Added `CaptionStyle` struct with `font_size`, `text_color`, `background_opacity`, `text_outline`, `position`. Added `caption_style: Option<CaptionStyle>` to `ExportConfig`.
|
|
- **`src/lib/bindings/export.ts`** — Added matching `CaptionStyle` interface and `captionStyle: CaptionStyle | null` to `ExportConfig`. Added `clipProgress` event variant to the discriminated union. Added optional `onClipProgress` callback parameter to `exportClips()`.
|
|
|
|
### 2. ASS force_style in clip_exporter.rs
|
|
|
|
- **`src-tauri/src/services/clip_exporter.rs`**:
|
|
- `hex_to_ass_color()` — Converts CSS hex `#RRGGBB` to ASS `&H00BBGGRR` format.
|
|
- `opacity_to_ass_back_colour()` — Converts 0-1 opacity to ASS alpha-prefixed BackColour.
|
|
- `caption_style_to_force_style()` — Builds the full ASS force_style string from CaptionStyle (Fontsize, PrimaryColour, BackColour, Outline, Shadow, Alignment, MarginV, BorderStyle).
|
|
- `build_ffmpeg_args_burnin_subs()` now accepts `Option<&CaptionStyle>` and appends `:force_style='...'` to the subtitles filter when provided.
|
|
- `parse_ffmpeg_time()` — Extracts `time=HH:MM:SS.mm` from ffmpeg stderr progress output.
|
|
- `run_ffmpeg_with_progress()` — Runs ffmpeg with piped stderr, parses progress lines, and invokes a callback with 0.0-1.0 percent values.
|
|
|
|
### 3. Progress Callbacks Throughout Export Pipeline
|
|
|
|
All four export functions (`export_single_clip`, `export_single_clip_with_subs`, `export_merged`, `export_merged_with_subs`) now accept progress callbacks. They use `run_ffmpeg_with_progress()` instead of `.output()` for the encode step, streaming real-time progress.
|
|
|
|
### 4. export.rs Command Handler
|
|
|
|
- **`src-tauri/src/commands/export.rs`** — Added `ClipProgress` event variant with `current`, `total`, `label`, `percent`. Wired progress callbacks for both Individual and Merged export paths. Passes `caption_style` through to the exporter.
|
|
|
|
### 5. ExportDialog Frontend
|
|
|
|
- **`src/lib/components/ExportDialog.svelte`**:
|
|
- Populates `captionStyle` in config from `preferences.captionSettings` when burn-in is enabled.
|
|
- Shows a progress bar with percentage during each clip export.
|
|
- Displays note that karaoke word highlighting is preview-only for burn-in.
|
|
|
|
## Files Modified
|
|
|
|
| File | Change |
|
|
|------|--------|
|
|
| `src-tauri/src/models.rs` | Added `CaptionStyle` struct, added field to `ExportConfig` |
|
|
| `src-tauri/src/services/clip_exporter.rs` | ASS helpers, force_style, ffmpeg progress streaming, progress callbacks |
|
|
| `src-tauri/src/commands/export.rs` | `ClipProgress` event, caption_style passthrough, progress wiring |
|
|
| `src/lib/bindings/export.ts` | `CaptionStyle` interface, `clipProgress` event, `onClipProgress` callback |
|
|
| `src/lib/components/ExportDialog.svelte` | captionStyle in config, progress bar UI, karaoke note |
|
|
|
|
## Build Verification
|
|
|
|
- `cargo check` — passes (only pre-existing warnings)
|
|
- `cargo test` — all 43 tests pass
|
|
- `svelte-check` — passes (only pre-existing `vite.config.ts` errors)
|
|
|
|
## Lessons Learned
|
|
|
|
- ASS color format uses BGR byte order with alpha prefix (`&HAA_BB_GG_RR`), where alpha `00` = opaque and `FF` = transparent (inverted from CSS).
|
|
- `BorderStyle=4` in ASS gives an opaque background box behind text (like CSS background), vs `BorderStyle=1` which uses outline+shadow only.
|
|
- ffmpeg progress is on stderr, not stdout. The `time=` field is the key metric for computing encode progress percentage.
|
|
- For merged exports, progress is reported per-segment during encoding, plus a concat step at the end.
|
|
|
|
## Follow-Up Items
|
|
|
|
- Smoke test burn-in export to verify styled subtitles render correctly.
|
|
- Karaoke word-by-word animation in burn-in would require converting VTT word timestamps to ASS `\k` override tags — complex and fragile, noted as preview-only limitation.
|