- Created AGENTS.md with architecture documentation - Fixed race conditions and async patterns - Added conversation history to LLM prompts - Fixed TTS audio shape handling - Added buffer limits and graceful shutdown - Fixed client.py with file sending support - Removed duplicate requirements - Added .gitignore
51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
import threading
|
|
import time
|
|
from config import Config
|
|
|
|
|
|
class AudioStreamBuffer:
|
|
def __init__(self):
|
|
self.config = Config()
|
|
self.buffer = b""
|
|
self.lock = threading.Lock()
|
|
self.event = threading.Event()
|
|
self.running = False
|
|
# Limit buffer to 10 seconds of audio to prevent OOM
|
|
self.max_buffer_bytes = int(self.config.SAMPLE_RATE * 10 * 2)
|
|
|
|
def start(self):
|
|
self.running = True
|
|
self.buffer = b""
|
|
self.event.clear()
|
|
|
|
def add_chunk(self, chunk: bytes):
|
|
with self.lock:
|
|
self.buffer += chunk
|
|
# Evict oldest data if buffer exceeds limit
|
|
if len(self.buffer) > self.max_buffer_bytes:
|
|
self.buffer = self.buffer[-self.max_buffer_bytes // 2:]
|
|
if len(self.buffer) >= self.config.CHUNK_SIZE:
|
|
self.event.set()
|
|
|
|
def get_ready_chunk(self, timeout: float = 1.0) -> bytes:
|
|
if self.event.wait(timeout=timeout):
|
|
with self.lock:
|
|
chunk = self.buffer
|
|
self.buffer = b""
|
|
self.event.clear()
|
|
return chunk
|
|
return b""
|
|
|
|
def get_full_buffer(self) -> bytes:
|
|
with self.lock:
|
|
chunk = self.buffer
|
|
self.buffer = b""
|
|
return chunk
|
|
|
|
def stop(self):
|
|
self.running = False
|
|
self.event.set()
|
|
|
|
def is_running(self):
|
|
return self.running
|