(audioChunk: Buffer)
| 197 | // to onReady when the WebSocket opens. |
| 198 | const connection: VoiceStreamConnection = { |
| 199 | send(audioChunk: Buffer): void { |
| 200 | if (ws.readyState !== WebSocket.OPEN) { |
| 201 | return |
| 202 | } |
| 203 | if (finalized) { |
| 204 | // After CloseStream has been sent, the server rejects further audio. |
| 205 | // Drop the chunk to avoid a protocol error. |
| 206 | logForDebugging( |
| 207 | `[voice_stream] Dropping audio chunk after CloseStream: ${String(audioChunk.length)} bytes`, |
| 208 | ) |
| 209 | return |
| 210 | } |
| 211 | logForDebugging( |
| 212 | `[voice_stream] Sending audio chunk: ${String(audioChunk.length)} bytes`, |
| 213 | ) |
| 214 | // Copy the buffer before sending: NAPI Buffer objects from native |
| 215 | // modules may share a pooled ArrayBuffer. Creating a view with |
| 216 | // `new Uint8Array(buf.buffer, offset, len)` can reference stale or |
| 217 | // overlapping memory by the time the ws library reads it. |
| 218 | // `Buffer.from()` makes an owned copy that the ws library can safely |
| 219 | // consume as a binary WebSocket frame. |
| 220 | ws.send(Buffer.from(audioChunk)) |
| 221 | }, |
| 222 | finalize(): Promise<FinalizeSource> { |
| 223 | if (finalizing || finalized) { |
| 224 | // Already finalized or WebSocket already closed — resolve immediately. |
nothing calls this directly
no test coverage detected