From 8aba6f29ef87f8c410e2efbe18fbbce2d7e516b8 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Tue, 4 Aug 2026 12:35:57 +0100 Subject: [PATCH] =?UTF-8?q?spec:=20AUDIO-IN-1=20=E2=80=94=20lang=20authori?= =?UTF-8?q?ty=20basis;=20bridge=20cites;=20sleep=20scope;=20STT-failure=20?= =?UTF-8?q?rule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reconciles §5 lang requiredness with PIPELINE-1 §9.1 (optional on the topic; audio input SHOULD always set it since it authoritatively knows the decode language by construction), retargets the §5.2 bridge citation to BRIDGE-1 §3.4.2 (assignment) + §3.2 (NAT), marks context.session.session_id on sleep/awoken as informational, notes the deliberate absence of a listener-state query topic, states record.ended carries no completion guarantee, adds a MUST NOT-phantom rule for STT failure/empty results, clarifies §4 transformer-chain lang-parameter degradation under in-process capture, and adopts TRANSFORM-1 §3.1's sample rate/width/channels metadata as the pre-STT audio-format vocabulary (AUDIO-1's mime/sample_rate as the output-side counterpart). Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 23 ++++++++++++++++++++ audio-in.md | 61 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6377ce08..0cd1b4c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -361,6 +361,29 @@ version 2: its `{{ … }}` sequences become substitution points, and its ### 2 +- §5 — `lang` on `ovos.utterance.handle` is optional (aligned with + OVOS-PIPELINE-1 §9.1), not required; the service SHOULD always set + it because it authoritatively knows the decode language by + construction (it chose the STT decoder). Added a MUST NOT-phantom + rule: no emission when STT produced no usable transcription. +- §5.2 — bridge citations retargeted from §4.2.1 to OVOS-BRIDGE-1 + §3.4.2 (managing-mode session assignment) and §3.2 (`session_id` + NAT translation). +- §6.3 — `context.session.session_id` on `ovos.listener.sleep` / + `ovos.listener.awoken` is informational only; the device-scope + effect is identical for any value. Noted the deliberate absence of + a listener-state query topic; deployments needing sync-on-connect + derive state from the last-seen lifecycle signal. +- §6.2 — `ovos.listener.record.ended` carries no completion + guarantee; utterance arrival or absence is the only reliable + signal. +- §4 — chain input metadata (sample rate/width/channels, OVOS-TRANSFORM-1 + §3.1) adopted as the pre-STT audio-format vocabulary, the + input-side counterpart to OVOS-AUDIO-1's `mime`/`sample_rate` + fields. Clarified that with in-process capture the chain's `lang` + parameter (OVOS-TRANSFORM-1 §3.0) starts unset and its writeback + is a no-op; the chain's output reaches the pipeline via + `session.detected_lang`. - §6.5 (new) — `ovos.listener.wakeword`: the wake-word detection signal (`wake_word`, optional `lang`), preceding `ovos.listener.record.started`; the observable event behind a diff --git a/audio-in.md b/audio-in.md index 9c97b199..8c0f86e5 100644 --- a/audio-in.md +++ b/audio-in.md @@ -58,7 +58,21 @@ deployer-defined. Before passing audio to STT, the audio input service **MUST** run the audio-transformer chain (**OVOS-TRANSFORM-1 §3.1**), configured per -OVOS-TRANSFORM-1 §4. +OVOS-TRANSFORM-1 §4. Chain input metadata carries at minimum +sample rate, sample width, and channel count (OVOS-TRANSFORM-1 +§3.1); this is the pre-STT audio-format vocabulary, and it is the +input-side counterpart to the `mime` and `sample_rate` fields +OVOS-AUDIO-1 defines on the output side. + +When capture is in-process (audio input service and STT sharing a +process, no bus hop between them), the chain's `lang` parameter +machinery (**OVOS-TRANSFORM-1 §3.0**) degrades gracefully: there is +no Message yet whose `data.lang` could seed it, so `lang` simply +starts unset for the chain and the §3.0 writeback step is a no-op +(there is no `Message.data.lang` to reflect a value into). This is +not a gap — the chain's actual output reaches the pipeline through +`session.detected_lang` (below), which is the channel §5.1 language +resolution already reads. Canonical use cases: @@ -84,7 +98,23 @@ per **OVOS-PIPELINE-1 §9.1**. | Field | Type | Required | Meaning | |-------|------|----------|---------| | `utterances` | array of string | yes | Transcription candidates; first element is primary. | -| `lang` | string | yes | BCP-47 output language of the transcription. See §5.1. | +| `lang` | string | no | BCP-47 output language of the transcription. See §5.1. | + +Per **OVOS-PIPELINE-1 §9.1**, `lang` on this topic is present only +when the producer authoritatively knows the content language. The +audio input service satisfies that condition by construction: it +selected the STT decoder (§5.1) and therefore knows, without +inference, which language the decoder was run in. It **SHOULD** +always set `lang` for that reason — omission is conformant (the +field stays optional on the topic per §9.1) but only expected when +the service could not resolve a decode language at all (§5.1). + +The service **MUST NOT** emit `ovos.utterance.handle` when STT +produced no usable transcription — an empty result, a decode +failure, or a confidence rejection. `utterances` is defined as +non-empty; a phantom emission with no real content is +non-conformant. Surfacing the failure for diagnostics is outside +this specification's scope. ### 5.1 Language resolution @@ -116,8 +146,9 @@ placed in `context.session` (**OVOS-MSG-1 §4**). - **Local device** — SHOULD use `session_id: "default"` (**OVOS-SESSION-2 §5**). - **Satellite** — session is assigned by the bridge at the hub - boundary (**OVOS-BRIDGE-1 §4.2.1**); the bridge relays or - NAT-translates the `session_id` as needed. + boundary (**OVOS-BRIDGE-1 §3.4.2**); the bridge relays or + NAT-translates the `session_id` as needed (**OVOS-BRIDGE-1 + §3.2**). --- @@ -151,6 +182,10 @@ of this Message. This signal pairs with `ovos.listener.record.started` (§6.1); a component that subscribed to the start signal uses this to restore state. +`ovos.listener.record.ended` carries no completion guarantee about +what capture produced — the arrival (or absence) of a subsequent +`ovos.utterance.handle` (§5) is the only reliable signal of whether +usable audio resulted. ### 6.3 Sleep mode @@ -175,6 +210,21 @@ request rides a session like every Message, sleep mode is a nothing for any session. Entering or leaving sleep affects the whole device, not only the session that carried the request. +`context.session.session_id` on `ovos.listener.sleep` and +`ovos.listener.awoken` (§6.4) is therefore **informational only**: +it identifies the requester for logging and correlation, but the +device-scope effect — capture suspended or resumed for every +session — is identical no matter which session's identifier the +Message carries. + +No topic in this specification lets a component query current +listener state (awake, asleep, capturing) on demand. This is a +**deliberate omission**: sleep and record signals (§6.1–§6.4) are +edge-triggered notifications, not a queryable state store. A +deployment that needs to synchronize to current state on connect +(e.g. a bridge attaching mid-session) derives it from the last-seen +lifecycle signal rather than polling for one. + ### 6.4 Awoken When the audio input service leaves sleep mode, it **MUST** emit: @@ -267,4 +317,5 @@ word (push-to-talk, `ovos.mic.listen`) emit no wake-word signal. `session.detected_lang`, `session.request_lang`. - **OVOS-SESSION-2** — session assignment and default-session rule. - **OVOS-MSG-1** — session carrier (§4) and envelope. -- **OVOS-BRIDGE-1** — satellite session assignment (§4.2.1). +- **OVOS-BRIDGE-1** — satellite session assignment (§3.4.2) and + session `session_id` NAT translation (§3.2).