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>
5.1 KiB
Extended Caption Styling: Font, Shadow, Dimmed Color
Date: 2026-09-22
Scope: Add font selection (system font detection), drop shadow controls, dimmed/unspoken text color customization, and background toggle to the shared caption settings panel.
Problem
Several burn-in caption style properties are hardcoded: font is always Arial, shadow is always off, and the dimmed (unspoken) text color in word-by-word mode is a hardcoded grey (&H73CCCCCC) that doesn't relate to the user's chosen text color. The preview uses a different approach (CSS opacity on the main color), creating a visual mismatch between preview and exported captions.
New Settings Fields
Added to CaptionSettings (frontend) and CaptionStyle (backend):
| Field | Type | Default | Description |
|---|---|---|---|
fontFamily |
string | 'Arial' |
Font family name from system fonts |
backgroundEnabled |
boolean | true |
Explicit toggle for the background box (replaces relying on opacity=0) |
shadowEnabled |
boolean | false |
Drop shadow toggle (mutually exclusive with background) |
shadowDepth |
number (1-5) | 2 |
Shadow offset in ASS units |
shadowColor |
string | '#000000' |
Shadow color (hex) |
dimmedColorMode |
'auto' | 'custom' |
'auto' |
How unspoken word color is derived |
dimmedOpacity |
number (0.1-0.9) | 0.4 |
Opacity for auto-derived dimmed color |
dimmedColor |
string | '#999999' |
Custom dimmed color (used in custom mode) |
Background / Shadow Mutual Exclusivity
Background and shadow are mutually exclusive. Enabling one disables the other. This is required because ASS uses BackColour for both the background box and shadow color — they cannot be independent simultaneously.
ASS BorderStyle Mapping
| Background | Outline | Shadow | ASS BorderStyle | ASS Outline | ASS Shadow |
|---|---|---|---|---|---|
| ON | ON | - | 4 | 2 | 0 |
| ON | OFF | - | 3 | 0 | 0 |
| - | ON | ON | 1 | 2 | depth |
| - | OFF | ON | 1 | 0 | depth |
| OFF | ON | OFF | 1 | 2 | 0 |
| OFF | OFF | OFF | 1 | 0 | 0 |
When background is ON: BackColour = backgroundColor + backgroundOpacity alpha.
When shadow is ON: BackColour = shadowColor (fully opaque).
When neither: BackColour = transparent (&HFF000000).
Dimmed Text Color
In word-by-word (karaoke) mode, unspoken words appear in a dimmed color (ASS SecondaryColour).
Auto Mode (default)
The dimmed color is derived from the main textColor at dimmedOpacity. Both preview and burn-in use the same approach:
- Preview CSS:
opacity: {dimmedOpacity}on unspoken word spans (current behavior, but using the configurable value instead of hardcoded 0.4) - Burn-in ASS:
SecondaryColour = hex_to_ass_color_with_alpha(textColor, (1 - dimmedOpacity) * 255)
Custom Mode
The user picks a specific dimmedColor. Both preview and burn-in use it directly:
- Preview CSS:
color: {dimmedColor}; opacity: 1on unspoken word spans - Burn-in ASS:
SecondaryColour = hex_to_ass_color(dimmedColor)
System Font Detection
A new Tauri command list_system_fonts runs fc-list : family (fontconfig, available because ffmpeg/libass depend on it). Output is parsed into a sorted, deduplicated list of font family names.
- Called once when the caption settings panel opens; result is cached in component state.
- If
fc-listis not available, falls back to a hardcoded preset list: Arial, Helvetica, Verdana, Georgia, Times New Roman, Courier New, Impact. - The dropdown renders each option with
font-familyset to that font's name, providing a live preview of each font.
Panel UI Layout
The settings panel (320px wide) is organized into grouped sections:
- Font: Dropdown (system fonts) + Size slider + Bold checkbox
- Text Color: Color picker
- Dimmed Text: Auto/Custom toggle. Auto: opacity slider. Custom: color picker.
- Outline: Checkbox + color picker (disabled when unchecked)
- Background (mutually exclusive with shadow): Checkbox + color picker + opacity slider
- Shadow (mutually exclusive with background): Checkbox + depth slider + color picker
- Position: Bottom/Top radio
- Word Highlight: Checkbox (karaoke on/off)
- Reset to defaults button
Files Changed
| File | Change |
|---|---|
src/lib/stores/preferences.svelte.ts |
Add new fields to CaptionSettings interface and defaults |
src-tauri/src/models.rs |
Add new fields to CaptionStyle struct |
src/lib/bindings/export.ts |
Update TS CaptionStyle interface |
src/lib/components/ExportDialog.svelte |
Pass new fields through to export config |
src-tauri/src/services/clip_exporter.rs |
Use font, shadow, dimmed color, background toggle in ASS generation |
src/lib/components/CaptionSettingsPanel.svelte |
Add font dropdown, shadow controls, dimmed color controls, background toggle |
src/lib/components/VideoPlayer.svelte |
Use dimmed color settings + font in preview CSS |
src-tauri/src/commands/media_analysis.rs (or new file) |
Add list_system_fonts command |
src-tauri/src/lib.rs |
Register new command |
src/lib/bindings/mediaAnalysis.ts (or new binding) |
TS binding for list_system_fonts |