| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- #!/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 <ws_url> --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()
|