Sam4rano's picture
Deploy Yoruba ASR backend (code only)
71cf6b9
Raw
History Blame Contribute Delete
4.67 kB
import asyncio
import websockets
import json
import librosa
import numpy as np
import os
import argparse
import sys
async def stream_file(audio_path, uri):
if not os.path.exists(audio_path):
print(f"Error: {audio_path} not found.")
return
print(f"Loading and resampling {audio_path} to 16kHz...")
y, sr = librosa.load(audio_path, sr=16000)
audio_int16 = (y * 32767).astype(np.int16)
audio_bytes = audio_int16.tobytes()
print(f"Connecting to server at {uri}...")
try:
async with websockets.connect(uri) as websocket:
print("Connected successfully. Starting file stream...")
chunk_samples = 1024
chunk_bytes_size = chunk_samples * 2
async def send_audio():
for idx in range(0, len(audio_bytes), chunk_bytes_size):
chunk = audio_bytes[idx:idx + chunk_bytes_size]
await websocket.send(chunk)
await asyncio.sleep(chunk_samples / 16000)
await websocket.send(b"")
print("Finished streaming all audio bytes. Waiting for final transcript...")
async def receive_transcripts():
try:
async for message in websocket:
data = json.loads(message)
if "text" in data:
print(f"\n[ASR Stream Result]: {data['text']}")
except websockets.exceptions.ConnectionClosed:
print("\nConnection closed by server.")
await asyncio.gather(send_audio(), receive_transcripts())
except Exception as e:
print(f"Error: {e}")
async def stream_mic(uri):
try:
import sounddevice as sd
except ImportError:
print("Error: sounddevice library is required for live recording. Run: pip install sounddevice")
return
print(f"Connecting to server at {uri}...")
try:
async with websockets.connect(uri) as websocket:
print("Connected successfully!")
print("Recording from microphone... SPEAK YORUBA NOW! Press Ctrl+C to stop.")
audio_queue = asyncio.Queue()
loop = asyncio.get_running_loop()
def callback(indata, frames, time, status):
if status:
print(f"Status check: {status}", file=sys.stderr)
loop.call_soon_threadsafe(audio_queue.put_nowait, indata.copy())
# Start the sounddevice InputStream (16kHz, mono, int16)
stream = sd.InputStream(
samplerate=16000,
channels=1,
dtype='int16',
blocksize=1024,
callback=callback
)
with stream:
async def send_mic_audio():
try:
while True:
indata = await audio_queue.get()
await websocket.send(indata.tobytes())
except asyncio.CancelledError:
await websocket.send(b"")
print("Microphone recording stopped.")
async def receive_transcripts():
try:
async for message in websocket:
data = json.loads(message)
if "text" in data:
print(f"\n[ASR Stream Result]: {data['text']}")
except websockets.exceptions.ConnectionClosed:
print("\nConnection closed by server.")
send_task = asyncio.create_task(send_mic_audio())
receive_task = asyncio.create_task(receive_transcripts())
await asyncio.gather(send_task, receive_task, return_exceptions=True)
except Exception as e:
print(f"Microphone stream error: {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Yoruba Streaming ASR Client")
parser.add_argument("--mic", action="store_true", help="Use live microphone instead of a file")
parser.add_argument("--file", type=str, default="test_unfinetuned_yo.wav", help="Audio file path to stream (default: test_unfinetuned_yo.wav)")
parser.add_argument("--uri", type=str, default="ws://localhost:8000/stream", help="WebSocket URI (default: ws://localhost:8000/stream)")
args = parser.parse_args()
if args.mic:
asyncio.run(stream_mic(args.uri))
else:
asyncio.run(stream_file(args.file, args.uri))