From 1cebab4cffbf4b518f1f7049e2d6dfe850bdb582 Mon Sep 17 00:00:00 2001 From: JarbasAi Date: Tue, 4 Aug 2026 12:21:37 +0100 Subject: [PATCH] =?UTF-8?q?spec:=20OVOS-AUDIO-1=20=E2=80=94=20bridge=20cit?= =?UTF-8?q?e;=20listen-gating=20scope;=20barge-in=20policy=20note?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - §4.3: fix bridge citation OVOS-BRIDGE-1 §4.2.4 → §4.2.5 (TTS as a service) - §4.4: scope listen-flag/ended gating to local-playback path, forward-ref §3.4's remote-client exception - §6: add barge-in-is-deployer-policy paragraph (ovos.listener.wakeword → ovos.audio.stop is optional, not mandated) - §3.2: scope synthesis-failure clause per-segment; state partial-utterance bus contract is limited to §5.2 ended-on-queue-empty - §5.3: note is_speaking is deliberately session-scoped, no aggregate query --- CHANGELOG.md | 16 ++++++++++++++++ audio-out.md | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6377ce08..37987948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,22 @@ an entry here. ### 2 +- §4.3 — fixed the bridge citation: `ovos.audio.speech` relaying is + OVOS-BRIDGE-1 §4.2.5 (TTS as a service), not §4.2.4. +- §4.4 — scoped the `listen`-flag / `ovos.audio.output.ended` gating + to the local-playback path, with a forward-reference to §3.4's + remote-client exception (`listen` fires right after + `ovos.audio.speech`, with no `ovos.audio.output.ended` to gate on). +- §6 (new paragraph) — barge-in (wake-word during active playback) + is deployer policy: a controller MAY subscribe to + `ovos.listener.wakeword` (OVOS-AUDIO-IN-1 §6.5) and emit + `ovos.audio.stop`; this spec mandates neither. +- §3.2 — scoped the synthesis-failure fallback clause to a segment + (whole utterance or sentence-chunk, §4.9) and stated the only + observable bus contract for partial-utterance failure is + `ovos.audio.output.ended` firing once the queue empties (§5.2). +- §5.3 — noted `is_speaking` is deliberately session-scoped; no + aggregate query exists in this version. - §4.0 (new) — one audio-format rule for all audio payloads: the container is the single source of truth (self-describing WAV / MP3 / OGG / FLAC); `mime` and `sample_rate` are OPTIONAL advisory fields on diff --git a/audio-out.md b/audio-out.md index 8ede27fd..8cb60d46 100644 --- a/audio-out.md +++ b/audio-out.md @@ -139,8 +139,15 @@ Language is taken from `data.lang` in the received Message (PIPELINE-1 §9.6); when absent, the service resolves it from the session (OVOS-SESSION-1 §3.2). -When synthesis fails, the service **SHOULD** attempt a fallback. -Selection and fallback logic are deployment concerns. +When synthesis fails for a segment — the whole utterance, or one +sentence-segmented chunk of it (§4.9) — the service **SHOULD** +attempt a fallback for that segment. Selection and fallback logic +are deployment concerns. Beyond that, this spec fixes no bus +contract for partial-utterance failure: whether a failed segment is +skipped, retried, or aborts the remaining segments is not +observable on the bus. The one guarantee is §5.2 — `ovos.audio.output.ended` +fires once the queue empties, whether it emptied by completing every +segment or by giving up on the failed ones. For `ovos.utterance.speak`, the synthesised audio is enqueued for local playback (§4). For `ovos.utterance.speak.b64`, the synthesised @@ -287,20 +294,27 @@ for decoding and playing it. headerless raw stream (§4.0). The session is identified via `context.session` as usual. A bridge -(OVOS-BRIDGE-1 §4.2.4) subscribes by `session_id` or `destination` +(OVOS-BRIDGE-1 §4.2.5) subscribes by `session_id` or `destination` and relays this message to the client. ### 4.4 Listen flag The `listen` field on `ovos.utterance.speak` is defined by -OVOS-PIPELINE-1 §9.6. When a received Message carries `listen: true`, -the audio output service **MUST** emit `ovos.mic.listen` after all -audio for that utterance has completed and after -`ovos.audio.output.ended` (§5.2). +OVOS-PIPELINE-1 §9.6. This timing — gated on `ovos.audio.output.ended` +— applies to the **local-playback path** (`ovos.utterance.speak`, +§3, §4.1). When a received Message carries `listen: true`, the audio +output service **MUST** emit `ovos.mic.listen` after all audio for +that utterance has completed and after `ovos.audio.output.ended` +(§5.2). On a stop-initiated end (§6), `ovos.mic.listen` is **NOT** emitted regardless of the `listen` flag. +The remote-client path (`ovos.utterance.speak.b64`) does not enqueue +into the scheduled queue and so never reaches `ovos.audio.output.ended`; +its `listen` handling is the exception fixed by §3.4, which emits +`ovos.mic.listen` immediately after `ovos.audio.speech`. + --- ## 5. Output lifecycle signals @@ -367,6 +381,9 @@ The service **MUST** reply via the `response` derivation |-------|------|----------|---------| | `speaking` | bool | yes | Whether audio is currently playing for the session identified by `context.session.session_id` of the request. | +`is_speaking` is deliberately session-scoped; this version defines +no aggregate query to ask whether any session is speaking. + --- ## 6. Stop integration @@ -391,6 +408,14 @@ The stop signal topics are: Both signals carry `context.session.session_id` (OVOS-MSG-1 §4). The audio output service **MAY** scope its response to that session. +**Barge-in is deployer policy.** Whether wake-word detection during +active playback interrupts that playback ("barge-in") is not fixed +by this spec. A controller MAY subscribe to `ovos.listener.wakeword` +(OVOS-AUDIO-IN-1 §6.5) and, on receipt while playback is in progress, +emit `ovos.audio.stop` to interrupt it. This spec mandates neither +that behaviour nor its absence — the audio output service's only +obligation on receiving a stop signal is the sequence above. + --- ## 7. Bus surface