Files
filmcraft/crates/interchange/README.md
T
aiongg 0a881266c8 CI: xtask ci in the dev profile, one test binary per crate, nextest (#2860)
* Tests: one integration-test binary per crate

Each crate with several tests/*.rs files keeps them as modules of tests/it/,
so cargo links one test executable per crate instead of one per file. Files
that change process-wide state or time a workload stay binaries of their own.

* Profiles: line tables for workspace crates, no debug info for dependencies

* Windows ARM64: nightly and on release pushes instead of every push to main

* xtask ci: clippy and tests in the dev profile

The release profile's thin LTO and single codegen unit made linking the test
binaries take most of the gate. The codec and audio crates stay at opt-level 3
in the dev profile, so their tests run at release speed.

* xtask ci: nextest, doctests, no examples, one wasm check

Tests run with cargo nextest when it is installed (cargo test otherwise) and
build with --lib --bins --tests, so examples aren't linked; doctests run
separately. The wasm check keeps going past the first failing crate. VP8
fixture generation locks across processes, since nextest runs each test in
its own.

* VP9 synthetic fixtures: write aside and rename

A test in another process could read a fixture ffmpeg was still writing.

* Fuzz tests: a third of each sweep by default, all of it with FILMCRAFT_FUZZ_ITERS

Every seed, mutation kind and thread count still runs. Header bytes each get
one overwrite value and two bit flips in rotation, so every value and bit
index still occurs across the region. FILMCRAFT_FUZZ_ITERS=N runs the whole
sweep plus N random rounds per seed, as before.

* Platform fallback tests: one failure point per hybrid path

The failure-anywhere test injected a failure at four points around every
restart point; the hybrid's paths differ only in the first GOP, around the
second and last restart points, at the end and never. The replay test needs
the first two GOPs.

* Export tests: shorter ranges with the same checks

The bitrate test measures 0.5–1.5 s, where each preset reaches its own
target (on 0–3 s the simple demo left two presets at the same rate). The
every-preset test exports three frames per preset.

* Audio tests: effects in parallel, a table-driven FFT for the Opus quality metric

The extreme-settings test keeps both settings and the 40 s tail for every
effect, one thread each. The Opus quality metric's FFT builds its twiddles
once and allocates nothing per transform (same algorithm and summation order).

* CI: dev-profile gate with nextest

xtask ci no longer builds with --release, so the release-profile overrides
go; nextest is installed for the test step.

* CI: apt packages through the cached install-apt-packages action

* Review fixes: fuzz tests with a panic hook in their own binaries, loud fixture lock

The fuzz tests of av1, h264, hevc, mpeg2v, vp8 and vp9 count panics through
a process-wide hook, so a panic in another test of the same process would
fail them; they are binaries of their own again. The VP8 fixture lock fails
the test instead of skipping it silently, and the full-sweep doc comments say
how many truncation points the full run samples.

* Fuzz tests: rotate the default subset per run (FILMCRAFT_FUZZ_SEED replays one)

* platform tests: decode-switch tests in their own binaries, one NVENC lock
2026-10-23 13:34:16 -04:00

7.7 KiB

filmcraft-interchange

Timeline interchange for FilmCraft: CMX 3600 EDL, Final Cut Pro 7 XML (xmeml), FCPXML, OpenTimelineIO, AAF and OMF import and export, plus Avid ALE. Layer L2: no file I/O; media references are strings and audio essence is supplied by the caller (the engine).

Specifications

Clean-room: written from public specifications only. The AAF SDK, pyaaf2, the OMF Toolkit and other implementations were not consulted. Where a specification leaves a layout open (how a nested sequence is written, how several video tracks share a slot), what Premiere Pro does was read off files it exports, never from the application itself.

Format Document Edition Used for
AAF AMWA AAF Object Specification v1.1 (2005) classes, properties (ids shared with SMPTE ST 377-1 local tags), mob / slot / segment model, sequences and transitions, operation groups, parameters, definitions, descriptors, locators, essence data
AAF AMWA AAF Low-Level Container Specification v1.0.1 objects as structured storages, properties streams, stored forms, strong / weak reference collections and their index streams, referenced properties
AAF AMWA AAF Edit Protocol v1.0 (AMWA AS-01) top-level composition, mob chains (composition → master → file → physical source), operation definitions (dissolve, fade to black, audio gain / dissolve), usage codes
AAF SMPTE RP 224 / RP 210 registers — data definition, class and type labels
AAF Microsoft [MS-CFB] rev. 10.0 the container, see filmcraft-cfb
OMF Avid OMF Interchange Specification Version 2.0 (1997) classes (HEAD, CMOB, MMOB, SMOB, MSLT, TRKD, SEQU, SCLP, FILL, TRAN, EFFE, ESLT, CVAL, VVAL, TCCP, WAVD, AIFD, WAVE, AIFC, locators), property and type names
OMF Apple Bento Specification revision 1.0d5 container label, TOC encoding, objects / properties / types, references
WAVE / AIFF Microsoft RIFF WAVE; Apple AIFF 1.3 — embedded and separate audio files

The other formats' editions are listed in the module docs (edl, fcp7, fcpxml, otio, ale).

Invariant — Unicode media URLs: file URL prefix probes must not panic when their byte boundary falls inside a UTF-8 character. Timeline importers use the shared converter; tests/it/file_urls.rs checks expected Unicode paths through the public converter, resolver and EDL importer.

AAF and OMF

comp holds a format-neutral mob-style model (compositions of slots whose sequences of fillers, source clips and overlapping transitions reference media through master and file source mobs). aaf and omf serialise it; both import back into the same model and from there into FilmCraft sequences and media. Mapping details (what each FilmCraft feature becomes) are in the aaf and omf module docs. Times are kept in ticks in the model; compositions use the sequence frame rate for picture and the sample rate for sound slots, so audio edits are sample-exact.

Embedded / consolidated audio (essence): audio_needs lists the media ranges an export references (per media item or per clip, with handles); the engine decodes or renders them and passes AudioEssence (embedded PCM or a written file) back in MediaOptions.

Not represented: speed changes and frame holds (exported at 100 % with a report entry), graphics and synthetic media (gaps), video effects other than transitions, clip markers (written to the master mob, so they come back as media markers), OMF video and markers.

Nested sequences

For the formats Premiere Pro exports (FCP7 XML, OTIO, EDL, AAF, OMF) a nested sequence is written the way Premiere Pro 26.5.2 writes it, as seen in the files it exports for a sequence with a nest. Premiere Pro does not write FCPXML.

Format Written as On import into FilmCraft
FCP7 XML a clip item holding the nested <sequence> (by id after the first use) a sequence the clips use
FCPXML a ref-clip to a media resource holding the sequence a sequence the clips use
OTIO a Stack inside the track a sequence the clips use
EDL one event: reel AX in every reel mode, the nested sequence's name as the clip name, its own time as source timecode (the report says the nest's edit is not in the EDL) an ordinary clip of that name
AAF a composition mob of its own (not tagged top-level); the nest's clips are source clips that point at it, at its first track of their kind. With embedded or consolidated audio the media inside the nest is prepared too (NestNeeds::Inside) a sequence the clips use, read once however many clips use it
OMF the nested sequence's sound, mixed by the engine with what is on the clip (NestNeeds::Render), as one clip named after the sequence. Without that essence: a gap, and the report names the sequence media in the document

A sequence that claims to be inside itself (a damaged project or file) is a gap with a report entry in both directions; nothing recurses without a bound.

The AAF reader also accepts Premiere Pro's layout of a composition: all video tracks in ONE slot (a nested scope with a segment per track, lowest first), and "top-level" tagged on nested compositions too (the top-level ones are those no other composition uses).

Graphics and adjustment layers

No format here has an equivalent of a FilmCraft graphic (title) clip or an adjustment layer, and none of the exports brings one back. Each such clip is named in the export Report as a warning (graphic clip "Title" at frame 48 …, one line per clip), with what was written instead:

Format Written as On import into FilmCraft
FCP7 XML a clip item without media (its layers as FilmCraft filter ids) not read back; the import report names the skipped clip item
FCPXML a clip without media not read back
OTIO a clip with a MissingReference (effects in the filmcraft metadata) offline media
EDL an ordinary event with the reel the reel mode gives an ordinary clip
AAF a gap nothing

OMF carries no video at all.

Tests

  • tests/it/aaf_omf.rs: AAF round trips at 25, 29.97 DF, 23.976 and 59.94 DF (clips, gaps, two-sided and one-sided transitions, links, markers, start timecodes, constant and keyframed gain, media markers and timecode); 512-byte sectors; breakout to mono; embedded trimmed audio (sample data and source offsets); separate consolidated files with a video mixdown; OMF round trips with embedded audio, separate AIFF files and breakout; empty sequences; truncation and random corruption never panic. Nested sequences: AAF round trips as compositions (nests in nests, a nest used twice, another frame and sample rate, breakout to mono), OMF with the rendered sound, the audio needs of nests, a sequence inside itself.
  • tests/it/uncarried_clips.rs: every format's export report names each graphic clip and adjustment layer once, as a warning; a sequence without them reports nothing; what a re-import gives back matches the report; the FCP7 XML import names a clip item whose file is not defined.
  • src/aaf/tests.rs: written files checked against the required properties of every class written (Header, Identification, Mobs, slots, components, descriptors), weak references resolving into the dictionary, source clips resolving to mobs and slots, the Edit Protocol transition rules and sequence length arithmetic; every stored form round-trips through the container; a file rewritten into Premiere Pro's layout (video tracks as layers of one slot, nested compositions tagged top-level) reads back as the same edit.
  • src/omf/tests.rs: the Bento label and TOC, the required properties of every OMF class written, reference resolution, embedded WAVE data, sequence lengths in samples.