WAI Extension: Access Services
Mirrored from the canonical text at commit b1681667 ().
Status: Draft. Registers the record
wai.access.services: the access services of a room session, and figures about them that any verifier recomputes from signed records. Captions are timed-text’s, unchanged. This extension adds a quality figure for a caption track: its latency, the room-clock instant a cue was first shown less the capture instant of the speech it carries; its stability, the revisions after first display and the words they changed; and its accuracy, the word errors of the first revision shown against a reviewed final revision or a signed reference transcript. Each is defined in integer arithmetic over the signed revisions, so two verifiers reach the same numbers, and a figure a vendor states is checked by recomputing it. Audio description is a signed description track, a script of timed descriptions with their mixing instructions (the programme audio ducked under each) and their voicing, a separate audio track or a voice the sink synthesizes, each labelled human or machine; it maps onto a document of the Dubbing and Audio description Profiles of TTML2. Sign language is a signing track, awai.avatar.posestream or the video of a person signing, whose objects are bound by digest to the caption revisions they translate, with a reviewer’s optional sign-off. A completeness claim states, for a room session, that each access track it declares was delivered complete and in sync, measured from signed times against the tolerances the texts below state; a verifier checks it against the records. No new transport. The reference implementation is theaccess_servicesmodule ofwai-rs(featureaccess_services); the corpus islive-conformance/access/, and its second implementation islive-conformance/access_services_verify.py. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.Texts read for this revision, each pinned to the version named: Directive (EU) 2019/882, Annex I, Section IV, point (b)(ii), and Article 31(2), from a reproduction of the text as adopted (the Official Journal could not be fetched for this revision); EN 301 549 V4.1.1 (2026-09), clauses 4.2.4, 6.5.2, 6.5.3, 7.1.2, 7.1.5, 7.2.1 to 7.2.3, 7.3, 12.4 and 12.5; Web Content Accessibility Guidelines (WCAG) 2.2, Success Criteria 1.2.2 to 1.2.7; 47 CFR 79.1(j)(2), (j)(3) and (k)(2), and 47 CFR 79.3(a)(3), as in force on 2026-10-01; Dubbing and Audio description Profiles of TTML2 (DAPT), W3C Candidate Recommendation Draft of 2026-06-26 (
CRD-dapt-20260626), §4.1 to §4.10, §5.2, §5.3, §5.5 to §5.7 and Appendix H.2.2; EBU Tech 3370, EBU-TT Part 3, version 1.0 (May 2017), §2.3.2 and §2.3.3; and two statements of the United Kingdom’s communications regulator, Measuring the quality of live subtitling (16 October 2013), §1.3, §3.65 to §3.67 and footnote 21, and Ensuring the quality of TV and on-demand services (15 April 2024), §3.3, §5.17, §5.23, §5.25, §5.29, §6.2 and §6.14. A section number of one of those texts in this extension is that version’s, and is written with the text’s name; a bare section number is this extension’s. DAPT is a Candidate Recommendation Draft, whose features may change before it is a Recommendation, and one that §5.5 uses is at risk there.
1. Scope
In scope: the records and their encoding (§2); words, and the alignment of two lists of words (§3); the quality figure of a caption track: the sources that place its words on the room clock, a reference transcript, latency, stability, accuracy, and the figure record (§4); audio description: the description record, its script, mixing and voicing, its synchronisation, its DAPT document, and what a player owes its listeners (§5); sign language: the signing record, its binding to caption revisions, and a review (§6); the completeness claim (§7); verification (§8); and what each figure measures in the texts above (§9).
Out of scope: a transport; recognising speech, writing descriptions, translating into a sign language and synthesizing speech, which produce the content; grading the severity of an error, which needs a person (§9); decoding a voicing track or a signing track, whose objects this extension names by digest; spoken subtitles and extended audio description, which pause or lengthen the programme; how a sink renders a description or a signer; and what any law requires.
Relationship to the core spec: wai.access.services is a record (SPEC
§5): a signed record a WAI tool emits and verifies. It names no payload format and is not
dispatchable.
Relationship to timed-text: captions are its live captions, verified as its §4.3 verifies them, and this extension changes nothing in them. The audio description that timed-text §1 leaves out of its scope is this extension’s §5.
Relationship to avatars and capture-binding: a signing
track in pose form is a wai.avatar.pose world, whose op batches are its objects (avatars
§5); a source on a take is placed on the room clock by the take’s clock mapping
(capture-binding §9.3).
Relationship to synthesis: the origins this extension’s records state are a
caption’s, which synthesis §1 maps onto its classes. A description voiced or written by a
model, and a signing a model generates, is synthesized media in its sense: class
synthesized, step generate, with the operation speech-synthesis for a voice, and
oversight fully_autonomous for origin machine or human_validated for origin
machine-reviewed (synthesis §3.1, §3.2). The publisher of such a track signs its origin
claim there; this extension’s label is the same statement, carried where a description or a
signing is read. A review of §6.4 reviews a translation against caption revisions; a review
of one exact reconstruction of a generated track, which every exact sink then shows, is
synthesis §9.1’s.
Duties this extension supports: the access services of Directive (EU) 2019/882, Annex I, Section IV(b)(ii) (“subtitles for the deaf and hard of hearing, audio description, spoken subtitles and sign language interpretation … fully transmitted with adequate quality for accurate display, and synchronised with sound and video, while allowing for user control of their display and use”); EN 301 549 V4.1.1 clauses 7.2.1 to 7.2.3, 7.3 and 12.4, beside the caption clauses timed-text §11 answers; WCAG 2.2 Success Criteria 1.2.3, 1.2.5 and 1.2.6, beside the caption criteria 1.2.2 and 1.2.4; and the caption quality standards of 47 CFR 79.1(j). WAI states what its records carry and what a verifier checks. It makes no statement about any regime, and a deployment confirms what a regime asks of it against that regime’s text.
2. Records
Every record of this extension is a JSON object (RFC 8259), read as
jwp-receipts §3.1 step 1 reads a claim: RFC 8259’s grammar, no byte-order
mark, no member named twice in one object, no \u escape that leaves a surrogate unpaired,
and at most 32 levels of nesting. Its values use the encodings of jwp-receipts §2.4.3: byte
strings in lowercase hexadecimal; integers unsigned, at most 2^53 − 1, in plain decimal; no
other number and no boolean. The types in this extension’s tables are:
hex32,hex64: 64 or 128 lowercase hexadecimal digits;int: such an integer;sint: a signed integer, written as a JSON string:0, or an optional-then a digit 1 to 9 then any digits, whose value lies in −2^63 to 2^63 − 1;string: a JSON string;tag: a string that live-events §4.10 reads as a language tag (checked by the rules of the record’s section);- a list of quoted values: a string equal to one of them;
object,array: as the table under it says;null, written where a member may be null.
A record has exactly the members its table lists, at every level, none missing and none
added, each of its type, and a kind that names it. One that is not JSON, or does not have
that shape, is record_malformed.
Every record carries signer_pubkey (hex32, the Ed25519 key of RFC 8032 that signs it) and
sig (hex64):
sig = Ed25519(signer_key, "wai:access\x01" || JCS(record without "sig"))
record id = SHA-256(JCS(record))
JCS is RFC 8785, which on these values reduces to what jwp-receipts §2.4.3 states. The
signature is verified strictly (SPEC §7 Signatures): a key that fails step 1
or 2 is bad_key, and a signature that fails a later step bad_signature. A record is named
by its record id wherever another names it. A member room names the room by its id
(live-events §2); a record whose room is not the verifier’s room is wrong_room.
Which signers a verifier trusts for each kind of record is its policy. This extension checks what each record states against the events and the other records; a figure’s weight comes from its recomputation (§4.7), not from its signer.
3. Words and their alignment
3.1 Words
The words of a text are found in two steps:
- The text is split at every U+0020 and U+000A, and empty pieces are dropped.
- In each piece, every code point from U+0041 to U+005A is replaced by the one 0x20 above it (ASCII letters to lower case), and code points of the set P are removed from its start and its end, repeatedly, until it neither starts nor ends with one. A piece left empty is dropped; the rest are the words, in order.
P is U+0021 !, U+0022 ", U+0027 ', U+0028 (, U+0029 ), U+002C ,, U+002D -,
U+002E ., U+003A :, U+003B ;, U+003F ?, U+005B [, U+005D ], U+00A1 ¡, U+00AB
«, U+00BB », U+00BF ¿, U+2013 –, U+2014 —, U+2018 ‘, U+2019 ’, U+201C “,
U+201D ” and U+2026 ….
No other normalisation is made: letters outside ASCII keep their case, and two words are equal when their code points are. The words so found ignore the case of ASCII letters and the punctuation at a word’s edges, so an error of capitalisation or of such punctuation is not a word error here (§9).
3.2 Alignment
The alignment of a hypothesis H (words h₁ … hₘ) to a reference R (words r₁ … rₙ) is the table D of integers, for 0 ≤ i ≤ m and 0 ≤ j ≤ n:
- D[0][j] = j, and D[i][0] = i;
- D[i][j] = the least of D[i − 1][j − 1] + c, D[i − 1][j] + 1 and D[i][j − 1] + 1, where c is 0 when hᵢ = rⱼ and 1 otherwise.
Its end is a column j*:
- a full alignment ends at j* = n;
- a prefix alignment ends at the greatest j for which D[m][j] is the least value in row m: the reference is read as far as the hypothesis reaches, and no further.
Its errors are E = D[m][j*] and its reference words N = j*. They are split into substitutions, deletions and insertions by walking back from (m, j*) to (0, 0), taking at each step the first of these that holds:
- i > 0, j > 0 and D[i][j] = D[i − 1][j − 1] + c: to (i − 1, j − 1), a substitution when c is 1;
- i > 0 and D[i][j] = D[i − 1][j] + 1: to (i − 1, j), an insertion (a hypothesis word the reference does not have);
- otherwise: to (i, j − 1), a deletion (a reference word the hypothesis does not have).
The substitutions, deletions and insertions add up to E.
4. Caption quality
4.1 The caption track and its cues
A caption track is the caption events of one principal P in a room’s stream, verified
as timed-text §4.3 verifies them. Its cues are the chains of its
revisions (timed-text §2): each from its first revision r₀ to its last rₖ. A cue is named
by the digest of r₀’s caption event (live-events §3.2).
P’s captions are whole when P has at least one cue, the verifier holds every seq of
P from 0 to the last it holds (no delivery gap of P, live-events §6.2), and, for every
cue, rₖ is final and its annotation is not unknown (timed-text §4.3). They are
resolved when they are whole and every rₖ has a duration_ms above 0, so that each cue
resolves (timed-text §4.5). A figure is computed only over whole captions.
The events digest of P is SHA-256 over the digests of P’s caption events the
verifier holds, 32 bytes each, in seq order.
4.2 Sources
A sources record places the words of each cue on the room clock: where the speech the cue carries was captured.
| member | type | meaning |
|---|---|---|
kind | "wai-caption-sources" | |
room | hex32 | the room |
principal | hex32 | P, whose cues it places |
sources | array | one entry per cue it places, each an object below |
signer_pubkey, sig | §2 |
| member of an entry | type | meaning |
|---|---|---|
cue | hex32 | the cue, by the digest of its first revision |
basis | "take", "room" | what start and end are measured on |
take | hex32 or null | for take, the take id (capture-binding §3.2); null for room |
start, end | int | the capture of the cue’s first word and of its last: device-clock microseconds of the take, or room-clock microseconds |
Its signer is whoever aligned the words to the media: the captioner, or anyone holding the
media afterwards. The alignment of a word to the media is the signer’s statement; the
media’s own time is not. On the basis take, the instants are positions in the master of a
take, and the take’s clock mapping places them on the room clock: the offset o of the
take’s opening commitment (capture-binding §9.3), which the capturing device signed while it
captured. A source instant d maps to the room-clock instant d + o. On the basis
room, the instants are on the room clock as stated.
Rules, in order:
roomis the verifier’s: otherwisewrong_room.- No sources record of P comes before it in the order given: otherwise
record_conflict. - Each entry:
takeis ahex32exactly whenbasisistake, andstart≤end; no cue is named twice: otherwiserecord_malformed. - P’s captions are whole (§4.1): otherwise
stream_incomplete. - Each entry’s
cuenames a cue of P’s captions: otherwisesource_unknown. - Each entry on the basis
take: among the events the verifier accepted there is atake_commitevent whose payload capture-binding §5.2 reads, whosetakeis the entry’s take, and which is an opening commitment (n0,phase1, capture-binding §5.3); the first such in stream order is the take’s opening commitment, its author A and its offset o. The take is derived: an acceptedcontrolevent whose command isrecord_startand whosetargetis A has a digest s for which SHA-256 ofwai:capture-take, 0x01, the room id, A and s is the take (capture-binding §3.2). Andstart+ o is not below 0. Otherwisesource_take_unknown.
P’s sources record is the first sources record of P in the order given, and its
reference record the first reference record (§4.3); a later one of either is
record_conflict. Who may start a take, and which device captures for which principal, are
live-rooms’ and capture-binding’s checks; this extension uses the take’s mapping as
capture-binding §9.3 defines it, and its bound, J, holds where a take verifier gives the
take single-take and aligned (capture-binding §9.4, §10).
4.3 The reference transcript
A reference record gives, for each cue of P, the text a reviewer holds correct.
| member | type | meaning |
|---|---|---|
kind | "wai-caption-reference" | |
room | hex32 | the room |
principal | hex32 | P |
entries | array | one per cue, each {"cue": hex32, "text": string} |
signer_pubkey, sig | §2 |
Rules, in order: room is the verifier’s (wrong_room); no reference record of P comes
before it in the order given (record_conflict); no cue is named twice (record_malformed);
each text meets timed-text §3.2 rules 1 to 3 (text_not_in_subset); P’s captions are whole
(stream_incomplete); each entry names a cue of P (reference_unknown); and every cue of
P has an entry (reference_incomplete).
4.4 Latency
The latency of a cue that a sources entry places is L = t(r₀) − S, in microseconds,
where t(r₀) is the room-clock instant its first revision was shown from (timed-text
§4.1) and S is its entry’s start on the room clock (§4.2). L is negative when the
caption was shown before the speech began.
Over the cues of P that the sources record places, n of them, with their latencies in ascending order L₁ ≤ … ≤ Lₙ:
min= L₁,max= Lₙ;mean= ⌊(L₁ + … + Lₙ) / n⌋, rounded toward negative infinity;p50andp95: the latency at rank ⌈50 × n / 100⌉ and ⌈95 × n / 100⌉, counting from 1.
Each is null when n is 0. The class of the latency is none when n is 0;
otherwise capture when every entry is on the basis take, and stated when any is on the
basis room.
4.5 Stability
For one cue, its revisions are k, the revisions after the first, and its words changed the sum, over each revision rᵢ and the one that supersedes it rᵢ₊₁, of the substitutions and insertions of the full alignment of the words of rᵢ (the hypothesis) to the words of rᵢ₊₁ (the reference): the words a viewer saw that the next revision did not keep. A word added at the end, as a partial grows, is a deletion there and is not counted.
The track’s figures are the sums over its cues of revisions and of words changed, and
cues_corrected, the number of cues whose words changed is above 0.
4.6 Accuracy
The reference of a cue is its entry’s text in P’s reference record, when P has one; otherwise the text of rₖ, the cue’s final revision. The class of the accuracy is:
transcriptwhen P has a reference record;reviewedwhen it has none and every cue’s rₖ has origin 1 (human) or 3 (machine-reviewed): a person wrote or reviewed the reference;selfotherwise: the reference is the machine’s own final text, and the figure measures how far its first display was from its own last.
Two figures, each the sums over the cues of the counts of §3.2:
first: the prefix alignment of the words of r₀ to the words of the reference. It counts the errors in what the viewer first saw, against as much of the reference as that revision reaches, so the words a partial has not reached yet are not errors.final: the full alignment of the words of rₖ to the words of the reference, when the class istranscript;nullotherwise.
Each is {"words", "errors", "substitutions", "deletions", "insertions"}: N, E and its
three parts.
4.7 The figure
A quality record states the figures of P’s track.
| member | type | meaning |
|---|---|---|
kind | "wai-caption-quality" | |
room | hex32 | the room |
principal | hex32 | P |
events | hex32 | P’s events digest (§4.1) |
sources | hex32 or null | the record id of P’s sources record, or null when there is none |
reference | hex32 or null | likewise, of its reference record |
cues | int | the number of P’s cues |
latency | object | {"class", "n", "min", "max", "mean", "p50", "p95"}: a string of §4.4, an int, and five sint or null |
stability | object | {"revisions", "words_changed", "cues_corrected"}, each an int |
accuracy | object | {"class", "first", "final"}: a string of §4.6, an object of §4.6, and one or null |
signer_pubkey, sig | §2 |
Rules, in order:
roomis the verifier’s: otherwisewrong_room.- P’s captions are whole (§4.1): otherwise
stream_incomplete. events,sourcesandreferenceare as the table says: otherwisefigure_inputs_mismatch.- Every other member but
kind,signer_pubkeyandsigequals the figure the verifier computes from §4.4 to §4.6: otherwisefigure_mismatch.
A figure that passes is the figure of exactly those revisions, placed by exactly those
sources and measured against exactly that reference. A verifier needs no record of its own to
compute a figure: the figure of a whole track is the object a quality record would carry,
without kind, signer_pubkey and sig.
5. Audio description
5.1 The description record
A description record is an audio description track: a script of timed descriptions of what is seen, the mixing of each into the programme audio, and its voicing. Times are media time in milliseconds, on the timeline of the media the descriptions accompany, as timed-text §2 defines it.
| member | type | meaning |
|---|---|---|
kind | "wai-description" | |
lang | tag | the language of the descriptions |
script | object | {"origin", "model"}: who wrote the descriptions |
voicing | object | {"form", "origin", "model", "track"}: who or what speaks them |
events | array | the descriptions, each an object below |
signer_pubkey, sig | §2 |
origin is "human", "machine" or "machine-reviewed", the names timed-text §10.5 gives
the origins of a caption, and model is a hex32 naming the model that wrote or spoke the
text, or null. form is "track", the voicing is a separate audio track named by track
(a hex32, the track’s digest, live-rooms §6.2), or "sink", the sink synthesizes the
voice from the text with the model model, and track is null.
| member of an event | type | meaning |
|---|---|---|
id | string | its identifier |
begin, end | int | the interval it describes, the description’s time slot |
represents | "visual", "visual.nonText", "visual.text", "visual.text.title", "visual.text.credit", "visual.text.location", "visual.dialogue" | what of the image it describes: DAPT’s content descriptors of the visual image (DAPT §4.7 and Appendix H.2.2) |
text | string | the description |
duck | object | {"gain", "ramp"}, each an int: the programme audio’s gain under the description in thousandths, and the milliseconds it takes to fall to it and to rise back |
voice | object or null | {"begin", "end"}, each an int: where the voicing track speaks it; null when the form is sink, or when the track has not voiced it |
5.2 Rules
In order; the first that fails names the refusal:
langreads as live-events §4.10 reads a tag: otherwisedescription_malformed.script.modelis ahex32exactly whenscript.originismachineormachine-reviewed; likewisevoicing.modelforvoicing.origin;voicing.trackis ahex32exactly whenformistrack; and whenformissink,voicing.originis nothuman: otherwisedescription_malformed.- There is at least one event; each
idis one ofA–Z,a–zor_, then up to 63 of those,0–9,.and-; noidtwice; eachbegin<end≤ 359 999 999; each event’sbeginis at or after theendof the event before it (one voice describes one thing at a time): otherwisedescription_malformed. - Each
textmeets timed-text §3.2 rules 1 to 3: otherwisetext_not_in_subset. - Each
duck:gain≤ 1000;rampis 0 whengainis 1000 and above 0 otherwise; and 2 ×ramp≤end−begin. Eachvoice:nullwhen the form issink, and otherwisenullor within its event, the event’sbegin≤voice.begin<voice.end≤ the event’send, since a Script Event’s audio is truncated at its end (DAPT §4.9.1): otherwisedescription_malformed. - The synchronisation of §5.3: otherwise
description_out_of_sync.
5.3 Synchronisation
The programme audio falls to the event’s gain from begin to begin + ramp, and rises
back from end − ramp to end. The description is spoken over the interval between,
from a = begin + ramp to z = end − ramp. Of a voiced event (its voice not null):
voice.begin≥ a − 35 andvoice.begin≤ a + 45;voice.end≤ z + 45.
These are DAPT §5.5’s bounds on a presentation processor: audio presentation changes no more than 35 ms before the time a document specifies and no more than 45 ms after it, which DAPT derives from EBU R 37’s bounds on audio relative to image. A voice that starts before the programme audio has fallen, or runs on after it has risen, is out of those bounds. EN 301 549 V4.1.1 clause 7.2.2 requires the synchronisation to be preserved and states no figure.
The offset of a voiced event is voice.begin − a, a signed number of milliseconds;
an unvoiced event has none.
5.4 Description over dialogue
A description is spoken in the pauses of the dialogue (47 CFR 79.3(a)(3): “into natural
pauses between the program’s dialogue”), though the regulator’s 2024 statement accepts
describing over dialogue where what is seen matters more (§6.14 there). So this is a figure,
not a refusal. Against the dialogue of one or more caption tracks, whose resolved cues
(timed-text §4.5) cover the union U of their intervals, each from its start up to, not
including, its end, an event’s overlap is the milliseconds of its spoken interval that lie
in U: from voice.begin up to voice.end when it is voiced, and from a up to z
otherwise. The figure is the sum of the overlaps and the
number of events whose overlap is above 0.
5.5 The DAPT document
A description record maps onto one DAPT document, given, for the form track, the voicing
track’s URI U and media type T, each one to 2048 of the ASCII characters ! to ~
other than ", &, < and > (otherwise parameter_malformed). It is written as UTF-8
with U+000A line ends:
<?xml version="1.0" encoding="UTF-8"?>
<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttp="http://www.w3.org/ns/ttml#parameter" xmlns:tta="http://www.w3.org/ns/ttml#audio" xmlns:daptm="http://www.w3.org/ns/ttml/profile/dapt#metadata" xmlns:wai="tag:transaction.science,2026:wai/access" xml:lang="LANG" ttp:contentProfiles="http://www.w3.org/ns/ttml/profile/dapt1.0/content" daptm:langSrc="zxx" daptm:scriptRepresents="REPS" daptm:scriptType="TYPE" wai:script="SO" wai:voice="VO">
<body>
EVENTS
</body>
</tt>
-
LANGislang.REPSis eachrepresentsvalue of the events once, in the order each first appears, joined by U+0020: every event’s value is then one of them (DAPT §4.1.1).TYPEisasRecordedfor the formtrackandpreRecordingfor the formsink. -
SOandVOare the script’s and the voicing’s origins. Afterwai:script="SO"comeswai:script-model="M"when the script has a model, and afterwai:voice="VO",wai:voice-model="M"when the voicing has one,Mthe digest in lowercase hexadecimal. -
EVENTSis, for each event in order:<div xml:id="ID" begin="B" end="E" daptm:represents="R"> <animate begin="00:00:00.000" end="RAMP" tta:gain="1;G" fill="freeze"/> <animate begin="FALL" end="DUR" tta:gain="G;1"/> <p>CONTENT</p> </div>BandEarebeginandendwrittenHH:MM:SS.mmm(timed-text §5.1);RAMP,FALLandDURareramp,end−begin−rampandend−begin, written the same way;Gis the gain:0for 0, and otherwise0.and its three decimal digits with trailing zeros removed. The twoanimatelines are written only when the gain is below 1000. -
CONTENTis the text, its lines separated by<br/>and&,<and>written&,<and>:- for the form
trackand a voiced event,<span begin="VB" end="VE"><audio src="U" type="T" clipBegin="CB" clipEnd="CE"/>TEXT</span>, withVB=voice.begin−begin,VE=voice.end−begin,CB=voice.beginandCE=voice.end, each writtenHH:MM:SS.mmm. The voicing track is on the programme’s timeline (an audio description stem), so the event’s audio is the interval of it that the event’s voice states; - for the form
trackand an event not yet voiced, the text alone; - for the form
sink,<span tta:speak="normal">TEXT</span>.
- for the form
The document’s features are DAPT’s: a Script Event per description, a div with xml:id,
begin, end and daptm:represents (DAPT §4.3); its Mixing Instructions as animate
children of the Script Event, which adjust the programme audio during it (DAPT §4.3, §4.10);
an Audio Recording by src and type with clipBegin and clipEnd (DAPT §4.9.1); and
Synthesized Audio by tta:speak (DAPT §4.9.2). ttp:contentProfiles names the DAPT content
profile, and no ttp:profile is written (DAPT §5.6). The document’s time base is media time,
times are clock times without frames (DAPT §5.7), and daptm:langSrc is zxx, content
without an inherent language (DAPT §4.5). Two choices are this extension’s:
srconaudio, for an external resource, is at risk in the Candidate Recommendation (its Issue 218). If it does not stay, a later revision of this mapping names the voicing track another way DAPT §4.9.1 keeps.- For the form
sink, DAPT says a pre-recording script SHOULD NOT contain Audio objects, and an as-recorded script SHOULD NOT contain Synthesized Audio. There is no recording: the sink’s voice is the recording. The document is the script it speaks, marked as one, withtta:speaksaying that it is to be spoken.
The attributes in the namespace tag:transaction.science,2026:wai/access are foreign
vocabulary, which DAPT §5.2 has a processor keep or prune. They carry the origin labels of
§5.6, which DAPT has no field for.
5.6 Obligations of a WAI player
These are requirements on a WAI player that plays audio description or shows sign language. Each cites the provision it answers by identifier; they are engineering requirements, and meeting them is not a statement about any law.
- Description can be played. A player of video with synchronised audio MUST let the listener select an available description track and play it to the default audio output (EN 301 549 V4.1.1 clause 7.2.1; WCAG 2.2 Success Criteria 1.2.3 and 1.2.5, which ask content to provide it).
- In sync. A player that mixes a description MUST apply its mixing instructions and play each voice at the times its event states, within §5.3’s bounds (EN 301 549 V4.1.1 clause 7.2.2).
- Preserved. A player or converter that transmits, converts or records a description MUST keep every event’s timing, text, mixing instructions, voicing and labels (EN 301 549 V4.1.1 clause 7.2.3): §5.5’s document keeps them all.
- One operation. A player whose purpose is video MUST offer turning description on and off as a single operation, at the same level as the volume control (EN 301 549 V4.1.1 clause 7.3), as timed-text §11 item 5 has it for captions.
- Labelled. A player MUST show, with a description whose voicing is
machineormachine-reviewed, that the voice is synthesized, in a way the listener perceives without turning on another feature, as timed-text §11 item 7 has it for a machine caption, and SHOULD let the listener learn whether the script was machine-written. The script’s origin and the voicing’s are the description’s labels, as a caption’s origin is its label (timed-text §10.1); a synthesized voice’s origin, with the model’s digest, is the statement its origin claim makes of it (synthesis §3.1), and a player shows its label as synthesis §10 has it show a synthesized object’s. - Signing under the viewer’s control. A player that shows a signing track MUST let the
viewer choose to show it, and SHOULD let the viewer choose its size and position (Directive
(EU) 2019/882 Annex I Section IV(b)(ii), “user control of their display”); a pose stream
leaves both to the sink (§6.1). It MUST show, with a signing track whose origin is
machineormachine-reviewed, that the signing is generated.
6. Sign language
6.1 The signing record
A signing record is a sign language track: a wai.avatar.pose stream (avatars §1), or a
video track of a person signing. Its objects are bound, by digest, to the caption revisions
they translate.
| member | type | meaning |
|---|---|---|
kind | "wai-signing" | |
room | hex32 | the room |
lang | tag | the sign language |
source | hex32 | the principal of the caption track it translates |
form | "pose", "video" | an avatar pose stream, or a video of a signer |
track | hex32 | the track’s digest (live-rooms §6.2) |
origin, model | as §5.1: human for a person signing (filmed, or motion-captured into the pose stream), machine for signing a model generated | |
video | object or null | for video, {"width", "height", "rate_num", "rate_den"}, each an int: its picture size and frame rate; null for pose |
segments | array | each an object below |
signer_pubkey, sig | §2 |
| member of a segment | type | meaning |
|---|---|---|
object | hex32 | the content hash of an object of the track (jwp-receipts §2.1): an op batch of the pose world, or a video object |
start, end | int | room-clock microseconds the signing of the object spans |
revisions | array of hex32 | the caption revisions it translates, by the digest of each caption event |
Pose-equivalence (avatars §4) makes the motion every sink shows the motion in the bound objects, while the appearance is the sink’s: a viewer may choose the signer’s size, place and appearance, which Directive (EU) 2019/882 Annex I Section IV(b)(ii) calls user control of display, and the binding still holds.
6.2 Rules
In order:
roomis the verifier’s: otherwisewrong_room.langreads as a tag;modelis ahex32exactly whenoriginismachineormachine-reviewed;videoisnullexactly forpose, and its four numbers are above 0; there is at least one segment, each withstart<endand at least one revision, each segment’sstartat or after theendof the segment before it; and no revision is named twice in the record: otherwisesigning_malformed.source’s captions are whole (§4.1): otherwisestream_incomplete.- Each named revision is a
captionevent ofsourcethat the verifier holds: otherwisesign_revision_unknown. - Each named revision is the last of its cue and final, its annotation not unknown: otherwise
sign_revision_not_final. Signing translates the text a cue resolves to; a partial that a later revision changed is not what the captions say.
6.3 Figures
- The offset of a segment is its
startless S (§4.4) of the earliest cue, by its first revision’st, among those whose final revisions it names, whensource’s sources record places that cue; it has none otherwise. It is a signed number of microseconds: the delay of the signing behind the speech it interprets. - For the form
video, the video floor ismeetswhen the picture is at least 320 by 240 in either orientation (the smaller side at least 240 and the larger at least 320) and the frame rate at least 20 a second (rate_num≥ 20 ×rate_den), andbelowotherwise: the resolution and frame rate EN 301 549 V4.1.1 clauses 6.5.2 and 6.5.3 require of real-time video communication, which its clause 4.2.4 NOTE 3 names for sign language that accompanies audiovisual content. For the formposeit isnull: the sink renders the signer at the size it chooses.
6.4 Review
A person who reviews the translation signs a review:
| member | type | meaning |
|---|---|---|
kind | "wai-signing-review" | |
signing | hex32 | the record id of the signing record it reviews |
scope | "translation" | what was reviewed: the signing against the caption revisions it is bound to |
verdict | "approved", "approved-with-notes", "rejected" | |
notes | hex32 or null | the digest of the reviewer’s notes; null exactly for approved |
signer_pubkey, sig | §2 |
Rules: notes is null exactly when the verdict is approved (record_malformed), and
signing is the record id of a signing record the verifier holds (review_subject_unknown).
The review binds the objects by their digests, so, for a pose stream, every viewer whose sink
is pose-equivalent sees the motion the reviewer approved. Its vocabulary is synthesis §9.1’s
review with the scope translation; that review binds one reconstruction of a synthesized
object, and this one binds a signing record to the caption revisions it translates.
7. The completeness claim
7.1 The record
A completeness claim states, for a room session, which access tracks it carried, and that each was delivered complete and in sync.
| member | type | meaning |
|---|---|---|
kind | "wai-access-completeness" | |
room | hex32 | the room |
from, to | int | the session, from from up to, not including, to, in room-clock microseconds |
pt0 | int | the media time of the room’s t0, in milliseconds (timed-text §2) |
tracks | array | the access tracks it declares, each an object below |
signer_pubkey, sig | §2 |
| service | its members besides service |
|---|---|
"captions" | principal (hex32), lang (tag), latency_mean_max and latency_max (each int or null, microseconds) |
"audio-description" | record (hex32, a description record’s id), lang (tag) |
"sign-language" | record (hex32, a signing record’s id), lang (tag), review (hex32 or null, a review’s id), offset_max (int or null, microseconds) |
The tracks a claim declares are the availability of access services an electronic programme guide states (EN 301 549 V4.1.1 clauses 12.4 and 12.5), made checkable.
A cue of P is in the session when its first revision’s t is at or after from and
before to. The
session’s media interval is from pt0 + ⌊from / 1000⌋ to pt0 + ⌊to / 1000⌋.
7.2 Checking the claim
roomis the verifier’s: otherwisewrong_room.from<to; at least one track; each track’slangreads; no principal is named by two caption tracks, and no record by two tracks: otherwiseclaim_malformed.
Then each track in order, the first failure naming the refusal:
Captions, of principal P:
- P has a cue in the session: otherwise
track_missing. - P’s captions are resolved (§4.1): otherwise
track_incomplete. A delivery gap is an event not delivered, and a cue that does not resolve was not finished. - Every revision of every cue of P in the session has the track’s
lang: otherwisetrack_mismatch. - When
latency_mean_maxorlatency_maxis notnull: P’s sources record places every cue of P in the session, otherwisesync_unmeasured; and over those cues the mean latency (§4.4) is at mostlatency_mean_max, and each latency at mostlatency_max, where each is given: otherwiseout_of_sync.
Audio description, of record D:
- D is a description record the verifier holds: otherwise
track_missing. - Its
langis the track’s, and each of its events lies in the session’s media interval: otherwisetrack_mismatch. - For the form
track, every event is voiced: otherwisetrack_incomplete. (Each voice is already in sync, §5.3.)
Sign language, of record G:
- G is a signing record the verifier holds: otherwise
track_missing. - Its
langis the track’s, and itssourceis the principal of a caption track of this claim: otherwisetrack_mismatch. - Every cue of
sourcein the session has its final revision named by a segment of G: otherwisetrack_incomplete. - When
reviewis notnull: it is the id of a review the verifier holds (otherwisereview_missing), which names G (otherwisereview_mismatch) and whose verdict is notrejected(otherwisereview_rejected). - When
offset_maxis notnull: every segment of G has an offset (§6.3), otherwisesync_unmeasured; and each offset’s absolute value is at mostoffset_max, otherwiseout_of_sync.
A claim that passes is held. Its dialogue overlap is, for each audio description
track, §5.4’s figure against the resolved cues of the claim’s caption tracks, their media
times as timed-text §4.5 gives them with the claim’s pt0.
7.3 The tolerances
| track | measured from | tolerance | stated by |
|---|---|---|---|
| captions, live | each cue’s first display and its source (§4.4) | a mean of at most 4.5 s across live programming: a recommendation, not a limit per programme | the regulator’s 2024 statement, §5.17 and §5.25; its 2013 statement (§3.65 to §3.67) recorded the earlier guidance of at most 3 s |
| captions, shown by a player | a cue’s time | within 100 ms of it, 20 ms as good practice | EN 301 549 V4.1.1 clause 7.1.2: the player’s, timed-text §11 item 2 |
| audio description | each voice and its event (§5.3) | 35 ms early to 45 ms late | DAPT §5.5, from EBU R 37 |
| sign language | each segment and its source (§6.3) | none stated | no text read for this revision gives a figure; EN 301 549 V4.1.1 clause 4.2.4 NOTE 3 asks only that it be “well synchronized with the spoken content” |
A claim states the caption and sign tolerances it is held to (latency_mean_max,
latency_max, offset_max); the description tolerance is fixed by §5.3. The captions’
mean is computed over the session, while the 2024 statement’s is over a provider’s live
programming taken together; a claim that states 4 500 000 holds one session to it.
8. Verification
8.1 Inputs
A verifier is given the room id; the records of the room’s event stream, in stream order (live-events §6); and the records of this extension, as JSON texts, in the order given.
8.2 Steps
- Events. Each event record is offered, in stream order, to a verifier of captions
(timed-text §4.3), which verifies it as live-events §6 does and the
captions in it as timed-text §4.3 does. A refusal is the outcome, at
eventsand the record’s index, with that extension’s reason. At the end of the stream the captions are finished (timed-text §4.3), and the gaps, which are not refusals, are noted. - Reading. Each record is read (§2), its signature verified and its record id computed,
in the order given: a failure is the outcome, at
recordand the record’s index. - Rules. Then each record is checked by its section’s rules, kind by kind in this
order, and the records of one kind in the order given: sources (§4.2), references
(§4.3), descriptions (§5.2), signings (§6.2), reviews (§6.4), quality records (§4.7) and
claims (§7.2). So a record that another names has been checked before it. The first
failure is the outcome, at
recordand the failing record’s index. - Figures. With no refusal, the outcome is accept, with: the figure (§4.7) of every
principal whose captions are whole, in the order of each one’s first
captionevent in the stream; for each description record, its number of events, the number voiced and each event’s offset (§5.3); for each signing record, its number of segments and of revisions named, each segment’s offset and its video floor (§6.3); and for each claim, its dialogue overlap (§7.2).
9. What the figures measure
| figure | what it measures | in the texts read |
|---|---|---|
latency: per cue, its mean, its range (min, max) and two ranks | first display on the room clock, less the capture of the first word the cue carries | the 2013 statement’s “average latency of the subtitling (the delay between speech and live subtitling), and the range of latencies” (§1.3(b)); the 2024 statement’s mean (§5.17, §5.25); 47 CFR 79.1(k)(2)(vi), “lag between the spoken word supplied by the program origination point and when captions are received at the same program origination point”, which the room clock’s t, stamped as the caption leaves its author, measures; 79.1(j)(2)(ii) and (j)(3)(ii); EBU Tech 3370 §2.3.2’s authoring delay, from the subtitler hearing the audio to the tool’s output, and its §2.3.3 ebuttm:authoringDelay, which a producer may state and this figure measures |
| stability: revisions after first display, words changed, cues corrected | what the viewer saw that a later revision changed | the 2024 statement’s research finding that subtitles corrected live on air distract (§5.23) |
| accuracy: words, errors, and their kinds | word errors against a reference a person wrote or reviewed | 47 CFR 79.1(k)(2)(iv): accuracy is the total words less the errors, over the total words, which is (N − E) / N here, and (k)(2)(v)‘s kinds of error, of which this figure counts incorrect and missing words; 79.1(j)(2)(i); the 2013 statement’s “number and type of errors” (§1.3(c)); the 2024 statement sets no minimum accuracy (§5.29) |
| dialogue overlap | description spoken over captioned dialogue | 47 CFR 79.3(a)(3); the 2024 statement §6.2 and §6.14 |
| completeness | every declared track present, every cue finished, every event voiced and every cue signed | Directive (EU) 2019/882 Annex I Section IV(b)(ii), “fully transmitted … synchronised”; 47 CFR 79.1(j)(2)(iii), captioning “from the beginning to the end of the program”, which this claim checks over the cues the session holds, not over the speech it does not hold |
Not computed here:
- the severity of an error, which the error-classification model the 2013 statement’s measurement used (its footnote 21) grades minor, standard or serious: that grading needs a person. The alignment gives the errors and the reference words a grader starts from;
- errors of capitalisation and of punctuation at a word’s edge, which §3.1 removes, and which 47 CFR 79.1(j)(2)(i) counts;
- the speed of the captions, and their placement (79.1(j)(2)(iv));
- the quality of a description, of a voice or of a signing, which a person judges, and whose judgement a review records.
10. Reasons
| reason | raised at |
|---|---|
record_malformed | §2, §4.2, §4.3, §6.4 |
bad_key | §2 |
bad_signature | §2 |
wrong_room | §2, §4.2, §4.3, §4.7, §6.2, §7.2 |
record_conflict | §4.2, §4.3 |
source_unknown | §4.2 |
source_take_unknown | §4.2 |
text_not_in_subset | §4.3, §5.2 |
reference_unknown | §4.3 |
reference_incomplete | §4.3 |
stream_incomplete | §4.2, §4.3, §4.7, §6.2 |
figure_inputs_mismatch | §4.7 |
figure_mismatch | §4.7 |
description_malformed | §5.2 |
description_out_of_sync | §5.2, §5.3 |
parameter_malformed | §5.5 |
signing_malformed | §6.2 |
sign_revision_unknown | §6.2 |
sign_revision_not_final | §6.2 |
review_subject_unknown | §6.4 |
claim_malformed | §7.2 |
track_missing | §7.2 |
track_incomplete | §7.2 |
track_mismatch | §7.2 |
sync_unmeasured | §7.2 |
out_of_sync | §7.2 |
review_missing | §7.2 |
review_mismatch | §7.2 |
review_rejected | §7.2 |
An event record that live-events or timed-text refuses keeps that extension’s reason.
11. Conformance
live-conformance/access/ holds the corpus, written from fixed
seeds by wai_access_services_vectors gen: vectors.json, and each description record’s DAPT
document as a file of its own, NAME.dapt.ttml. Each vector is a room’s event stream and the
records of this extension, with the outcome §8 gives them and, when accepted, every figure. It
has:
- accepted sessions: a lesson with a human captioner, a machine captioner whose partials
are revised to final, a capture take placing the machine captions’ words, a reference
transcript, a quality record for each track, a description voiced on a separate track, a
motion-captured signer bound to the human captions with an approved review, and a claim over
all of them held to the 2024 statement’s mean; a session whose machine captions a person
reviews, with a description the sink voices by a pinned model, the video of a signer, and a
claim without latency bounds; and a session with no sources, whose latency class is
none; - negative controls, each a copy of an accepted session with one defect, and each refused with its reason: a latency figure misstated, a broken revision chain, a sign track bound to a revision a later one superseded and to a revision the stream does not hold, a description spoken late and one spoken early, a claim over a track the verifier does not hold, and one for every other reason of §10.
A conforming verifier gives every vector the outcome, the reason, the place and every figure
the corpus states, and writes every DAPT document byte for byte. wai_access_services_vectors verify and the test tests/access_services.rs check that every file regenerates byte for
byte, that no other file is there, that wai-rs gives every vector its outcome, that every
reason of §10 refuses a vector, and that §10 lists exactly the reference’s codes.
live-conformance/access_services_verify.py is the second implementation, written from this
text: it shares no code with wai-rs; it verifies events and captions with the timed-text
corpus’s second implementation (timed_text_verify.py) and signatures with WAI’s strict rule
(claim-conformance/_ed25519.py); it computes every figure, writes every DAPT document and
parses each with an XML parser; and it requires every mutated copy of the corpus to fail.
12. Security and privacy considerations
- Every figure is recomputed from signed records. A figure states nothing a verifier takes on trust; a quality record’s signer vouches only that it computed the figure, and a verifier that recomputes it needs no trust in the signer.
- A source places words on the room clock as its signer states. On a take, the media’s time is
the device’s signed commitment and cannot be moved; where a word lies in the media is the
aligner’s statement, attributable to it by its signature, and checkable by anyone holding the
master. A source on the basis
roomplaces the words by the signer’s word alone, and the latency’s class says so (stated). - A take’s opening commitment is the device’s, but a principal that is not a capturing device
can sign one too. This extension requires the take to be derived from a
record_startaddressed to the commitment’s author; that the author was permitted to capture, and for whom, is what a take verifier and a room verifier check (capture-binding §9, live-rooms §9). tis its author’s statement of the room clock (live-events §11). A captioner who stamps its captions early lowers its latency, and the stamp is signed: the room’s relays see when each event arrived, and a later extension’s per-hop receipts witness it.- A reference transcript is its reviewer’s. The accuracy’s class names what the reference is; a verifier’s policy decides whose transcripts it accepts.
- Labels are their producers’ statements, as timed-text §14 says of captions. A description or a signing labelled human that a model produced misleads its audience, and the signature makes that attributable.
- A signing track’s binding names caption revisions by digest. It shows what the signing translates; it does not show that the translation is correct, which a review states.
- A sources record ties a cue to a position in a recording, and a signing record ties a track to a person who signs. Both persist with the session’s records, as the events do.