← SpeechRecognitionResult Timestamps (WebSpeech API)
v153 · dev trial · attribute
SpeechRecognitionResult.audioEndTime
A nullable DOMHighResTimeStamp reporting the end of the source-audio segment that produced this recognition result, in milliseconds relative to the time origin, quantized to 2 ms precision. null when the recognition engine does not supply segment timestamps. Subtracting it from Event.timeStamp yields the recognition pipeline's processing lag — the signal behind latency-triggered backend failover. Developer trial in Chrome 153 behind the WebSpeechTimestamps flag.
Behind --enable-blink-features=WebSpeechTimestamps (flag experimental, not public — no chrome://flags entry, no origin trial). The defining spec change, WICG/speech-api PR #192, is open; the attribute can change in review. Detect with 'audioEndTime' in SpeechRecognitionResult.prototype. See the overview warn-block.
syntax
readonly attribute DOMHighResTimeStamp? audioEndTime;
Proposed spec text (PR #192, quoted verbatim): “A nullable DOMHighResTimeStamp representing the end of the audio segment corresponding to this recognition result, in milliseconds relative to the time origin. Returns null if the underlying recognition engine does not support audio segment end timestamps.”
The shipping Chromium IDL gates the same member on the runtime feature (speech_recognition_result.idl):
[RuntimeEnabled=WebSpeechTimestamps] readonly attribute DOMHighResTimeStamp? audioEndTime;
Source: PR #192 diff; speech_recognition_result.idl
value
| Type | DOMHighResTimeStamp? (nullable double; milliseconds per High Resolution Time) |
|---|---|
| Meaning | End of the audio segment this result was transcribed from, relative to the time origin — the same clock as performance.now() and Event.timeStamp |
| Null case | null when the underlying recognition engine does not support audio segment end timestamps (per spec PR) — in Chromium, when the engine's TimingInformation.audio_end_time was absent (getter returns std::nullopt) |
| Precision | Floored to a multiple of 2 ms (FuzzTimestamp, kFuzzInterval = base::Milliseconds(2)) — anti-fingerprinting quantization required by the spec PR's privacy clause |
| Engine semantics | In Chromium's pipeline the value originates as “elapsed processed audio from first frame after preamble” (speech_recognition.mojom) — i.e. how much audio the engine had consumed when the segment closed |
| Latency role | event.timeStamp - result.audioEndTime ≈ processing lag: how long after the audio ended the result arrived. See the overview latency section |
inputs
None. This is a read-only attribute: no setter, no parameters, no options. What the engine supplies is what the getter returns (after quantization); script cannot influence the value other than by choosing a recognition engine/backend that supports segment timestamps.
Source: PR #192 (readonly attribute, no associated setter or algorithm inputs)errors
No error surface. The getter never throws: unsupported engines yield null, not an exception. Reading the attribute on a browser without the runtime flag fails earlier — the member does not exist on the prototype at all — so feature-detection ('audioEndTime' in SpeechRecognitionResult.prototype) is the correct guard, not try/catch.
context and exposure
- Exposed on every
SpeechRecognitionResult— the objects inSpeechRecognitionEvent.resultsdelivered toresultevent handlers — when theWebSpeechTimestampsruntime feature is enabled. - The host Web Speech API requires a secure context and microphone permission (or a
MediaStreamTracksource); these attributes add no new requirements of their own. - Both interim (
isFinal === false) and final results can carry the value: Chromium's aggregation path constructs provisional and final results from the same engine struct (speech_recognition.cc). Latency monitoring therefore works on interim hypotheses, not only on final segments.
lifecycle
- The recognition engine emits a result with timing information (
TimingInformation.audio_end_timein the mojom struct). - Blink stores it on the result object at construction (
SpeechRecognitionResult::Create). - Each getter call returns the stored value floored to 2 ms, or
nullif unset. The value for a given result object does not change afterwards. - Because
Event.timeStampis captured when theresultevent is created, the latency figureevent.timeStamp - result.audioEndTimeis most accurate when read promptly inside the handler; heavy handler work before reading it inflates the apparent lag.
examples
recognition.onresult = (event) => {
const result = event.results[event.resultIndex];
if (result.audioEndTime === null) return; // engine without segment timing
const lagMs = event.timeStamp - result.audioEndTime;
latencySamples.push(lagMs);
// Sustained lag over a sliding window → fail over to the cloud backend.
if (median(latencySamples.slice(-20)) > 1500) {
switchToCloudBackend();
}
};
Source: adapted from the explainer's example usage (threshold + failover pattern); sliding-window aggregation is gendn-derived
browser compatibility
Interim table. No BCD key exists for this member (verified 2026-07-29); rows compiled from primary sources.
| Browser | Support | Evidence |
|---|---|---|
| Chrome / Edge (Chromium) | Dev trial 153 — WebSpeechTimestamps flag (experimental, not public) | listing; flag record |
| Firefox | No signal | ChromeStatus API record |
| Safari | No signal | ChromeStatus API record |
security and privacy
- High-precision timing is a hardware-fingerprinting vector; the spec PR requires fuzzing/precision reduction before script exposure (“e.g. by rounding to 2ms precision”) and Chromium floors values to 2 ms multiples in the getter — so derived latency figures are likewise 2 ms-quantized.
- The attribute reveals nothing beyond timing metadata about audio the page already submitted for recognition under the existing permission model — no new audio, device, or engine access. Engine load is indirectly observable through latency trends; the 2 ms floor plus event-delivery noise keeps that signal coarse.
- A
nullresult distinguishes “engine cannot time segments” from “segment ends at 0”, preventing fabricated-zero latency misreads (anullguard must precede any subtraction —event.timeStamp - nullwould silently compute a bogus value).
see also
- SpeechRecognitionResult Timestamps — overview (feature page, incl. the latency walkthrough)
audioStartTime— the segment start- Chrome Platform Status — feature 5811907077472256
- MDN — Event.timeStamp (the latency formula's other operand)
- Showcase — latency monitor demo (HEAD-checked 200, 2026-07-29)