MCPcopy Create free account
hub / github.com/KoljaB/RealtimeVoiceChat / process_incoming_data

Function process_incoming_data

code/server.py:232–325  ·  view source on GitHub ↗

Receives messages via WebSocket, processes audio and text messages. Handles binary audio chunks, extracting metadata (timestamp, flags) and putting the audio PCM data with metadata into the `incoming_chunks` queue. Applies back-pressure if the queue is full. Parses text message

(ws: WebSocket, app: FastAPI, incoming_chunks: asyncio.Queue, callbacks: 'TranscriptionCallbacks')

Source from the content-addressed store, hash-verified

230# --------------------------------------------------------------------
231
232async def process_incoming_data(ws: WebSocket, app: FastAPI, incoming_chunks: asyncio.Queue, callbacks: 'TranscriptionCallbacks') -> None:
233 """
234 Receives messages via WebSocket, processes audio and text messages.
235
236 Handles binary audio chunks, extracting metadata (timestamp, flags) and
237 putting the audio PCM data with metadata into the `incoming_chunks` queue.
238 Applies back-pressure if the queue is full.
239 Parses text messages (assumed JSON) and triggers actions based on message type
240 (e.g., updates client TTS state via `callbacks`, clears history, sets speed).
241
242 Args:
243 ws: The WebSocket connection instance.
244 app: The FastAPI application instance (for accessing global state if needed).
245 incoming_chunks: An asyncio queue to put processed audio metadata dictionaries into.
246 callbacks: The TranscriptionCallbacks instance for this connection to manage state.
247 """
248 try:
249 while True:
250 msg = await ws.receive()
251 if "bytes" in msg and msg["bytes"]:
252 raw = msg["bytes"]
253
254 # Ensure we have at least an 8‑byte header: 4 bytes timestamp_ms + 4 bytes flags
255 if len(raw) < 8:
256 logger.warning("🖥️⚠️ Received packet too short for 8‑byte header.")
257 continue
258
259 # Unpack big‑endian uint32 timestamp (ms) and uint32 flags
260 timestamp_ms, flags = struct.unpack("!II", raw[:8])
261 client_sent_ns = timestamp_ms * 1_000_000
262
263 # Build metadata using fixed fields
264 metadata = {
265 "client_sent_ms": timestamp_ms,
266 "client_sent": client_sent_ns,
267 "client_sent_formatted": format_timestamp_ns(client_sent_ns),
268 "isTTSPlaying": bool(flags & 1),
269 }
270
271 # Record server receive time
272 server_ns = time.time_ns()
273 metadata["server_received"] = server_ns
274 metadata["server_received_formatted"] = format_timestamp_ns(server_ns)
275
276 # The rest of the payload is raw PCM bytes
277 metadata["pcm"] = raw[8:]
278
279 # Check queue size before putting data
280 current_qsize = incoming_chunks.qsize()
281 if current_qsize < MAX_AUDIO_QUEUE_SIZE:
282 # Now put only the metadata dict (containing PCM audio) into the processing queue.
283 await incoming_chunks.put(metadata)
284 else:
285 # Queue is full, drop the chunk and log a warning
286 logger.warning(
287 f"🖥️⚠️ Audio queue full ({current_qsize}/{MAX_AUDIO_QUEUE_SIZE}); dropping chunk. Possible lag."
288 )
289

Callers 1

websocket_endpointFunction · 0.85

Calls 5

format_timestamp_nsFunction · 0.85
parse_json_messageFunction · 0.85
applyMethod · 0.80
update_settingsMethod · 0.80
resetMethod · 0.45

Tested by

no test coverage detected