From f711e7ac9672d7964545a6a4dc2db36c1e6ea489 Mon Sep 17 00:00:00 2001 From: "Alan Ding (Google)" Date: Thu, 13 Aug 2026 08:45:53 -0700 Subject: [PATCH 1/9] =?UTF-8?q?Update=20audioStartTime=20and=20audioEndTim?= =?UTF-8?q?e=20to=20be=20relative=20to=20start=20of=20aud=E2=80=A6=20(#203?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update audioStartTime and audioEndTime to be relative to start of audio stream We want to switch to stream-Relative (0-based) impl. since: - In Web Audio and Media APIs (HTMLMediaElement.currentTime, AudioContext.currentTime, WebCodecs VideoFrame.timestamp), media timelines are always 0-based offsets relative to stream start, not the time origin. - Immune to inter-process jitter since SODA and audio capture run in a separate utility/browser process. Translating stream offsets to the renderer's timeOrigin relies on estimating when IPC AudioStarted() arrived, which introduces IPC latency jitter. Stream-relative offsets are not prune to this and aligns with the raw audio frames. - If SpeechRecognition is used with a pre-recorded MediaStreamTrack, a 0-based stream offset reflects the actual position in the audio track regardless of when the webpage was loaded. - Being relative to performance.timeOrigin doesn't make sense in general for the Web Speech API because it assumes that the audio source is live. Since a SpeechRecognizer can also be created for a prerecorded media stream I think the timestamps on the speech recognition events should be relative to the position in that media stream. See https://crbug.com/542330168 for more details. * Update speech recognition explainer with timestamp conversion Added a section on converting stream timestamps to document time origin and provided a live translation latency example with code. * Minor update to close live transcription latency measurement example Added separator before security section and closed example section for live transcription measurements. * respond to review comment --- .../speech-recognition-result-timestamps.md | 62 ++++++++++++++++++- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/explainers/speech-recognition-result-timestamps.md b/explainers/speech-recognition-result-timestamps.md index c6ccd3b..0200cc5 100644 --- a/explainers/speech-recognition-result-timestamps.md +++ b/explainers/speech-recognition-result-timestamps.md @@ -17,10 +17,10 @@ We propose extending the `SpeechRecognitionResult` interface to include optional ```webidl partial interface SpeechRecognitionResult { - // Start timestamp of the audio segment in milliseconds (relative to time origin) + // Start timestamp of the audio segment in milliseconds (relative to the start of the audio stream) readonly attribute DOMHighResTimeStamp? audioStartTime; - // End timestamp of the audio segment in milliseconds (relative to time origin) + // End timestamp of the audio segment in milliseconds (relative to the start of the audio stream) readonly attribute DOMHighResTimeStamp? audioEndTime; }; ``` @@ -39,7 +39,7 @@ recognition.interimResults = true; recognition.onresult = (event) => { const result = event.results[event.resultIndex]; - if (result.audioEndTime !== null) { + if (result.audioEndTime !== null && result.audioEndTime !== undefined) { // Calculate on-device processing latency const processingLatencyMs = event.timeStamp - result.audioEndTime; @@ -54,6 +54,62 @@ recognition.onresult = (event) => { recognition.start(); ``` +## Converting Stream Timestamps to Document Time Origin + +`audioStartTime` and `audioEndTime` are defined as media-local offsets in milliseconds relative to the start of the audio stream ($t = 0.0\text{ms}$). + +For real-time applications such as **live translation**, **subtitling overlays**, and **audio-visual sync**, developers often need to map these stream offsets to the document's global timeline (`DOMHighResTimeStamp` / `performance.now()`). + +### Pattern: Capturing the Audio Timeline Origin + +To convert stream-relative timestamps to document time coordinates: +1. Record the baseline timestamp when the `audiostart` event fires (`event.timeStamp` is a `DOMHighResTimeStamp` relative to `timeOrigin`). +2. Add the result's `audioStartTime` and `audioEndTime` offsets to that baseline. + +$$\text{absoluteStartTime} = \text{audioOrigin} + \text{result.audioStartTime}$$ +$$\text{absoluteEndTime} = \text{audioOrigin} + \text{result.audioEndTime}$$ + +### Measuring Live Translation Latency Example + +In live speech translation workflows, measuring both **Speech-to-Text (STT) latency** and **Machine Translation (MT) end-to-end latency** is essential: + +```javascript +const recognition = new SpeechRecognition(); +recognition.continuous = true; +recognition.interimResults = true; + +let audioOriginTime = 0; + +// 1. Capture the audio stream's time origin on the document timeline +recognition.onaudiostart = (event) => { + audioOriginTime = event.timeStamp; +}; + +recognition.onresult = async (event) => { + const result = event.results[event.resultIndex]; + if (result.audioEndTime === null || result.audioEndTime === undefined) return; + + // 2. Convert stream offsets to document time origin coordinates + const absoluteAudioStart = audioOriginTime + result.audioStartTime; + const absoluteAudioEnd = audioOriginTime + result.audioEndTime; + + // 3. Compute ASR recognition latency + const asrLatencyMs = event.timeStamp - absoluteAudioEnd; + + // 4. Perform live translation + const text = result[0].transcript; + const translationStartTime = performance.now(); + const translatedText = await translateService.translate(text, 'es'); + const translationEndTime = performance.now(); + + // 5. Total end-to-end latency from speaker utterance to translated subtitle + const totalE2ELatencyMs = translationEndTime - absoluteAudioEnd; + + console.log(`ASR Processing Time: ${asrLatencyMs.toFixed(1)}ms`); + console.log(`Total Live Translation Delay: ${totalE2ELatencyMs.toFixed(1)}ms`); +}; +``` +--- ### Security and Privacy Considerations #### Fingerprinting Risk From d5b1e6113e6373f4ea43623fa69262ddcc48aad5 Mon Sep 17 00:00:00 2001 From: "Alan Ding (Google)" Date: Fri, 21 Aug 2026 15:33:52 -0700 Subject: [PATCH 2/9] Expand on limitations of existing speech recognition events in Alternatives and refactor Timestamps to use Seconds (#205) * Expand on limitations of existing speech recognition events Added detailed explanations regarding the limitations of existing API surfaces for tracking latency in speech recognition in the Alternatives Considered section, including issues with `speechstart` and `speechend` events and the implications of modifying `event.timeStamp`. * Refactor speech recognition timestamps to use seconds Updated the speech recognition result timestamps to use seconds instead of milliseconds, improving consistency with other Web APIs. Added detailed explanations for the choice of time representation, proposed behavior, and security considerations. Based off of comments from https://github.com/WebAudio/web-speech-api/pull/205 --- .../speech-recognition-result-timestamps.md | 123 +++++++++++++----- 1 file changed, 88 insertions(+), 35 deletions(-) diff --git a/explainers/speech-recognition-result-timestamps.md b/explainers/speech-recognition-result-timestamps.md index 0200cc5..ff85d63 100644 --- a/explainers/speech-recognition-result-timestamps.md +++ b/explainers/speech-recognition-result-timestamps.md @@ -6,70 +6,103 @@ The Web Speech API currently does not expose the start and end timestamps of the source audio corresponding to a given transcription result (`SpeechRecognitionResult`). This limitation creates two major challenges for API clients and end users: -- **Timeline Association:** Developers cannot readily associate transcribed text with specific segments of the audio source, making it difficult to map generated captions to media timelines or audio tracks. +- **Timeline Association:** Developers cannot readily associate transcribed text with specific segments of the audio source, making it difficult to map generated captions to media timelines, audio tracks, or video frames. - **Latency Tracking & Backend Failover:** With the adoption of on-device Automatic Speech Recognition (ASR) to improve privacy and reduce server costs, processing performance becomes heavily dependent on local client hardware resources. The Web Speech API acts as a "black box" regarding local processing delays. Developers cannot programmatically calculate transcription latency or detect when on-device models fall behind real-time. This leads to poor user experiences (e.g. caption lag during live video conferencing) and deprives applications of the signal needed to seamlessly fail over to high-performance cloud backends. ### Proposed Solution -We propose extending the `SpeechRecognitionResult` interface to include optional (nullable) `audioStartTime` and `audioEndTime` attributes. +We propose extending the `SpeechRecognitionResult` interface to include `audioStartTime` and `audioEndTime` attributes. #### Web IDL Definition ```webidl partial interface SpeechRecognitionResult { - // Start timestamp of the audio segment in milliseconds (relative to the start of the audio stream) - readonly attribute DOMHighResTimeStamp? audioStartTime; + // Start timestamp of the audio segment in seconds relative to the start of the audio stream (0.0s). + readonly attribute double audioStartTime; - // End timestamp of the audio segment in milliseconds (relative to the start of the audio stream) - readonly attribute DOMHighResTimeStamp? audioEndTime; + // End timestamp of the audio segment in seconds relative to the start of the audio stream. + readonly attribute double audioEndTime; }; ``` +### Choice of Time Representation: Seconds as `double` + +The timestamps `audioStartTime` and `audioEndTime` are defined as `double` representing **seconds**, rather than `DOMHighResTimeStamp` (milliseconds). This design choice is based on the following considerations: + +1. **Consistency with Adjacent Web Audio & Media APIs:** + * In adjacent W3C media specifications, media-local stream timelines are universally represented in **seconds** as a `double`: + * **Web Audio API:** [`BaseAudioContext.currentTime`](https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-currenttime) (seconds) + * **HTML Media Elements:** [`HTMLMediaElement.currentTime`](https://html.spec.whatwg.org/multipage/media.html#dom-media-currenttime) (seconds) + * **AudioParam Scheduling:** [`AudioParam.setValueAtTime()`](https://webaudio.github.io/web-audio-api/#dom-audioparam-setvalueattime) (seconds) + * Using seconds ensures seamless interoperability when developers route audio between `