diff dictation/webrtc_smoke.py @ 275:78699f810817

Add Qwen3-VL and WebRTC dictation services Add Bazel targets for the CUDA-backed Qwen3-VL server and a local WebRTC faster-whisper dictation service. Co-authored-by: Copilot <[email protected]> Copilot-Session: e3d8cb06-6c95-4ae0-9757-651d3796ab00
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 10:58:47 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dictation/webrtc_smoke.py	Mon Aug 17 10:58:47 2026 -0700
@@ -0,0 +1,70 @@
+from __future__ import annotations
+
+import argparse
+import asyncio
+import json
+
+from aiortc import RTCPeerConnection, RTCSessionDescription
+from aiortc.contrib.media import MediaPlayer
+import httpx
+
+
+async def run(server_url: str, audio_path: str, timeout: float) -> None:
+    peer = RTCPeerConnection()
+    channel = peer.createDataChannel("transcripts")
+    player = MediaPlayer(audio_path)
+    if player.audio is None:
+        raise RuntimeError("Input file does not contain an audio track")
+    peer.addTrack(player.audio)
+    final_received = asyncio.Event()
+    session_id = None
+
+    @channel.on("message")
+    def on_message(message):
+        event = json.loads(message)
+        print(json.dumps(event, ensure_ascii=False), flush=True)
+        if event.get("type") == "transcript.final":
+            final_received.set()
+
+    try:
+        offer = await peer.createOffer()
+        await peer.setLocalDescription(offer)
+        async with httpx.AsyncClient(timeout=timeout) as client:
+            response = await client.post(
+                f"{server_url}/api/webrtc/offer",
+                json={
+                    "sdp": peer.localDescription.sdp,
+                    "type": peer.localDescription.type,
+                },
+            )
+            response.raise_for_status()
+            answer = response.json()
+            session_id = answer["sessionId"]
+            await peer.setRemoteDescription(
+                RTCSessionDescription(
+                    sdp=answer["sdp"],
+                    type=answer["type"],
+                )
+            )
+            await asyncio.wait_for(final_received.wait(), timeout=timeout)
+            await client.post(
+                f"{server_url}/api/webrtc/session/{session_id}/close"
+            )
+    finally:
+        await peer.close()
+
+
+def main() -> None:
+    parser = argparse.ArgumentParser()
+    parser.add_argument("audio")
+    parser.add_argument(
+        "--server",
+        default="http://127.0.0.1:8090",
+    )
+    parser.add_argument("--timeout", type=float, default=60.0)
+    args = parser.parse_args()
+    asyncio.run(run(args.server.rstrip("/"), args.audio, args.timeout))
+
+
+if __name__ == "__main__":
+    main()