Commit Graph
15 Commits
Author SHA1 Message Date
Jonathan CardosoandBrandon Thomas 8ce79afd23 captions: SCC and MCC export name the characters they drop or replace (#4023) (#4036)
CEA-608 has no code for some characters (the ellipsis, CJK) and the SCC
and MCC writers dropped them, or sent a close basic-set one (’ as '),
without saying so. The CEA-708 service in MCC sent ? the same way, for
instance for an em dash.

charset_warnings lists each such character once, with how often and
the first caption that has it, using the writers' own tables, and
captions.export returns the list as warnings. The list is capped at
20 characters per stream plus one summary line.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-11-03 00:02:10 -05:00
Jonathan Cardoso a4bc8edd50 captions: TTML export writes the track language, import keeps it (#4025) (#4038)
TTML and DFXP exports always wrote xml:lang="en", whatever the caption
track's language. The document now carries the language: export takes
the track's, TTML import reads xml:lang (a language tag of at most 35
characters, else a warning), and captions.import takes an optional
language that wins over both.
2026-11-03 00:01:18 -05:00
aiongg f319ff9af3 Merge PR #3389: #3357: caption track font style 2026-10-31 02:13:13 +00:00
AbdullahandClaude Opus 5.5 25f3e9eade Captions: File ▸ Export ▸ Captions… asks for the file format (#3365) (#3523)
The menu item, and the Text panel's Export captions…, opens Caption Export
Settings with a File Format menu of every format captions.export writes. OK
opens the save panel with only that format's filter and a matching name. A
name typed with another caption format's extension is written in that format
(it is the file the save panel asked about); any other name gets the chosen
format's extension. If a file with that new name already exists, nothing is
written: with WebVTT chosen, typing "keep" when keep.vtt exists leaves
keep.vtt alone. With a path the command still exports directly.

Also fixes a panic: captions.export with params that are not an object
indexed into them.

Fixes #3365

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 01:22:42 -04:00
Alex PerraultandClaude Opus 5.5 1a7bc0602f #3357: caption track font style
Caption text was always the family's SemiBold: caption_style hard-coded
the style. CaptionStyle gains font_style (captions.setStyle `fontStyle`,
default "SemiBold", serde default so old projects load unchanged),
resolved like graphic text: the nearest weight when the family has no
face of that name, SemiBold when empty.

- render_caption uses it (Program monitor and burned-in export)
- captions.list reports it; the Text panel's Captions tab offers the
  family's styles next to the font
- Upgrade Caption to Graphic carries it to the text layer's font style;
  graphics.fonts.used lists it and file.replaceFonts matches and
  replaces it
- docs/captions.md, docs/graphics.md

The default keeps default_style_renders_like_the_reference green
(pixel-identical); font_style_is_used renders Regular and Bold against
SemiBold.

Fixes #3357

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:29:21 -07:00
561322b46d Text panel: the Captions list follows the playhead (#3042)
* Text panel: the Captions list follows the playhead

As the playhead reaches a caption, the Captions list scrolls it to the middle, so the list stays
lined up with the Timeline during playback and scrubbing. Each caption is brought into view once
(scrolling the list by hand still works), and never while a field in the panel has focus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move the Captions list follow test into the shared ui-egui test binary

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-24 10:24:03 -04:00
bd4139e430 Edit: Copy, Cut and Paste work on captions selected in the Timeline (#3041)
* Edit: Copy, Cut and Paste work on captions selected in the Timeline

With only captions selected, Edit ▸ Copy / Cut (⌘C / ⌘X) copy them to a caption clipboard,
and Paste / Paste Insert (⌘V / ⇧⌘V) place them at the playhead on the caption tracks they came
from (the last track when that one is gone), overwriting what is there; Paste Insert first pushes
later captions on by the copied span. The pasted captions are selected, the playhead moves past
them, and it is one undo step. Copying clips empties the caption clipboard and the other way
round, so Paste places whichever was copied last. Before, Copy did nothing with only captions
selected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move the caption copy/paste UI test into the shared ui-egui test binary

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-24 10:23:35 -04:00
964424ea8d Timeline: Option-drag duplicates captions (#3040)
* Timeline: Option-drag duplicates captions

Option-dragging a caption block leaves the original in place and drops a copy where it is
released; the cursor turns into a copy cursor and the original stays drawn under the copy while
dragging. A drag now carries the whole caption selection, not only the grabbed block.

New command `captions.duplicate` {captions, delta|deltaFrames}: copies on their own tracks,
never before 0, selected afterwards, one undo step. Captions never overlap, so
`edit::captions::overwrite_captions` places copies over what is there: captions under a copy are
trimmed, split around it or removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* captions.duplicate: refuse an empty caption list and copy each caption once; move its UI test into the shared ui-egui test binary

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-24 10:17:02 -04:00
a5c2a73cbd Timeline: the Razor tool cuts captions (#3039)
* Timeline: the Razor tool cuts captions

With the Razor tool (C), a click on a caption block in the Timeline splits it there, snapped like
a clip cut, with the same white preview line; Shift cuts every caption on an unlocked caption
track at that time. Before, the caption blocks took every click for select/move whatever the
tool, so the Razor did nothing on them. Locked caption tracks ignore it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move the caption Razor UI test into the shared ui-egui test binary

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-24 10:16:33 -04:00
seif cfe0c751e9 #395: Arabic and Hebrew in the interface: fallback fonts, captions in reading order
The interface had no face for Arabic or Hebrew, so caption text, track and media names showed
missing-glyph boxes in the Text panel and on the timeline while the Program monitor drew them.
crates/ui-egui/src/rtl.rs adds the craft-fonts Arab / Hebr faces, else one installed face per
script (Noto Sans Arabic, SF Arabic, Segoe UI...), as the last fallbacks of every UI font family,
as cjk.rs does for Chinese.

egui already shapes each font run with harfrust, so the letters join, but it lays runs out left to
right with no bidi pass and multi-word Arabic read backwards. rtl::Lines lays captions out in
reading order: lines are broken on the logical text as egui wraps it, each line is reordered with
unicode-bidi (UAX #9, as crates/text does for titles) and every right-to-left word is its own
layout section for egui's shaper. Caption blocks on the timeline and the Text panel caption list
use it; a caption being edited keeps egui's logical order, since TextEdit places the caret by
character index. Left-to-right text is laid out exactly as before.
2026-10-11 13:14:30 -06:00
lloydandClaude Opus 5.5 8175b16a47 captions: captions.list with a track that names no caption track is an error
`captions.list` resolved `track` with track_param and treated an
unresolved selector the same as an omitted one, so a missing numeric id
(or a label past the last track, such as `C3` with two tracks) returned
every caption track with success. It now fails with "no such caption
track", as captions.export, setTrack, setStyle, deleteTrack and add do.
Omitting `track` still lists every track, and valid ids and C-labels
still return just their track.

Test: two caption tracks; each id and each label returns only its own
track; a missing id, `C3`, `C0` and a non-label string are errors.

Fixes #545

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:02:57 +02:00
justjohn12345andClaude Opus 5.5 e13151d87b NEST10: the captions doc says nested captions are part of the nest's picture
docs/captions.md still said nested sequences do not burn in their own
captions. Since NEST10 the captions of a nested sequence are drawn wherever
the nest is shown, in the Program monitor and in exports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:53:53 -04:00
Brandon ThomasandClaude Opus 5.5 d90b9c8ee2 fix: document that the caption track margin is a fraction of the frame height
captions.setStyle {margin: 60} (pixels, as one would guess) was silently clamped to 0.45 and
put subtitles mid-frame. The parameter doc and docs/captions.md now give the unit and range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:18:06 -04:00
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
Brandon ThomasandClaude Opus 5.5 098dcc8a61 M10.4: caption UI — caption track rows above the video tracks (select, drag to move/trim, eye/lock headers), Text panel Captions tab (segment list with editable in/out/text, add/split/merge/delete/export, track picker, style strip), Burn Captions Into Video in Export mode, caption file dialogs; docs/captions.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:06:29 -04:00