#!/usr/bin/env python3 """STT worker subprocess — connects to stt.mm.mk via WebSocket. Receives PCM via UDP, sends to STT server. Posts JSON results back to Flask via HTTP POST. Usage: python3 stt_worker.py --audio-port 19876 --callback-url http://127.0.0.1:5000/internal/stt """ import argparse import json import socket import threading import urllib.request import websocket def main(): parser = argparse.ArgumentParser() parser.add_argument("url") parser.add_argument("--audio-port", type=int, default=19876) parser.add_argument("--callback-url", default="http://127.0.0.1:5000/internal/stt") args = parser.parse_args() connected = False ws = None def emit(obj): try: data = json.dumps(obj).encode("utf-8") req = urllib.request.Request( args.callback_url, data=data, headers={"Content-Type": "application/json"}, method="POST", ) urllib.request.urlopen(req, timeout=2) except Exception: pass def on_open(w): nonlocal connected connected = True emit({"type": "stt_status", "connected": True}) def on_message(w, message): try: emit(json.loads(message)) except Exception: pass def on_error(w, error): pass def on_close(w, code, msg): nonlocal connected connected = False emit({"type": "stt_status", "connected": False}) ws = websocket.WebSocketApp( args.url, on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close, ) ws_thread = threading.Thread( target=ws.run_forever, kwargs={"ping_interval": 20, "ping_timeout": 10}, daemon=True, ) ws_thread.start() # Listen for audio on UDP audio_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) audio_sock.bind(("127.0.0.1", args.audio_port)) audio_sock.settimeout(1.0) try: while True: try: data, _ = audio_sock.recvfrom(65536) except socket.timeout: continue except OSError: break if connected and ws and data: try: ws.send(data, opcode=0x2) except Exception: pass except KeyboardInterrupt: pass finally: if ws: ws.close() audio_sock.close() if __name__ == "__main__": main()