Architecture and implementation

August 10, 2026 · View on GitHub

English | 简体中文

Architecture and implementation

┌─────────────────────┐                    ┌─────────────────────────────────────┐
│  Client / SDK / SIP │                    │      StreamCore Runtime (Go)        │
│                     │                    │                                     │
│  Mic → WebRTC ──────┼──── Opus RTP ──────┼──→ Opus decode → VAD → STT          │
│  Speaker ← WebRTC ←─┼──── Opus RTP ←─────┼──← Opus encode ← TTS                │
│                     │                    │               │                     │
│  HTTP POST ─────────┼── WHIP (SDP) ──────┼──→ Peer + session created           │
│  DataChannel ◄──────┼──── events   ←─────┼──← transcript · response · state    │
│                     │                    │               │                     │
│                     │                    │               ├── your LLM client   │
│                     │                    │               ├── RAG context       │
│                     │                    │               ├── Skills prompt     │
│                     │                    │               ├── Plugin runtime    │
│                     │                    │               │   ├── Python        │
│                     │                    │               │   ├── TypeScript    │
│                     │                    │               │   └── JavaScript    │
│                     │                    │               └── Native Go tools   │
└─────────────────────┘                    └─────────────────────────────────────┘

Media flow. Microphone audio arrives over WebRTC, is decoded to PCM in 20 ms frames, run through VAD, and streamed to STT. Final transcripts go to the model layer; streamed output is split on sentence boundaries and handed to TTS as it arrives, so synthesis starts before generation finishes. Synthesized PCM is encoded back to Opus and written to the RTP stream. Transcript, response, and state text travel over the DataChannel in parallel.

Why Go. The latency-sensitive path is implemented in Go with Pion: goroutines per stage, bounded channels between them, and no GC-heavy buffering in the hot loop. RTP read, Opus decode, VAD, STT streaming, orchestration, TTS, Opus encode, and RTP write are each their own stage. This is an implementation choice in service of predictable turn latency — the surface you build against is the SDKs and the event protocol, in whatever language you prefer.

Package layout

PackageResponsibility
internal/signalingWHIP handler, SDP exchange, session URLs
internal/peerPion peer connection, tracks, DataChannel
internal/sessionSession manager, multi-peer lifecycle
internal/pipelineInbound/outbound audio, agent loop, barge-in, thinking sound
internal/audioOpus codec, RTP framing
internal/vadEnergy-based voice activity detection
internal/stt, internal/tts, internal/llmProvider adapters
internal/pluginPlugin runtime, native tools, skills
internal/ragRetrieval and embeddings
internal/turnBuilt-in STUN/TURN server

Wire-level details: Protocol reference.