Pace Talk audio over gateway relay

This commit is contained in:
Mikei386
2026-09-03 23:00:56 +02:00
parent 0a68df22eb
commit df41175960
4 changed files with 13 additions and 2 deletions
+4
View File
@@ -235,7 +235,11 @@ class AthenaTalkBridge {
return; return;
const frameBytes = 24000 * 2 / 50; const frameBytes = 24000 * 2 / 50;
for (let offset = 0; offset < pcm.length; offset += frameBytes) { for (let offset = 0; offset < pcm.length; offset += frameBytes) {
if (controller.signal.aborted || generation !== this.generation || !this.isConnected()) {
return;
}
this.req.onAudio?.(pcm.subarray(offset, Math.min(offset + frameBytes, pcm.length))); this.req.onAudio?.(pcm.subarray(offset, Math.min(offset + frameBytes, pcm.length)));
await new Promise((resolve) => setTimeout(resolve, 20));
} }
this.req.onResponseDone?.({ status: "completed", responseId }); this.req.onResponseDone?.({ status: "completed", responseId });
this.req.onEvent?.({ direction: "server", type: "response.done", responseId }); this.req.onEvent?.({ direction: "server", type: "response.done", responseId });
@@ -243,7 +243,14 @@ class AthenaTalkBridge {
if (generation !== this.generation || !this.isConnected()) return; if (generation !== this.generation || !this.isConnected()) return;
const frameBytes = 24000 * 2 / 50; const frameBytes = 24000 * 2 / 50;
for (let offset = 0; offset < pcm.length; offset += frameBytes) { for (let offset = 0; offset < pcm.length; offset += frameBytes) {
if (controller.signal.aborted || generation !== this.generation || !this.isConnected()) {
return;
}
this.req.onAudio?.(pcm.subarray(offset, Math.min(offset + frameBytes, pcm.length))); this.req.onAudio?.(pcm.subarray(offset, Math.min(offset + frameBytes, pcm.length)));
// Gateway relay drops audio frames when its WebSocket queue is full.
// Pace 20 ms PCM frames in realtime instead of flooding the complete
// synthesized response into the socket in a few milliseconds.
await new Promise((resolve) => setTimeout(resolve, 20));
} }
this.req.onResponseDone?.({ status: "completed", responseId }); this.req.onResponseDone?.({ status: "completed", responseId });
this.req.onEvent?.({ direction: "server", type: "response.done", responseId }); this.req.onEvent?.({ direction: "server", type: "response.done", responseId });
@@ -2,7 +2,7 @@
"id": "athena-talk", "id": "athena-talk",
"name": "Athena Local Talk", "name": "Athena Local Talk",
"description": "Local German voice conversations through Athena without a public speech provider.", "description": "Local German voice conversations through Athena without a public speech provider.",
"version": "0.1.0", "version": "0.1.1",
"enabledByDefault": true, "enabledByDefault": true,
"activation": { "activation": {
"onStartup": true, "onStartup": true,
@@ -1,6 +1,6 @@
{ {
"name": "openclaw-plugin-athena-talk", "name": "openclaw-plugin-athena-talk",
"version": "0.1.0", "version": "0.1.1",
"description": "Private realtime Talk bridge for Athena STT, OpenClaw agent consult, and Athena TTS.", "description": "Private realtime Talk bridge for Athena STT, OpenClaw agent consult, and Athena TTS.",
"type": "module", "type": "module",
"private": true, "private": true,