Files
filmcraft/crates/captions
Brandon ThomasandClaude Opus 5.5 b141c406e9 M10.1: text engine (crates/text): font database with bundled OFL fonts and system-font discovery, harfrust shaping, bidi, line breaking, paragraph layout, glyph cache and rasteriser; captions and Timecode/Clip Name burn-ins use it
- New L1 crate filmcraft-text: fonts (bundled Inter Regular/Medium/SemiBold/Bold/Italic,
  JetBrains Mono, Noto Serif; DirectorySource scans system font folders reading only name/OS2
  tables; family/style resolution with synthetic bold/italic; per-char fallback), layout
  (harfrust kerning/ligatures, unicode-bidi, unicode-linebreak, alignment incl. justify,
  leading, tracking, baseline shift, all/small caps, underline, carets/hit-test/selection,
  cached), raster (moved from captions; active-edge list, shapes, emboldening), render
  (outline + sub-pixel glyph-mask caches; transformed-outline path for rotation/skew),
  mask (distance-transform strokes, blur).
- Captions burn-in now shapes and kerns via the engine (font.rs/raster.rs removed).
- Timecode / Clip Name effects draw real text (full clip names, not seven-segment digits);
  text_burnin golden re-blessed.
- UI takes its font bytes from the text crate (no duplicate copies in the binary).
- New fonts: Inter Bold, Inter Italic (OFL-1.1, rsms/inter v4.1), Noto Serif Regular
  (OFL-1.1, notofonts) with sidecars, ATTRIBUTION.md rows and licence text.
- Perf: 3-line 96 px title at 1080p ~1.6 ms cold / 0.15 ms warm (release).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 01:22:30 -04:00
..

filmcraft-captions

Caption files and caption burn-in for FilmCraft (layer L2: depends on filmcraft-time, filmcraft-color, filmcraft-project and filmcraft-text).

The caption model (caption tracks in a sequence, captions, track style) lives in filmcraft-project (caption.rs) because it is part of the .fcproj document. This crate reads and writes caption files, converts them to and from caption tracks, and draws captions.

Formats

Format Read Write Notes
SubRip .srt yes yes BOM, UTF-16, Windows-1252 fallback, CRLF/CR, missing or wrong indexes, , or . milliseconds, 1–9 fraction digits, missing hours, SSA coordinates, cues not separated by blank lines. Inline tags are kept as text.
WebVTT .vtt yes yes Cue identifiers, cue settings (verbatim), a leading <v Speaker> voice span (as the caption's speaker) and STYLE / REGION / NOTE blocks are kept. A missing WEBVTT signature is tolerated.
Scenarist SCC .scc yes yes CEA-608 at 29.97 fps, drop-frame or not. Reads pop-on, roll-up and paint-on (channel 1); writes pop-on.

All cue times are exact Ticks. Milliseconds convert exactly (1 ms = 254 016 000 ticks); SCC frames map through FrameRate::FPS_29_97. Document::snap_to_frames snaps cues to a sequence's frame grid (the engine does this on import) and removes overlaps.

SCC writer

Each caption is sent as a pop-on load (RCL, ENM, then per row a preamble address code and tab offset for centring, then text; control codes doubled) into non-displayed memory, followed by End Of Caption exactly on the caption's first frame. The load is placed in the latest run of free frames before the caption, so back-to-back captions load while the previous one is on screen. An Erase Displayed Memory clears the caption at its out point unless the next caption replaces it. Text is wrapped at 32 columns, bottom-aligned (last row 15) and centred. Characters come from the 608 basic, special and extended sets (extended characters are preceded by a basic fallback character, as the standard requires); others are dropped. If there is no room to load a caption before its in point (for example a caption at 00:00:00:00), it appears as soon as it is loaded.

Burn-in

burn::render_caption lays out a caption with the track style (font size relative to a 1080-line frame, colour, background box, outline, alignment, top/middle/bottom anchor and margin; WebVTT line:N% and align: settings override them), wraps lines to 90% of the frame width and rasterises it to a small premultiplied linear-light RGBA overlay. filmcraft-render composites the overlays of visible caption tracks over the finished frame (Program monitor and export burn-in).

Text is set in Inter SemiBold (assets/fonts/Inter-SemiBold.ttf, SIL OFL 1.1, attributed in ATTRIBUTION.md) by the filmcraft-text engine: shaped with kerning and ligatures, bidi-ordered, and drawn from its sub-pixel positioned glyph cache.

Tests

  • Unit tests per module (timestamps, decoding, sloppy SRT, WebVTT blocks and voices, CEA-608 tables, PAC round trips, known SCC pop-on and roll-up streams, layout).
  • tests/roundtrip.rs: property tests — SRT (also with BOM + CRLF), WebVTT (ids, speakers, settings, STYLE blocks) and SCC (drop-frame and non-drop, gaps and back-to-back captions) round-trip exactly; readers never panic on random bytes; SRT → VTT → SCC keeps text and frames.