Skip to content

iOS glasses WebRTC client + Mac-mic agent input#2

Open
J4Joshua wants to merge 1 commit into
mainfrom
glasses-webrtc-audio
Open

iOS glasses WebRTC client + Mac-mic agent input#2
J4Joshua wants to merge 1 commit into
mainfrom
glasses-webrtc-audio

Conversation

@J4Joshua

Copy link
Copy Markdown
Owner

Adds the iOS glasses app and wires audio into the CourtLine agent over WebRTC.

Architecture

Human speaks → MacBook mic → agent (bot-courtline.py, MAC_MIC_INPUT=1)
   → NVidia STT → vLLM → Gradium TTS → SmallWebRTCTransport.output()
   → WebRTC → iOS app (receive-only) → Bluetooth HFP → 🕶️ glasses speaker

Why this shape: WebRTC on iOS can't reliably capture the Bluetooth-HFP glasses mic (it routes to HFP but no samples reach the server), and iOS WebRTC has no supported hook to inject externally-captured PCM into an audio track. So the agent listens via the Mac mic and speaks through the glasses — the output leg is verified working end-to-end.

Changes

  • ios/ — Meta Ray-Ban Display glasses app (DAT SDK). WebRTCAudioSpike.swift is a Pipecat SmallWebRTC client that connects receive-only (enableMic = false) to the agent's /api/offer and plays the agent's voice through the glasses' HFP speaker. See ios/README.md.
  • bot-courtline.py — optional Mac-microphone input behind MAC_MIC_INPUT=1: captures the local mic (sounddevice) and feeds InputAudioRawFrames into the pipeline. No-op when unset, so the existing browser/WebRTC audio-in path is unaffected.
  • pyproject.toml / uv.lock — add sounddevice.

Verified

  • ✅ iOS app compiles against the real SDKs (PipecatClientIOS / SmallWebRTC / WebRTC 134) — xcodebuild -sdk iphonesimulator → BUILD SUCCEEDED.
  • ✅ Agent audio → glasses speaker proven on-device (downlink over WebRTC, peer-to-peer on a LAN).
  • ✅ Mac-mic capture → Pipecat frames verified standalone; bot-courtline.py syntax-checks.

Pending (needs the agent's API keys / on-stack run — not CI-able)

  • ⏳ Full Mac-mic → STT → LLM → TTS → glasses loop (Gradium / NVIDIA / OpenAI keys).
  • ⏳ Glasses video → vision (check_camera) — the legacy WebSocket video path is left as a placeholder.

Setup

Server: cd yc-voice-agents-hackathon/server && uv sync && MAC_MIC_INPUT=1 uv run main.py
iOS: set webRTCServerURL (in WebRTCAudioSpike.swift) to the Mac's LAN IP:7860, build on a device on the same Wi-Fi.

Network: peer-to-peer WebRTC needs a routable media path (same LAN, or a TURN server on isolated networks). A Cloudflare HTTP tunnel won't carry the UDP media.

🤖 Generated with Claude Code

ios/: Meta Ray-Ban glasses app (DAT SDK) with a Pipecat SmallWebRTC client
(WebRTCAudioSpike) that connects receive-only to the agent's /api/offer and
plays the agent's voice out through the glasses' Bluetooth-HFP speaker.

server (bot-courtline.py): optional Mac-microphone input (MAC_MIC_INPUT=1)
that feeds InputAudioRawFrames into the pipeline, so the agent listens via the
Mac while speaking back over WebRTC to the glasses. No-op when the flag is
unset, so the existing browser/WebRTC audio-in path is unaffected. Adds the
sounddevice dependency (pyproject + uv.lock).

Rationale: WebRTC on iOS can't reliably capture the Bluetooth-HFP glasses mic
(and offers no PCM-injection hook for audio), so we capture audio on the Mac
and use the glasses for the agent's voice output — which is verified working.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant