wai: timed text and live captions, wai.text.timed (L8) #303
Loading…
Reference in a new issue
No description provided.
Delete branch "wai/timed-text"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
L8: timed text and live captions (
wai.text.timed)This PR adds a spec, a reference implementation, a conformance corpus and an independent verifier. It does not change live-events.
What it adds
wai/extensions/timed-text.mdregisters the recordwai.text.timed. It contains:captionevent, unchanged.captionevent, followed by ametaevent whose payload is theWTX1annotation. The annotation holds: the digest of the revision it supersedes, partial or final,stable_cp, the anchor, and the italic ranges.annotation_malformed,annotation_misplaced,supersede_unknown,supersede_final,supersede_forked,supersede_mismatch,stability_broken,text_not_in_subset.not_final,duration_unknown).X-TIMESTAMP-MAP. The map is re-anchored in every segment, so a 33-bit wrap stays exact. There is also a reader of the subset.draft-wilaw-moq-webvtt-msf-00; the IMSC1 timeline (cue mode) followsdraft-law-moq-imsc1-msf-00. Records are written byte for byte.wai_machine_generatedfield.public.machine-generatedonSUBTITLESandCLOSED-CAPTIONS;c2pa.ai-disclosure, one assertion per model, plus the IPTC digital source type;<c.wai-machine.wai-model-HEX>;wai:originandwai:modelattributes;EXT-X-SESSION-DATA, for targets that cannot carry the label. A target with no carrier must still publish the sidecar; the label is never dropped silently.wai/wai-rs/src/timed_text.rsandtimed_text/cc608.rs, with the generator intimed_text/corpus.rs:timed_text = ["live_events"];cbindgen:ignore;wai_timed_text_vectors(gen/verify) andtests/timed_text.rs, declared withrequired-features. The test checks that:Reason::ALL.wai/live-conformance/captions/:vectors.jsonplus 39 expected outputs (.vtt,.segK.vtt,.ttml,.608.hex), and a README with the provenance line. It holds:malformed_payloadfor a machine caption with no model digest;The 608 files contain every code path: indent and italics preamble address codes, TO1, TO2 and TO3, both mid-row codes, special characters, extended characters from both tables, RCL, ENM, EOC, EDM, CR, RU2, RU3 and RU4. Every reason in §12 refuses at least one case.
wai/live-conformance/timed_text_verify.pyuses the standard library only and runs with-I.live_events_verify.py.xml.etreeagainst §6.3 and runs the HRM check.CI and registry:
extensions/timed-text.mdadded to both path lists;registry.rs:CAP_TEXT_TIMEDas a record, and wire identifiersWTX1,wai_origin,wai_model,wai_machine_generated, the twotag:URIs, and theDATA-ID;wai registry exportre-run;int_kernels_vectorsreason updated to "live events, rooms and takes, and captions: …".Implemented, and specified only
EXT-X-MEDIAandEXT-X-SESSION-DATA, the C2PA statement and digital source type, and the sidecar.Where the HLS machine-generated characteristic is defined
public.machine-generatedis defined indraft-pantos-hls-rfc8216bis-22§4.4.6.1 (EXT-X-MEDIA,CHARACTERISTICS): "Any Rendition MAY include the "public.machine-generated" characteristic to indicate the Rendition was authored or translated programmatically." The spec cites the IETF draft directly, so no vendor document is needed. Revision -22 is the latest; datatracker shows rev 22. The draft defines it per rendition, so per-cue granularity comes from the in-segment forms and the sidecar.Also verified at the source:
c2pa.ai-disclosure, itsmodelType(Table 12), and the §18.28.3 pairing of digital source type withhumanOversightLevel;Sources and what is unchecked
draft-wilaw-moq-webvtt-msf-00,draft-law-moq-imsc1-msf-00,draft-ietf-moq-msf-01;draft-pantos-hls-rfc8216bis-22;draft-wilaw-moq-webvtt-msf-00cites MSF sections (§11, §5.3.x) that do not matchdraft-ietf-moq-msf-01(§8, §5.2.x). The spec notes this and cites -01's own numbers.Design choices to review
wai.text.timedunder thewai.text.prefix, even though it is a record.captionpayload has no supersede field, and appending one would break its reader. So the annotation rides inmeta, and is bound to its caption by being the next seq with the samet. It is not bound by a field. Revisions supersede by caption digest. The spec notes that a later live-events revision may fold these fields intocaption.tof a revision is when it is shown.duration_mscounts fromt. A resolved cue runs from its first revision'stto its final'stplus duration. Partials never reach documents, timelines or 608, because none of those can replace a cue in place. Live HLS segments use the cues final at cut time.human_validated, which pairs withcompositeWithTrainedAlgorithmicMedia. A mix of origins maps tocompositeSynthetic.modelIdentifieristag:transaction.science,2026:wai/model/<hex>, because live-events does not name the model digest's algorithm, so anni:URI cannot be formed.Ren(0.6) andGCpy(3) for every glyph, empties the glyph cache at empty ISDs, and works in integer units of 1/2700 s. It may refuse a document that conforms; it never passes one that does not. This avoids needing Unicode Script tables.ttcarriesttp:profile="http://www.w3.org/ns/ttml/profile/imsc1/text", which IMSC 1.0.1 §6.9 says SHOULD be present. 1.0.1 is the IMSC1 the HLS draft names, and these documents are neither EBU-TT-D nor SDP-US, so that edition's exceptions do not apply. IMSC 1.3's feature table permits#profile.ebuttm:conformsToStandardelements stay (the imsc1 and imsc1.3 text designators). IMSC 1.3 §8.10.2 specifies that form, and §6.3.2's override reads it.ttp:profileelement is written.ttp:contentProfilesis still absent, following IMSC 1.3 §8.10.1's note for documents meant for TTML1-based profiles.imsc_structurein the verifier now checks the attribute, the absence of the element, and the absence of any Image designator. A new mutated copy, withttp:profileremoved, fails.t.style_not_expressible;wai_origin/wai_modelare members the IMSC1 MoQ draft does not define. The catalog field and the sidecar back them up.CHARACTERISTICSon aCLOSED-CAPTIONStag. The HLS draft says that tag names a channel rather than a rendition; the spec says so and carries the characteristic there anyway.rbrunsAll ran on the build host through
~/kani-logs/remote/rb /Users/dcharlot/data-share/vibe-coding/_wt-timed-text -- '…'. The set was run first at053bb285, and again at head06f006bfafter thettp:profilechange. Each exit status is 0 at both heads:cargo test --no-default-features --features timed_text --lib timed_text::(13 passed)cargo test --no-default-features --features timed_text --test timed_text(4 passed)cargo run -q --no-default-features --features timed_text --bin wai_timed_text_vectors -- verify ../live-conformance/captionstouch cbindgen.toml, thengit diff --exit-code --stat include/wai.h. The header is unchanged after build.rs re-ran.cargo test --no-default-features --lib codecs::registry(14 passed)cargo run -q --no-default-features --bin wai -- registry export --checkcargo test --no-default-features --features live_events --lib live_events::and--test live_eventscargo test --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int,generate,score,staged,stage_measure,legacy_int --test int_kernels_vectors(8 passed). These are the features of the cargo-class corpora job.python3 -I live-conformance/timed_text_verify.py live-conformance/captions(all vectors pass; 20 of 20 mutated copies fail)python3 -I live-conformance/live_events_verify.py live-conformance/eventsThe corpus and the registry export were generated with
rb --pull … wai_timed_text_vectors genandwai registry export. The corpus was regenerated at06f006bf; only the six.ttmlfiles changed.Clippy:
cargo clippy --no-default-features --features timed_text --lib --tests --bins -- -D warningsreports nothing in this PR's files after the lint fixes. It still exits 101, on 36 findings in modules this PR does not touch (int_payload/wire.rs,container.rs,quality.rs,codecs/glossary_check.rs,world/*,sig.rs,pin.rs,hls_render.rs).Local checks, all clean:
check-tests-in-ci.py,check-spec-refs.py,check-wai-section-refs.py,check-no-vanity-metrics.sh,check-comparative-prose.sh,check-orphan-sources.py.Merge notes
#296 (
wai/live-compose) and #299 (wai/live-record) also touch SPEC §5, REGISTRY.md, the CHANGELOG,wai-conformance.yml,registry.rs, the registry export and thelive-conformanceexclusion line intests/int_kernels_vectors.rs. This PR's edits there are additive (new lines, new list items). The exclusion line is a single line: whichever PR lands second should merge the reason to read "live events, rooms and takes, compositions, and captions". After rebasing, the export should be regenerated (wai registry export).🤖 Generated with Claude Code