#!/usr/bin/env python3 """STT worker subprocess — connects to stt.mm.mk via WebSocket. Reads raw PCM int16 binary chunks from stdin, sends to STT server. Writes JSON messages (one per line) to stdout. Usage: python3 stt_worker.py """ import json import sys import threading import time import websocket def main(): if len(sys.argv) < 2: sys.exit(1) url = sys.argv[1] connected = False ws = None def on_open(w): nonlocal connected connected = True _emit({"type": "stt_status", "connected": True}) def on_message(w, message): try: msg = json.loads(message) _emit(msg) except Exception: pass def on_error(w, error): _emit({"type": "stt_error", "error": str(error)}) def on_close(w, code, msg): nonlocal connected connected = False _emit({"type": "stt_status", "connected": False}) def _emit(obj): try: line = json.dumps(obj, ensure_ascii=True) sys.stdout.write(line + "\n") sys.stdout.flush() except Exception: pass ws = websocket.WebSocketApp( url, on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close, ) # Run WebSocket in background thread ws_thread = threading.Thread( target=ws.run_forever, kwargs={"ping_interval": 20, "ping_timeout": 10}, daemon=True, ) ws_thread.start() # Read PCM chunks from stdin and forward to WebSocket try: while True: # Read 4-byte length prefix, then that many bytes of PCM header = sys.stdin.buffer.read(4) if not header or len(header) < 4: break length = int.from_bytes(header, "little") if length <= 0 or length > 1_000_000: continue data = sys.stdin.buffer.read(length) if not data or len(data) < length: break if connected and ws: try: ws.send(data, opcode=0x2) except Exception: pass except (BrokenPipeError, KeyboardInterrupt): pass finally: if ws: ws.close() if __name__ == "__main__": main()