Files
Qwen3-tts/docker/ws_log_proxy.py
2026-06-19 17:23:38 +02:00

85 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""Logging WebSocket proxy for Qwen3-TTS streaming calls."""
import argparse
import asyncio
import datetime as dt
import json
import websockets
def now():
return dt.datetime.now().isoformat(timespec="seconds")
def shorten(value, limit=500):
text = value if isinstance(value, str) else repr(value)
return text if len(text) <= limit else text[:limit] + "..."
async def proxy(client_ws, upstream_url):
conn_id = f"ws-{id(client_ws):x}"
print(f"[{now()}] {conn_id} open -> {upstream_url}", flush=True)
async with websockets.connect(upstream_url, max_size=None) as upstream_ws:
async def client_to_upstream():
async for msg in client_ws:
if isinstance(msg, str):
try:
data = json.loads(msg)
typ = data.get("type")
if typ == "session.config":
log_data = dict(data)
if "speaker_embedding" in log_data:
emb = log_data["speaker_embedding"] or []
log_data["speaker_embedding"] = f"<{len(emb)} floats>"
print(f"[{now()}] {conn_id} C->S config {json.dumps(log_data, ensure_ascii=False, sort_keys=True)}", flush=True)
elif typ == "input.text":
print(f"[{now()}] {conn_id} C->S text {data.get('text')!r}", flush=True)
else:
print(f"[{now()}] {conn_id} C->S {shorten(msg)}", flush=True)
except Exception:
print(f"[{now()}] {conn_id} C->S {shorten(msg)}", flush=True)
else:
print(f"[{now()}] {conn_id} C->S binary {len(msg)} bytes", flush=True)
await upstream_ws.send(msg)
async def upstream_to_client():
async for msg in upstream_ws:
if isinstance(msg, str):
try:
data = json.loads(msg)
print(f"[{now()}] {conn_id} S->C {data}", flush=True)
except Exception:
print(f"[{now()}] {conn_id} S->C {shorten(msg)}", flush=True)
else:
print(f"[{now()}] {conn_id} S->C binary {len(msg)} bytes", flush=True)
await client_ws.send(msg)
await asyncio.gather(client_to_upstream(), upstream_to_client())
async def handler(client_ws):
try:
await proxy(client_ws, handler.upstream_url)
except Exception as exc:
print(f"[{now()}] proxy error: {exc}", flush=True)
try:
await client_ws.close()
except Exception:
pass
async def main():
parser = argparse.ArgumentParser()
parser.add_argument("--host", default="0.0.0.0")
parser.add_argument("--port", type=int, default=8094)
parser.add_argument("--upstream", default="ws://localhost:8091/v1/audio/speech/stream")
args = parser.parse_args()
handler.upstream_url = args.upstream
print(f"WS log proxy: ws://{args.host}:{args.port}/v1/audio/speech/stream -> {args.upstream}", flush=True)
async with websockets.serve(handler, args.host, args.port, max_size=None):
await asyncio.Future()
if __name__ == "__main__":
asyncio.run(main())