import asyncio
import json
import struct
import sys
import wave
try:
import websockets
except ImportError:
print("Install: pip install websockets")
sys.exit(1)
async def transcribe(wav_path: str, server: str = "ws://127.0.0.1:9876/ws"):
async with websockets.connect(server) as ws:
msg = json.loads(await ws.recv())
assert msg["type"] == "ready", f"Expected ready, got {msg}"
print(f"Connected: {msg['model']} @ {msg['sample_rate']}Hz")
with wave.open(wav_path, "rb") as wf:
assert wf.getnchannels() == 1, "Expected mono audio"
assert wf.getsampwidth() == 2, "Expected 16-bit audio"
rate = wf.getframerate()
frames = wf.readframes(wf.getnframes())
if rate != 16000:
print(f"Warning: audio is {rate}Hz, server expects 16000Hz")
chunk_samples = 8000 chunk_bytes = chunk_samples * 2
for i in range(0, len(frames), chunk_bytes):
await ws.send(frames[i : i + chunk_bytes])
await asyncio.sleep(0.05)
await ws.close()
print("Done.")
async def stream_and_print(wav_path: str, server: str = "ws://127.0.0.1:9876/ws"):
async with websockets.connect(server) as ws:
msg = json.loads(await ws.recv())
print(f"Connected: {msg['model']} @ {msg['sample_rate']}Hz\n")
async def receiver():
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "partial":
print(f"\r ... {msg['text']}", end="", flush=True)
elif msg["type"] == "final":
print(f"\r >>> {msg['text']}")
elif msg["type"] == "error":
print(f"\n ERR: {msg['message']}")
recv_task = asyncio.create_task(receiver())
with wave.open(wav_path, "rb") as wf:
frames = wf.readframes(wf.getnframes())
chunk_bytes = 16000 for i in range(0, len(frames), chunk_bytes):
await ws.send(frames[i : i + chunk_bytes])
await asyncio.sleep(0.1)
await asyncio.sleep(1) recv_task.cancel()
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <audio.wav> [ws://host:port]")
sys.exit(1)
wav = sys.argv[1]
server = sys.argv[2] if len(sys.argv) > 2 else "ws://127.0.0.1:9876/ws"
asyncio.run(stream_and_print(wav, server))