Split View: WebRTC 미디어 인프라 2026 — LiveKit·Pion·Daily·100ms·mediasoup·Janus·Cloudflare Realtime와 WHIP/WHEP 심층 탐구
WebRTC 미디어 인프라 2026 — LiveKit·Pion·Daily·100ms·mediasoup·Janus·Cloudflare Realtime와 WHIP/WHEP 심층 탐구
프롤로그 — WebRTC는 인프라 선택이 90%다
2018년 WebRTC는 "브라우저에서 P2P 영상통화를 어떻게 짜는가"의 문제였다. STUN/TURN 서버 한 대, RTCPeerConnection 코드 200줄, 그리고 영상 두 칸짜리 데모 페이지. 끝.
2026년의 WebRTC는 다른 문제다.
- 100명짜리 룸을 어떻게 굴리지? — SFU(Selective Forwarding Unit)가 답이다. P2P 메시는 N제곱이라 5명에서 무너진다.
- AI 음성 에이전트는 어떻게 붙이지? — LLM의 출력 토큰을 TTS로, 마이크 오디오를 STT로, 모두 200ms 지연 내에. WebRTC의 강점이다.
- 라이브 송출은 어떻게? — RTMP는 옛날 코덱(H.264만)에, 지연도 2~5초다. WHIP(WebRTC-HTTP Ingestion Protocol)/WHEP(WebRTC-HTTP Egress Protocol)가 새 표준으로 올라섰다.
- 우리는 매니지드(Daily·100ms·Twilio·Chime)를 쓸까, 자가 호스트(LiveKit OSS·mediasoup·Janus·Jitsi)를 쓸까?
이 글은 "WebRTC 코드 200줄"이 아니라 "프로덕션 미디어 인프라를 어디서 어떻게 굴리느냐"를 다룬다. 이 결정 한 번이 6개월 뒤의 인프라 비용·지연·운영 부담을 결정한다.
요약: 2026년 5월 기준 큰 그림은 이렇다.
- LiveKit이 AI 음성 에이전트 인프라의 사실상 표준이 됐다. LiveKit Agents 프레임워크는 OpenAI Realtime API·Deepgram·ElevenLabs와 일급으로 통합된다.
- Pion이 Go 진영의 WebRTC 엔진으로 굳어졌다. LiveKit 자체도 Pion 위에 올려져 있다.
- WHIP/WHEP가 RTMP를 대체하는 라이브 송출 표준으로 정착했다. OBS 30+이 WHIP 송출을 기본 지원한다.
- 매니지드 진영(Daily·100ms·Twilio Video·AWS Chime SDK)은 살아 있지만 가격 압박이 거세다. LiveKit Cloud가 1라운드 강자.
- Cloudflare Realtime이 엣지에서 WebRTC를 던지며 새 카테고리를 만들었다. Calls API + Realtime SFU.
자, 출발한다.
1장 · WebRTC 인프라의 풍경 — 2026년 지도
먼저 분류. 모두가 같은 자리에 있지 않다.
| 카테고리 | 대표 제품 | 한 줄 요약 |
|---|---|---|
| AI 음성·영상 인프라(매니지드+OSS) | LiveKit Cloud / LiveKit OSS | 2026년 음성 에이전트 표준. Agents 프레임워크. |
| 매니지드 비디오 API | Daily.co, 100ms, Twilio Video, AWS Chime SDK, Vonage | SDK·매니지드 SFU. 빠른 출시. |
| 엣지 WebRTC | Cloudflare Realtime / Calls | 글로벌 엣지 SFU. 새 카테고리. |
| 자가 호스트 SFU(Node.js) | mediasoup | 라이브러리 형태. 직접 시그널링 짠다. |
| 자가 호스트 SFU(C) | Janus | 플러그인 아키텍처. OG. |
| 풀스택 OSS | Jitsi (Meet/Videobridge) | 다운로드 후 쓰는 미팅 솔루션 + SFU. |
| WebRTC 엔진(Go) | Pion | Go에서 WebRTC를 짤 수 있게 한 라이브러리. |
| WebRTC 엔진(Rust) | webrtc-rs | Pion의 Rust 포팅. 성장 중. |
| 라이브 송출 표준 | WHIP / WHEP | HTTP 한 번에 WebRTC 세션 시작. RTMP 대체. |
이 글의 초점은 굵게 갈리는 LiveKit·Pion·Daily·100ms·mediasoup·Janus·Jitsi·Twilio·Chime·Cloudflare Realtime이다. WHIP/WHEP는 별도 장에서 따로 다룬다.
왜 LiveKit이 표준이 됐는가
- AI 음성 에이전트 시대의 1등 인프라. LiveKit Agents 프레임워크가 OpenAI Realtime·Deepgram STT·ElevenLabs TTS·Cartesia와 일급 통합.
- OSS와 클라우드(LiveKit Cloud) 양 진영을 동시에 굴린다. 자가 호스트로 시작해서 클라우드로 갈아탈 수 있다.
- Pion 위에 짜져서 Go 단일 바이너리. 쿠버네티스·도커 배포가 단순.
- LiveKit의 클라이언트 SDK(JS·Swift·Kotlin·Flutter·Unity·React Native)가 잘 정리돼 있다.
2장 · 7축으로 보는 비교 매트릭스
상세 분석으로 들어가기 전, 한눈에 보는 큰 그림.
| 축 | LiveKit | Daily | 100ms | mediasoup | Janus | Jitsi | Twilio Video | AWS Chime SDK | Cloudflare Realtime |
|---|---|---|---|---|---|---|---|---|---|
| 운영 모델 | 매니지드+OSS | 매니지드 | 매니지드 | OSS 라이브러리 | OSS 데몬 | OSS 풀스택 | 매니지드 | 매니지드 | 매니지드(엣지) |
| 언어 | Go(Pion) | 비공개 | 비공개 | Node.js+C++ | C | Java+C(libwebrtc) | 비공개 | 비공개 | 비공개 |
| AI 음성 통합 | 일급 (Agents) | 좋음 | 좋음 | 직접 | 직접 | 직접 | 보통 | 좋음 (Voice Focus) | 직접 |
| WHIP/WHEP | 일급 지원 | 지원 | 지원 | 플러그인 | 플러그인 | 외부 도구 | 미지원 | 미지원 | 일급 지원 |
| 글로벌 라우팅 | 클라우드에서 일급 | 일급 | 일급 | 직접 | 직접 | 직접 | 일급 | 일급 | 일급(엣지) |
| 가격 압박 | 강함(OSS+클라우드) | 보통 | 보통 | 인프라 비용만 | 인프라 비용만 | 인프라 비용만 | 비쌈 | 비쌈 | 새로움 |
| 신규 채택 추이 | 매우 강함 | 안정 | 강함(인도 시장) | 안정 | 감소 | 안정 | 감소 | 안정 | 빠른 성장 |
이 표만 보고 결정을 내려선 안 된다. 다음 장부터 각 도구를 정확히 무엇이 되고 안 되는지 짚는다.
3장 · LiveKit — 표준이 된 이유, 그리고 LiveKit Agents
LiveKit은 2021년 출범 이래 가장 빠르게 자리잡은 WebRTC 인프라다. OSS(Apache 2.0)와 LiveKit Cloud 양 진영을 동시에 굴린다. 2025~2026 사이 결정적인 사건이 둘이었다.
- LiveKit Agents 프레임워크 — Python/Node SDK로 LLM·STT·TTS·VAD를 묶어 음성 에이전트를 만든다. OpenAI Realtime API·Deepgram·AssemblyAI·ElevenLabs·Cartesia 등이 일급 통합.
- OpenAI가 LiveKit을 공식 채택 — ChatGPT 음성 모드 인프라가 LiveKit 위에 올라간다는 사실이 공개됐다. 사실상 산업 표준 도장.
왜 LiveKit이 강한가
- 단일 Go 바이너리 —
livekit-server한 개. Pion 기반. 도커 한 줄로 띄운다. - 클라이언트 SDK 풀 — JS, Swift, Kotlin, Flutter, Unity, React Native, Python. 모두 같은 추상화(
Room,Participant,Track). - Egress·Ingress 서비스 — 녹화(MP4·HLS), 스트림 추출(WHIP/WHEP 인제스트), 트랜스코드까지 모듈로 분리.
@livekit/components-react— 미팅 UI를 30분에 짤 수 있는 사전 빌트 컴포넌트.- LiveKit Cloud — 자가 호스트 운영이 부담스러우면 같은 API로 갈아탄다. SLA·글로벌 라우팅 포함.
LiveKit Agents 스켈레톤
음성 에이전트 한 개의 가장 단순한 모양. 이 코드는 마이크 입력을 OpenAI Realtime로 보내고, 모델의 응답 오디오를 룸으로 도로 송출한다.
# agent.py — LiveKit Agents 최소 스켈레톤
import asyncio
import os
from livekit import agents, rtc
from livekit.agents import AgentSession, Agent
from livekit.plugins import openai, deepgram, elevenlabs, silero
class VoiceAssistant(Agent):
def __init__(self) -> None:
super().__init__(
instructions=(
"You are a friendly voice assistant. "
"Answer in short, conversational sentences."
),
)
async def on_enter(self) -> None:
# 인사말 자동 송출
await self.session.say("안녕하세요. 무엇을 도와드릴까요?")
async def entrypoint(ctx: agents.JobContext) -> None:
await ctx.connect() # 룸에 합류
session = AgentSession(
# 1) STT — Deepgram nova-3
stt=deepgram.STT(model="nova-3"),
# 2) LLM — OpenAI Realtime(또는 일반 chat completions)
llm=openai.LLM(model="gpt-4o-mini"),
# 3) TTS — ElevenLabs
tts=elevenlabs.TTS(voice_id="Rachel"),
# 4) VAD — Silero 음성 활성 감지(턴 결정)
vad=silero.VAD.load(),
)
await session.start(
agent=VoiceAssistant(),
room=ctx.room,
)
if __name__ == "__main__":
agents.cli.run_app(
agents.WorkerOptions(entrypoint_fnc=entrypoint),
)
배포는 python agent.py dev로 로컬에서 띄우고, 그대로 python agent.py start로 프로덕션 모드. LiveKit 서버가 새 룸을 만들면 Agents 워커가 자동으로 매칭되어 합류한다.
OpenAI Realtime + WebRTC 직결 모드
OpenAI Realtime API는 2024년 출시 당시 WebSocket 전용이었다. 2025년 WebRTC 연결 모드가 추가됐다. 클라이언트가 SDP를 만들어 OpenAI 엔드포인트에 직접 던지면, 모델이 SFU처럼 응답한다. 지연이 200~400ms로 떨어진다.
LiveKit Agents는 이 두 가지를 모두 추상화한다.
# OpenAI Realtime을 WebRTC 직결로 쓰는 모양
from livekit.plugins import openai
session = AgentSession(
llm=openai.realtime.RealtimeModel(
model="gpt-4o-realtime-preview",
voice="alloy",
# WebRTC 모드 — 별도 STT/TTS 필요 없음
modalities=["audio", "text"],
),
)
이 모드에선 STT/TTS가 따로 필요 없다. 모델이 직접 오디오 입출력을 처리한다. 단점은 가격이 높고, 모델 선택이 OpenAI Realtime 계열로 제한된다는 것.
LiveKit의 약점
- 매니지드 진영에 비해 클라이언트 사이드 분석(품질 측정·세션 리플레이)이 약하다. Daily가 이 영역에서 앞선다.
- 자가 호스트로 가면 TURN·로드 밸런서·녹화 스토리지 등 부속을 모두 직접 굴려야 한다.
- 라우팅 토폴로지(노드 클러스터링)는 강력하지만 학습 곡선이 있다.
4장 · Pion — Go의 WebRTC 엔진
Pion은 Go로 짜인 WebRTC 풀 구현이다. 2018년 처음 공개됐고, LiveKit·Galene·ion-sfu·OBS WHIP 송출까지 모두 Pion 위에 올라가 있다. Go의 단일 바이너리·동시성·크로스 컴파일 장점이 미디어 서버 운영에 잘 맞는다.
왜 Pion인가
- libwebrtc(구글의 C++ WebRTC)는 빌드와 임베드가 악명 높게 어렵다. Pion은
go get으로 끝. - Go의 goroutine이 다수 피어 관리에 자연스럽게 맞는다.
- 모든 WebRTC 부속(SDP·DTLS·SRTP·ICE·SCTP)이 분리된 라이브러리로 제공돼 부분만 가져다 쓸 수 있다.
Pion으로 짠 가장 단순한 SFU 피어 한 조각
피어 하나가 한 명의 발신자 트랙을 받아 다른 참가자에게 그대로 흘려보내는 코드의 최소형. 실제 SFU 구축은 트랙 라우팅·시뮬캐스트·DataChannel·재연결 처리가 추가로 들어간다.
// sfu_peer.go — Pion으로 짠 1대1 트랙 포워딩 한 조각
package main
import (
"fmt"
"github.com/pion/webrtc/v4"
)
func newPeer() (*webrtc.PeerConnection, error) {
api := webrtc.NewAPI()
pc, err := api.NewPeerConnection(webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{URLs: []string{"stun:stun.l.google.com:19302"}},
},
})
if err != nil {
return nil, err
}
// 인입 트랙을 받아서 그대로 outgoing 트랙으로 송출
pc.OnTrack(func(remote *webrtc.TrackRemote, _ *webrtc.RTPReceiver) {
// outgoing 트랙 생성(VP8 가정)
local, err := webrtc.NewTrackLocalStaticRTP(
remote.Codec().RTPCodecCapability,
"video",
"pion-sfu",
)
if err != nil {
return
}
if _, err := pc.AddTrack(local); err != nil {
return
}
// RTP 패킷 그대로 포워딩
buf := make([]byte, 1500)
for {
n, _, readErr := remote.Read(buf)
if readErr != nil {
return
}
if _, writeErr := local.Write(buf[:n]); writeErr != nil {
return
}
}
})
pc.OnICEConnectionStateChange(func(s webrtc.ICEConnectionState) {
fmt.Println("ICE state:", s.String())
})
return pc, nil
}
이 코드의 한계는 명확하다. 1대1만 처리하고, 시뮬캐스트(다중 해상도 트랙)는 안 받고, 시그널링은 안 들어있다. 그래도 Pion이 얼마나 직관적인지는 잘 보여준다.
Pion 기반 프로젝트들
- LiveKit
- Galene — 1인 운영을 가정한 가벼운 SFU. 강의·소규모 회의에 좋다.
- ion-sfu — 풀 SFU. 시뮬캐스트·녹화·라우팅.
- OBS Studio의 WHIP 송출 — Pion 클라이언트 모듈.
5장 · mediasoup — Node.js의 표준 SFU 라이브러리
mediasoup은 Node.js 진영의 SFU 라이브러리다. 자체 데몬이 아니라 Node 프로세스에서 임포트하는 라이브러리 형태라는 점이 중요하다. Worker는 C++로 짜져 있고, JS는 그걸 조종한다.
왜 mediasoup인가
- 라이브러리 형태라 시그널링·인증·룸 관리를 완전히 자유롭게 설계한다.
- 시뮬캐스트·SVC·녹화·트랜스코드·서버 라우팅을 모두 지원.
- discord·Microsoft Mesh 같은 큰 곳이 mediasoup을 기반으로 짰다는 사례가 있다.
mediasoup의 단점
- 시그널링부터 룸 관리·인증·재연결까지 전부 직접 짜야 한다. LiveKit/Janus가 끝에 끝까지 묶어주는 것과 정반대.
- 학습 곡선이 가장 가파르다. 라우터·트랜스포트·프로듀서·컨슈머의 추상이 다단계.
- Node 진영 외의 클라이언트 SDK는 커뮤니티가 굴린다.
mediasoup은 "팀에 미디어 인프라를 깊게 이해하는 엔지니어가 있다"는 전제일 때만 권한다. 사실상 매니지드/LiveKit이 채울 자리에 mediasoup을 직접 짜면 6개월 정도가 비용으로 나간다.
6장 · Janus — C로 짠 OG SFU
Janus는 2014년 출시된 C 기반 SFU다. WebRTC 인프라의 OG이고, 플러그인 아키텍처가 트레이드마크다.
- VideoRoom 플러그인 — 전형적인 다자간 미팅.
- Streaming 플러그인 — RTP·RTSP를 WebRTC로 전환.
- AudioBridge 플러그인 — 다자간 오디오 믹싱.
- WHIP 플러그인 — 표준 WHIP 송출 수신.
Janus의 위치
- 매우 오래되고 안정적이다. 작은 코어·낮은 메모리 사용·C의 성능.
- 플러그인 모델이 라이브 스트리밍·통화·믹싱 등 다양한 시나리오를 한 데몬에서 굴리게 한다.
- 단점: 시그널링 프로토콜이 독자적(REST·WebSocket Janus API). 클라이언트 SDK가 매니지드만큼 풍부하진 않다.
- 신규 채택은 LiveKit/매니지드로 옮겨가는 추세지만, 살아있고 활발하다.
7장 · Jitsi — 풀스택 OSS 미팅 솔루션
Jitsi는 OSS 풀스택 미팅 솔루션이다. 한 번 다운로드하면 Jitsi Meet(웹 UI) + Videobridge(SFU) + Jicofo(시그널링) + Prosody(XMPP) 묶음이 통째로 굴러간다.
- 8x8(Jitsi 인수)이 메인 메인테이너.
- 자가 호스트로 "회사 내부 미팅 솔루션"을 빠르게 띄울 때 1순위.
- API 통합은 약하다 — Jitsi는 "솔루션"이지 "라이브러리"가 아니다.
대안 사용 사례
- 회사 내부 미팅 솔루션 자가 호스트 → Jitsi.
- 우리 제품 안에 비디오를 넣어야 함 → LiveKit / mediasoup / 매니지드.
- 둘이 헷갈리는 일이 잦다. 목표가 다르다.
8장 · 매니지드 진영 — Daily, 100ms, Twilio Video, AWS Chime SDK
매니지드 비디오 API의 큰 패턴은 비슷하다. SDK + 서버 SDK + 매니지드 SFU + 녹화 + 분석. 다만 강점이 갈린다.
Daily.co
- 가장 깔끔한 DX. 한 줄짜리
prebuilt임베드(call-frame)와 풀 SDK 양쪽 다 강함. - 분석·세션 리플레이가 가장 깊다. 어떤 사용자의 어떤 통화가 어떻게 망가졌는지 가장 잘 보여줌.
- 가격: 분당 비용. 1000명 이내 규모에선 합리적.
100ms
- 인도 기반. RoomKit이라는 사전 빌트 미팅 UI 패키지.
- 인도·동남아 시장 점유율이 강함. 라이브 스트리밍 RoomKit이 따로 있어 라이브 송출도 한 묶음.
- 가격 경쟁력이 강점.
Twilio Video
- 기업 진영의 표준이었지만 2024년 신규 가입을 닫고 2026년 EOL로 가는 중. Twilio 음성·SMS는 살아 있다.
- 현재 시점에서 Twilio Video를 신규로 고르는 이유는 거의 없다.
AWS Chime SDK
- AWS 진영에서 영상 통화를 짤 때 1순위. IAM·CloudWatch·S3 녹화 등 AWS 생태계 통합이 강점.
- Voice Focus(잡음 제거), Echo Reduction 같은 부속이 일급으로 들어 있음.
- 단점: 가격이 비싸고, 클라이언트 SDK가 LiveKit·Daily만큼 매끈하진 않다.
Cloudflare Realtime / Calls
- 2024년 등장. Cloudflare의 엣지 네트워크 위에 WebRTC SFU를 던졌다는 새 카테고리.
- 글로벌 분산이 일급이고, WHIP/WHEP 표준 지원이 강력.
- 가격 모델이 새로워서 트래픽 패턴에 따라 큰 차이가 난다. 검토 가치는 충분.
- 단점: 아직 생태계가 어리다. SDK·문서가 LiveKit·Daily에 못 미친다. 그래도 빠르게 따라잡는 중.
9장 · WHIP/WHEP — RTMP를 대체하는 새 표준
라이브 송출은 오래 RTMP의 자리였다. 2002년 어도비가 만든 프로토콜. H.264 코덱·Flash 시대에 만들어졌고, 결정적인 약점이 셋이었다.
- 코덱이 H.264로 사실상 고정. AV1·VP9·HEVC 못 함.
- 지연이 2
5초로 큼. WebRTC는 200500ms. - TCP 기반이라 패킷 손실 회복이 굼뜸.
WHIP(WebRTC-HTTP Ingestion Protocol)와 WHEP(WebRTC-HTTP Egress Protocol)이 답이다. IETF 표준 절차.
WHIP의 작동 흐름
- 송출자가 SDP offer를 HTTP POST로 서버에 던진다.
- 서버가 SDP answer를 200 OK로 돌려준다.
- DTLS·SRTP 협상이 끝나면 미디어가 흐르기 시작.
이게 전부다. 시그널링이 HTTP 한 번. WebSocket·시그널링 서버 별도 구축이 필요 없다.
WHIP 송출 클라이언트 — 가장 단순한 fetch 한 줄
// whip-publisher.js — 마이크/카메라를 WHIP으로 송출
async function publishWHIP(endpoint, token) {
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
});
// 로컬 미디어 추가
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: { width: 1280, height: 720 },
});
stream.getTracks().forEach((track) => pc.addTrack(track, stream));
// SDP offer 생성
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// ICE gathering 완료까지 대기(간소화)
await new Promise((resolve) => {
if (pc.iceGatheringState === 'complete') return resolve(null);
pc.addEventListener('icegatheringstatechange', () => {
if (pc.iceGatheringState === 'complete') resolve(null);
});
});
// WHIP 엔드포인트로 SDP POST
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/sdp',
Authorization: `Bearer ${token}`,
},
body: pc.localDescription.sdp,
});
if (!response.ok) {
throw new Error(`WHIP failed: HTTP ${response.status}`);
}
// 서버의 answer로 RemoteDescription 설정
const answer = await response.text();
await pc.setRemoteDescription({ type: 'answer', sdp: answer });
return pc;
}
// 사용
const pc = await publishWHIP(
'https://ingest.example.com/whip/my-stream',
'my-token',
);
WHIP/WHEP가 채택된 곳
- OBS Studio 30+ — WHIP 송출이 기본 옵션으로 들어옴.
- LiveKit Ingress — WHIP·RTMP·SRT를 모두 받는 입구.
- Cloudflare Realtime — WHIP/WHEP 일급 지원.
- Twitch·YouTube Live — 시험 중(2026년 5월 기준).
- mediasoup·Janus — 플러그인.
WHIP/WHEP가 RTMP를 대체하는 이유
- 코덱 자유(VP9·AV1·H.264·Opus 등 SDP 협상으로 결정).
- 지연이 한 자릿수 초 → 0.5초.
- HTTPS POST 한 번이라 방화벽 통과가 쉽다(443).
- WebRTC 표준 위라 디버깅 도구가 그대로 쓰임.
10장 · SFU vs MCU vs P2P — 토폴로지 결정
WebRTC 인프라의 토폴로지가 결정의 큰 축이다.
| 토폴로지 | 어떻게 굴러가는가 | 적합 상황 |
|---|---|---|
| P2P 메시 | 모든 참가자가 다른 모두에게 직접 연결 | 2~3인. 매우 작음. |
| P2P 스타 | 호스트 하나가 다른 참가자에게 송출 | 1대N 스트리밍. 호스트 업로드 비대. |
| SFU | 서버가 인입 스트림을 받아 다른 참가자에게 그대로 포워딩 | 미팅·웨비나·라이브. 사실상 표준. |
| MCU | 서버가 모든 스트림을 디코드·믹스·재인코드해서 하나로 송출 | 전화 컨퍼런스. 클라이언트 부하 최저. |
SFU가 표준이 된 이유
- 서버 CPU 비용이 낮다. 디코드·인코드를 안 함. RTP 패킷을 그대로 라우팅만.
- 시뮬캐스트(다중 해상도) 지원. 수신자의 대역에 맞춰 적절한 해상도 트랙을 선택.
- SVC(스케일러블 비디오 코딩) 지원. 한 트랙에 다중 레이어가 들어가 더 효율적.
MCU의 자리
- 전화 컨퍼런스(PSTN 게이트웨이) — 모두를 하나로 믹스해야 함.
- 매우 약한 클라이언트(임베디드·구형 단말) — 한 트랙만 받으면 되니까.
- 녹화의 최종 산물(단일 합성 비디오).
P2P의 자리
- 1대1 영상통화 — STUN으로 직접 연결되면 서버 비용 0.
- 작은 가족·친구용 앱. 3인 이상이면 SFU로 가는 게 맞다.
11장 · 코덱 풍경 — Opus, VP8, VP9, AV1, H.264, H.265
WebRTC의 의무 코덱은 오디오 Opus, 비디오 VP8·H.264다. 나머지는 선택.
오디오
- Opus — 사실상 유일한 선택. 8~510kbps 가변. 음악·음성 양쪽 다 잘함. 모든 WebRTC 구현이 지원.
- G.711·G.722 — PSTN 게이트웨이에서 가끔 쓰인다. WebRTC 내부는 거의 안 씀.
비디오
- VP8 — WebRTC 초창기부터 의무. 가장 호환성 높음.
- H.264 — 의무. iOS Safari에서 하드웨어 가속 일급. 미국 시장에서 선호.
- VP9 — 선택. AV1 전 단계의 효율 좋은 코덱. Chrome·Firefox 지원.
- AV1 — 선택. 가장 효율적(VP9보다 30% 더). 인코딩 비용이 비싸 모든 시나리오에 맞진 않음. 2026년 들어 데스크톱 하드웨어 가속이 보편화되며 빠르게 채택 중.
- H.265(HEVC) — WebRTC에선 거의 안 씀. 라이선스 부담.
시뮬캐스트와 SVC
- 시뮬캐스트 — 송출자가 같은 영상을 여러 해상도/비트레이트로 동시에 송출. SFU가 수신자에 맞춰 하나를 선택.
- SVC — 한 스트림 안에 베이스 레이어 + 인핸스먼트 레이어가 묶여 있음. SFU가 레이어를 깎아 보냄. AV1·VP9에서 강함.
결정
- 시작은 VP8 + Opus로. 모든 곳에서 호환.
- iOS 일급 지원 → H.264도 함께.
- 대역폭 절약·고화질 → AV1 추가, 인코딩 비용 감안.
- 시뮬캐스트는 무조건 켜라. SFU 입장에서 수신자별 적응이 안 되면 큰 룸에서 무너진다.
12장 · 매니지드 vs 자가 호스트 결정 매트릭스
큰 결정 한 번. 이 매트릭스가 가이드.
| 상황 | 추천 | 이유 |
|---|---|---|
| MVP, 6개월 안에 출시 | 매니지드 (LiveKit Cloud, Daily, 100ms) | 미디어 인프라에 시간을 쓰지 마라 |
| 음성 에이전트 중심(LLM·STT·TTS) | LiveKit (Cloud 또는 OSS) | Agents 프레임워크가 기다리고 있음 |
| 회사 내부 미팅 솔루션 | Jitsi 자가 호스트 | "솔루션" 그대로 떨어짐 |
| WHIP 라이브 송출 | LiveKit Ingress 또는 Cloudflare Realtime | WHIP 일급 지원 |
| 글로벌 분산, 엣지 라우팅 | Cloudflare Realtime 또는 LiveKit Cloud | 엣지 위 SFU |
| 인프라 비용 최소화(중간 규모) | LiveKit OSS 자가 호스트 | 매니지드 분당 비용 안 냄 |
| 시그널링·라우팅을 완전 통제 | mediasoup | 라이브러리 형태, 모든 결정이 내 것 |
| AWS 생태계 깊게 통합 | AWS Chime SDK | IAM·S3·CloudWatch 동기화 |
| 전화 게이트웨이(PSTN) 통합 | Twilio Voice + LiveKit SIP | Twilio Voice는 살아있음 |
| 인도·동남아 시장 가격 | 100ms | 가격 경쟁력 |
매니지드 → 자가 호스트로 이주 시그널
- 매니지드 비용이 월 USD 5천을 넘기 시작 → 자가 호스트 인프라 + DevOps 1명의 비용을 넘어선다.
- 데이터 주권·HIPAA·온프레미스 요구사항 → 매니지드는 어렵다.
- 미디어 파이프라인을 깊게 만져야 함(맞춤 트랜스코드·맞춤 라우팅) → 매니지드의 추상이 막힌다.
자가 호스트의 숨은 비용
- TURN 서버 — 회사 방화벽 뒤 사용자 비율만큼 트래픽을 떠안는다. 트래픽 비싸다.
- 로드 밸런서·노드 클러스터링.
- 녹화 스토리지·트랜스코드 워커.
- 모니터링·관측성(WebRTC 통계가 가장 까다로움).
- 비상 대응 — 미디어 서버는 다른 서버보다 까다롭다.
13장 · 클라이언트 사이드 라이브러리
서버만큼이나 클라이언트가 결정의 절반이다.
표준 RTCPeerConnection
- 브라우저가 기본으로 주는 API. 가장 가볍지만 가장 시그널링을 직접 짜야 함.
- 작은 P2P 데모·WHIP 송출·매우 가벼운 상황에 맞다.
LiveKit Client SDK
Room,Participant,Track추상화. 자동 재연결·시뮬캐스트·DataChannel.@livekit/components-react— 미팅 UI를 즉시 만든다.
Daily의 call-frame
- 한 줄 iframe 임베드. 가장 단순. 풀 SDK도 따로 있다.
mediasoup-client
- mediasoup 서버와 짝. 트랜스포트·프로듀서·컨슈머 추상.
Janus의 JS 어댑터
- Janus 서버와 짝. REST/WebSocket 시그널링.
simple-peer
- 가장 단순한 P2P 라이브러리. 시그널링을 직접 굴리는 모드.
14장 · 운영 — TURN, NAT, 모니터링
운영의 절반은 시그널링·NAT·관측성에 들어간다.
STUN과 TURN
- STUN — 클라이언트가 자기 공인 IP/포트를 알아내는 서버. UDP 한 패킷 RTT.
- TURN — STUN으로 안 되는 NAT(대칭 NAT, 방화벽) 뒤 사용자를 위한 미디어 릴레이. 트래픽이 TURN을 지나가므로 비싸다.
coturn— TURN 서버의 사실상 표준 OSS 구현.- TURN 트래픽 비율은 보통 5~20%. 회사 네트워크가 많으면 50%까지도.
getStats()로 보는 WebRTC 관측성
- 표준
RTCPeerConnection.getStats()가 RTT·jitter·패킷 손실·코덱·해상도 등을 준다. - 1분당 한 번 수집해서 데이터 웨어하우스로 흘려라.
- 매니지드(Daily·LiveKit Cloud)는 이를 대시보드로 떨어뜨려 준다.
통화 품질 지표
- MOS(Mean Opinion Score) — 1~5의 통화 품질 점수. RTT·패킷 손실·jitter에서 추정.
- 시작 실패율 — 룸 입장까지 도달 못한 비율. 핵심 SLI.
- 재연결 빈도 — 한 통화당 재연결 횟수.
- 비디오 동결 시간 — 비디오가 멈춰 있던 누적 시간.
15장 · 라이브 스트리밍 시나리오
라이브 송출은 WebRTC 인프라의 별도 영역으로 굳어졌다. 시나리오별 권장.
| 시나리오 | 송출 | 라우팅 | 수신 |
|---|---|---|---|
| 강연자 한 명 → 1만 명 시청 | OBS WHIP 송출 | LiveKit/Cloudflare Realtime SFU | HLS 트랜스코드 후 HLS 시청자 |
| 강연자 한 명 → 100명 인터랙티브 | OBS WHIP 송출 | LiveKit SFU | WHEP 수신 |
| 다자간 미팅 녹화 → 시청자에 송출 | LiveKit Room | LiveKit Egress | HLS 트랜스코드 |
| 게임 플레이 송출 → 인터랙티브 채팅 | OBS WHIP | Cloudflare Realtime | WHEP 또는 HLS |
WebRTC 라이브가 RTMP 라이브를 대체하는 한계
- 시청자 규모가 매우 큼(10만+) → CDN 거리는 HLS·DASH가 여전히 표준. WebRTC는 5만 이내가 합리적.
- 광고 삽입·DRM 같은 방송 기능은 HLS 진영이 깊다.
- WebRTC 라이브는 "낮은 지연 + 양방향 인터랙션"이 강점인 영역에서 우위.
16장 · 보안·DRM·E2EE
WebRTC는 기본적으로 DTLS-SRTP 암호화다. 미디어 패킷은 클라이언트와 서버 간에 항상 암호화된다. 다만 SFU 모드에선 SFU가 평문으로 라우팅 결정을 한다(코덱 정보·시뮬캐스트 레이어 선택 등).
E2EE — Insertable Streams
- 진정한 종단간 암호화가 필요하면 Insertable Streams로 SFU도 평문을 못 보게 한다.
- LiveKit·Jitsi·Google Meet이 채택. 매니지드 키 관리가 핵심.
- 비용은 시뮬캐스트 효율이 떨어지고, 서버 사이드 녹화·트랜스코드가 어려워진다는 것.
DRM
- WebRTC는 DRM과 잘 안 맞는다. DRM은 콘텐츠 보호가 목표인데 WebRTC는 실시간성이 목표.
- 라이브 송출 DRM이 필요하면 HLS + Widevine 같은 조합으로 가야 한다.
17장 · 케이스 스터디 — AI 음성 에이전트 한 개 풀스택
위 도구들이 한 데 모이면 어떻게 굴러가는가. 가장 보편적인 시나리오.
[사용자 브라우저]
|
| WebRTC 오디오 송수신
v
[LiveKit Server]
|
| LiveKit Agents Worker가 룸에 자동 합류
v
[Agents Worker (Python)]
|
+-- Deepgram STT(스트리밍)
+-- OpenAI gpt-4o-mini(LLM)
+-- ElevenLabs TTS(스트리밍)
+-- Silero VAD(턴 결정)
|
| TTS 오디오를 LiveKit 룸으로 송출
v
[사용자 브라우저 — 즉시 재생]
지연 분해(목표 700ms 미만)
- 사용자가 말 끝남 → VAD가 턴 결정: 100~200ms
- 마지막 STT 결과 확정: 50~100ms
- LLM 첫 토큰까지: 200~400ms
- 첫 TTS 오디오 청크까지: 100~200ms
- WebRTC 전송 지연: 50~150ms
합계: 500~1000ms. 사람이 "대화처럼 느끼는" 한계가 이 정도다.
OpenAI Realtime + WebRTC 직결 모드
위 그림에서 Deepgram·OpenAI·ElevenLabs가 한 모델로 합쳐진다. 지연 200~400ms.
[사용자 브라우저]
|
| WebRTC 오디오 직결
v
[OpenAI Realtime 엔드포인트]
|
| 모델이 오디오 입출력 자체를 처리
v
[사용자 브라우저 — 응답 오디오]
이 모드의 트레이드오프
- 장점: 지연 매우 낮음. 모델이 음성의 뉘앙스를 직접 봄(웃음·끼어들기).
- 단점: 가격 높음. 모델이 OpenAI 진영으로 고정. STT/TTS의 자유도 잃음.
대다수 프로덕션은 둘을 함께 굴린다. 빠른 대화는 Realtime, 도구 호출·맞춤 TTS는 일반 LLM + 별도 STT/TTS.
18장 · 흔한 안티 패턴
운영에서 자주 봤다.
- P2P 메시로 4인 이상을 굴리려 함 — 5명에서 무너진다. 처음부터 SFU로 가라.
- TURN 서버 없이 출시 — 회사 네트워크 뒤 사용자가 들어오는 순간 통화 실패율이 30% 찍힌다.
- 시뮬캐스트를 끄고 한 해상도만 송출 — 10명 룸에서 누군가 모바일 4G면 모두가 끊긴다.
getUserMedia권한을 한 번 받고 끝났다고 생각 — 권한은 페이지·세션 단위로 바뀐다. 매번 다시 확인.- WebSocket 시그널링 한 개로 SFU 자체를 굴리려 함 — 시그널링은 시그널링이고 미디어는 미디어다. 한 프로세스로 묶지 마라.
- WebRTC 통계 수집을 안 함 — 사용자 한 명이 "끊겨요" 신고하면 재현 못 한다.
getStats()1분당 1회 수집. - 녹화·트랜스코드를 SFU 같은 프로세스에 박음 — 인코딩 1개가 SFU 전체를 멈춘다. 별도 워커로 분리.
- AI 음성 에이전트에서 VAD를 약하게 잡음 — 사용자 말이 끝나기 전 모델이 끼어든다. 또는 끝났는데 모델이 안 답한다.
- WHIP·RTMP·SRT 중에서 RTMP만 받는다 — 2026년에 AV1·VP9 송출은 RTMP로 못 한다. WHIP를 옵션으로 넣어라.
- 자가 호스트인데 모니터링이 PromQL 메트릭 5개로 끝 — 미디어 서버의 관측성은 일반 웹 서버보다 한 단계 더 깊다.
19장 · 큰 그림 — 무엇이 표준이 됐는가
2026년 5월 기준 정리.
- LiveKit이 AI 음성 에이전트 인프라의 표준 — Agents 프레임워크·OpenAI 채택·OSS+클라우드 양 갈래.
- Pion이 Go 진영의 WebRTC 엔진 — LiveKit·Galene·OBS WHIP 모두 Pion 위.
- WHIP/WHEP가 RTMP의 자리를 빠르게 가져가는 중 — OBS 30+이 기본 지원.
- OpenAI Realtime이 WebRTC 직결 모드 추가 — 음성 에이전트 지연이 사람 대화 수준.
- Cloudflare Realtime이 엣지 SFU라는 새 카테고리 — 글로벌 분산이 일급.
- 매니지드 진영은 여전히 강함 — Daily·100ms·AWS Chime SDK. 다만 가격 압박.
- Twilio Video는 사실상 사라짐 — 신규 가입 중단. EOL 진행 중.
- mediasoup·Janus·Jitsi는 자가 호스트 진영의 세 갈래로 굳어짐.
결정 체크리스트
- AI 음성 에이전트가 핵심인가? — LiveKit + LiveKit Agents.
- 회사 내부 미팅 솔루션이 필요한가? — Jitsi 자가 호스트.
- 라이브 스트리밍 송출이 핵심인가? — WHIP + LiveKit Ingress 또는 Cloudflare Realtime.
- 글로벌 분산 엣지가 우선인가? — Cloudflare Realtime 또는 LiveKit Cloud.
- 매니지드의 일급 분석이 필요한가? — Daily.
- 인도·동남아 가격 경쟁력이 필요한가? — 100ms.
- AWS 깊은 통합이 필요한가? — AWS Chime SDK.
- Go로 짠 작은 SFU 한 조각을 깊게 만져야 하나? — Pion 직접.
- Node.js로 시그널링·라우팅을 직접 통제하려면? — mediasoup.
- 매우 안정적이고 오래된 C 데몬을 원하나? — Janus.
안티 패턴 요약
- P2P 메시로 4인 이상.
- TURN 없이 출시.
- 시뮬캐스트 끔.
- WebRTC
getStats()미수집. - 한 프로세스에서 시그널링·SFU·녹화·트랜스코드.
- AI 에이전트에서 VAD 약함.
- RTMP만 받음(WHIP 미지원).
- 큰 룸에 MCU 강제.
- 매니지드와 자가 호스트 결정 없이 둘을 섞음.
- E2EE를 켰는데 서버 사이드 녹화를 기대.
다음 글 예고
다음 글 후보: LiveKit Agents 깊게 — 토큰 단위 스트리밍·도구 호출·인터럽션 처리, WHIP/WHEP 인제스트 한 달 운영기 — OBS·Cloudflare·LiveKit 비교, WebRTC getStats() 100개 메트릭 — 무엇을 보고 무엇을 무시할까.
"WebRTC는 표준이 아니라 표준들의 묶음이다. 묶음을 운영할 줄 아는 팀만큼 멀리 간다."
— WebRTC 미디어 인프라 2026, 끝.
참고 / References
- LiveKit 공식
- LiveKit GitHub — livekit/livekit
- LiveKit Agents 프레임워크 문서
- LiveKit Agents GitHub — livekit/agents
- LiveKit Cloud 가격
- Pion 공식
- Pion WebRTC GitHub
- Daily.co 공식
- 100ms 공식
- mediasoup 공식
- Janus Gateway 공식
- Jitsi Meet 공식
- Twilio Video 문서
- AWS Chime SDK 문서
- Cloudflare Realtime 공식
- Cloudflare Calls 발표
- WHIP IETF 표준 RFC 9725
- WHEP IETF 드래프트
- OBS Studio — WHIP 송출 지원
- OpenAI Realtime API 문서
- OpenAI Realtime + WebRTC 가이드
- Deepgram Nova 모델
- ElevenLabs TTS 문서
- Cartesia TTS
- Silero VAD GitHub
- coturn GitHub — TURN 서버 OSS 표준
- WebRTC
getStats()MDN - Insertable Streams MDN
- Opus 코덱
- AV1 코덱
- Galene SFU GitHub
- ion-sfu GitHub
- webrtc-rs GitHub
WebRTC Media Infrastructure 2026 — LiveKit·Pion·Daily·100ms·mediasoup·Janus·Cloudflare Realtime and WHIP/WHEP Deep Dive
Prologue — WebRTC is 90% an infrastructure choice
In 2018, WebRTC was the problem of "how do I write a P2P video call in the browser". One STUN/TURN server, 200 lines of RTCPeerConnection code, a demo page with two video boxes. Done.
In 2026, WebRTC is a different problem.
- How do I run a 100-person room? — Answer: an SFU (Selective Forwarding Unit). The P2P mesh is N-squared and falls over at 5.
- How do I plug in an AI voice agent? — Pipe LLM output tokens through TTS, microphone audio through STT, all under 200 ms of latency. WebRTC's strength.
- How do I do live broadcast? — RTMP is stuck on old codecs (H.264 only) with 2–5 second latency. WHIP (WebRTC-HTTP Ingestion Protocol) and WHEP (WebRTC-HTTP Egress Protocol) have risen as the new standard.
- Do we go managed (Daily, 100ms, Twilio, Chime) or self-host (LiveKit OSS, mediasoup, Janus, Jitsi)?
This piece is not about "200 lines of WebRTC code". It is about "where and how do you run production media infrastructure". That one decision sets your infra cost, latency and operational burden for the next six months.
Summary — the big picture as of May 2026.
- LiveKit became the de facto standard infrastructure for AI voice agents. The LiveKit Agents framework integrates first-class with OpenAI Realtime API, Deepgram, and ElevenLabs.
- Pion settled in as the WebRTC engine of the Go camp. LiveKit itself sits on top of Pion.
- WHIP/WHEP became the live ingestion standard replacing RTMP. OBS 30+ ships WHIP egress out of the box.
- The managed camp (Daily, 100ms, Twilio Video, AWS Chime SDK) is alive but under price pressure. LiveKit Cloud is the round-one strong contender.
- Cloudflare Realtime threw WebRTC onto the edge as a new category. Calls API plus Realtime SFU.
Let's start.
1. The WebRTC Infrastructure Landscape — The 2026 Map
First, classification. Not everything is in the same place.
| Category | Representative product | One-line summary |
|---|---|---|
| AI voice/video infra (managed + OSS) | LiveKit Cloud / LiveKit OSS | The 2026 voice-agent standard. Agents framework. |
| Managed video API | Daily.co, 100ms, Twilio Video, AWS Chime SDK, Vonage | SDK plus managed SFU. Fast time to ship. |
| Edge WebRTC | Cloudflare Realtime / Calls | Global edge SFU. New category. |
| Self-host SFU (Node.js) | mediasoup | Library form. You write the signaling yourself. |
| Self-host SFU (C) | Janus | Plugin architecture. The OG. |
| Full-stack OSS | Jitsi (Meet / Videobridge) | A meeting solution plus SFU you download and run. |
| WebRTC engine (Go) | Pion | The library that made WebRTC writable in Go. |
| WebRTC engine (Rust) | webrtc-rs | The Rust port of Pion. Growing. |
| Live ingestion standard | WHIP / WHEP | Start a WebRTC session with a single HTTP request. RTMP replacement. |
The focus of this piece is the bolded set — LiveKit, Pion, Daily, 100ms, mediasoup, Janus, Jitsi, Twilio, Chime, Cloudflare Realtime. WHIP/WHEP gets its own chapter.
Why LiveKit became the standard
- The number-one infrastructure of the AI voice-agent era. The LiveKit Agents framework integrates first-class with OpenAI Realtime, Deepgram STT, ElevenLabs TTS and Cartesia.
- Runs both OSS and Cloud (LiveKit Cloud) at the same time. You can start self-hosted and move to Cloud later.
- Built on Pion, so a single Go binary. Kubernetes and Docker deploys are simple.
- LiveKit's client SDK family (JS, Swift, Kotlin, Flutter, Unity, React Native) is well organized.
2. A 7-Axis Comparison Matrix
Before the deep analysis, the one-glance picture.
| Axis | LiveKit | Daily | 100ms | mediasoup | Janus | Jitsi | Twilio Video | AWS Chime SDK | Cloudflare Realtime |
|---|---|---|---|---|---|---|---|---|---|
| Operating model | Managed + OSS | Managed | Managed | OSS library | OSS daemon | OSS full stack | Managed | Managed | Managed (edge) |
| Language | Go (Pion) | Closed | Closed | Node.js + C++ | C | Java + C (libwebrtc) | Closed | Closed | Closed |
| AI voice integration | First-class (Agents) | Good | Good | DIY | DIY | DIY | Average | Good (Voice Focus) | DIY |
| WHIP/WHEP | First-class | Supported | Supported | Plugin | Plugin | External tool | Not supported | Not supported | First-class |
| Global routing | First-class in Cloud | First-class | First-class | DIY | DIY | DIY | First-class | First-class | First-class (edge) |
| Price pressure | Strong (OSS + Cloud) | Average | Average | Infra cost only | Infra cost only | Infra cost only | Expensive | Expensive | New |
| New adoption trend | Very strong | Stable | Strong (India market) | Stable | Decreasing | Stable | Decreasing | Stable | Rapid growth |
Don't decide off this table alone. The next chapters pin down what each tool can and cannot do.
3. LiveKit — Why It Became the Standard, and LiveKit Agents
LiveKit, born in 2021, is the WebRTC infrastructure that found its place the fastest. It runs both an OSS (Apache 2.0) and LiveKit Cloud track. Two decisive events happened between 2025 and 2026.
- The LiveKit Agents framework — Python and Node SDKs that bundle LLMs, STT, TTS and VAD to build voice agents. OpenAI Realtime API, Deepgram, AssemblyAI, ElevenLabs, Cartesia, and more integrate first-class.
- OpenAI officially adopted LiveKit — It came out publicly that the infrastructure behind ChatGPT voice mode runs on LiveKit. A de facto industry stamp.
Why LiveKit is strong
- A single Go binary —
livekit-server. Pion-based. One Docker line and it is up. - Client SDK lineup — JS, Swift, Kotlin, Flutter, Unity, React Native, Python. All share the same abstraction (Room, Participant, Track).
- Egress and Ingress services — Recording (MP4, HLS), stream extraction (WHIP/WHEP ingest), transcoding are split into their own modules.
@livekit/components-react— Pre-built components that get you a meeting UI in 30 minutes.- LiveKit Cloud — When you don't want to run self-hosted, you switch to the same API. SLA and global routing included.
A LiveKit Agents skeleton
The simplest shape of a single voice agent. The code pipes microphone audio into OpenAI Realtime and sends the model's response audio back into the room.
# agent.py — minimal LiveKit Agents skeleton
import asyncio
import os
from livekit import agents, rtc
from livekit.agents import AgentSession, Agent
from livekit.plugins import openai, deepgram, elevenlabs, silero
class VoiceAssistant(Agent):
def __init__(self) -> None:
super().__init__(
instructions=(
"You are a friendly voice assistant. "
"Answer in short, conversational sentences."
),
)
async def on_enter(self) -> None:
# Auto-greet the user
await self.session.say("Hi there, how can I help you?")
async def entrypoint(ctx: agents.JobContext) -> None:
await ctx.connect() # join the room
session = AgentSession(
# 1) STT — Deepgram nova-3
stt=deepgram.STT(model="nova-3"),
# 2) LLM — OpenAI Realtime, or plain chat completions
llm=openai.LLM(model="gpt-4o-mini"),
# 3) TTS — ElevenLabs
tts=elevenlabs.TTS(voice_id="Rachel"),
# 4) VAD — Silero voice activity detection (turn taking)
vad=silero.VAD.load(),
)
await session.start(
agent=VoiceAssistant(),
room=ctx.room,
)
if __name__ == "__main__":
agents.cli.run_app(
agents.WorkerOptions(entrypoint_fnc=entrypoint),
)
To deploy, run python agent.py dev locally, then python agent.py start in production. When the LiveKit server creates a new room, the Agents worker is matched automatically and joins.
OpenAI Realtime + WebRTC direct mode
OpenAI's Realtime API launched in 2024 with WebSocket only. In 2025 a WebRTC connection mode was added. A client crafts an SDP and posts it directly to the OpenAI endpoint; the model responds like an SFU. Latency drops to 200–400 ms.
LiveKit Agents abstracts both options.
# Using OpenAI Realtime as a direct WebRTC connection
from livekit.plugins import openai
session = AgentSession(
llm=openai.realtime.RealtimeModel(
model="gpt-4o-realtime-preview",
voice="alloy",
# WebRTC mode — no separate STT/TTS needed
modalities=["audio", "text"],
),
)
In this mode you don't need separate STT/TTS — the model handles audio in and out itself. Downsides: pricing is higher, and your model choice is locked to the OpenAI Realtime lineup.
LiveKit's weaknesses
- Client-side analytics (call-quality measurement, session replay) lags the managed players. Daily leads in this area.
- Going self-hosted means you operate TURN, load balancers, recording storage and everything around it.
- Routing topology (node clustering) is powerful but has a learning curve.
4. Pion — The WebRTC Engine of Go
Pion is a full WebRTC implementation written in Go. First public in 2018. LiveKit, Galene, ion-sfu, and even OBS WHIP egress all sit on Pion. Go's single-binary, concurrency, and cross-compilation advantages match media-server operations well.
Why Pion
- libwebrtc (Google's C++ WebRTC) is famously hard to build and embed. With Pion,
go getis it. - Go's goroutines map naturally onto managing many peers.
- Every WebRTC subsystem (SDP, DTLS, SRTP, ICE, SCTP) is provided as a separate library, so you can pull in just the part you need.
The simplest SFU peer fragment in Pion
The minimal shape of one peer taking one sender's track and forwarding it to another participant. A real SFU adds track routing, simulcast, DataChannel, and reconnection logic.
// sfu_peer.go — a 1-to-1 track-forwarding fragment in Pion
package main
import (
"fmt"
"github.com/pion/webrtc/v4"
)
func newPeer() (*webrtc.PeerConnection, error) {
api := webrtc.NewAPI()
pc, err := api.NewPeerConnection(webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{URLs: []string{"stun:stun.l.google.com:19302"}},
},
})
if err != nil {
return nil, err
}
// Take incoming track and forward it as an outgoing track
pc.OnTrack(func(remote *webrtc.TrackRemote, _ *webrtc.RTPReceiver) {
// Create an outgoing track (assume VP8)
local, err := webrtc.NewTrackLocalStaticRTP(
remote.Codec().RTPCodecCapability,
"video",
"pion-sfu",
)
if err != nil {
return
}
if _, err := pc.AddTrack(local); err != nil {
return
}
// Forward RTP packets as-is
buf := make([]byte, 1500)
for {
n, _, readErr := remote.Read(buf)
if readErr != nil {
return
}
if _, writeErr := local.Write(buf[:n]); writeErr != nil {
return
}
}
})
pc.OnICEConnectionStateChange(func(s webrtc.ICEConnectionState) {
fmt.Println("ICE state:", s.String())
})
return pc, nil
}
The limits are clear. It handles only 1-to-1, doesn't take simulcast (multi-resolution tracks), and has no signaling. Still, it shows how direct Pion feels.
Projects on Pion
- LiveKit
- Galene — a lightweight SFU assuming single-operator use. Great for lectures and small meetings.
- ion-sfu — a full SFU. Simulcast, recording, routing.
- The WHIP egress in OBS Studio — a Pion client module.
5. mediasoup — Node.js's Standard SFU Library
mediasoup is the SFU library for the Node.js world. The important point: it isn't a daemon — it's a library you import into a Node process. The worker is written in C++, and the JS layer orchestrates it.
Why mediasoup
- Because it is library-shaped, you control signaling, auth, and room management completely.
- Supports simulcast, SVC, recording, transcoding, and server routing.
- Large projects like Discord and Microsoft Mesh have been built on top of mediasoup.
mediasoup's downsides
- You write signaling, room management, auth, and reconnection logic yourself. The opposite of LiveKit / Janus tying things end to end.
- The steepest learning curve. The abstractions (router, transport, producer, consumer) are multi-layered.
- Client SDKs outside the Node ecosystem are community-driven.
I only recommend mediasoup when the team includes an engineer who deeply understands media infrastructure. Writing a mediasoup stack to fill a slot that LiveKit or managed would have covered tends to burn about six months.
6. Janus — The OG SFU Written in C
Janus, released in 2014, is a C-based SFU. The OG of WebRTC infrastructure, with a plugin architecture as its trademark.
- The VideoRoom plugin — a classic multi-party meeting.
- The Streaming plugin — converts RTP/RTSP into WebRTC.
- The AudioBridge plugin — multi-party audio mixing.
- The WHIP plugin — receives standard WHIP egress.
Where Janus sits
- Very old and stable. Small core, low memory footprint, the performance of C.
- The plugin model lets one daemon serve live streaming, calls, and mixing scenarios at the same time.
- Downside: a proprietary signaling protocol (the REST/WebSocket Janus API). Client SDKs aren't as rich as the managed players.
- New adoption is shifting toward LiveKit and managed, but Janus is alive and active.
7. Jitsi — The Full-Stack OSS Meeting Solution
Jitsi is a full-stack OSS meeting solution. One download and you get Jitsi Meet (web UI) plus Videobridge (SFU) plus Jicofo (signaling) plus Prosody (XMPP), all as one bundle that runs together.
- 8x8 (which acquired Jitsi) is the main maintainer.
- The number-one pick for quickly bringing up a self-hosted "internal meeting solution".
- API integration is weak — Jitsi is a "solution", not a "library".
Alternate use cases
- Self-host an internal company meeting solution → Jitsi.
- Embed video into your product → LiveKit, mediasoup, or managed.
- People mix these up often. Their targets are different.
8. The Managed Camp — Daily, 100ms, Twilio Video, AWS Chime SDK
The big pattern across managed video APIs is similar. SDK + server SDK + managed SFU + recording + analytics. But strengths diverge.
Daily.co
- The cleanest developer experience. Both the one-line
prebuiltembed (thecall-frame) and a full SDK are strong. - Analytics and session replay run the deepest. Daily best shows you which user's which call broke and how.
- Pricing: per-minute. Reasonable up to roughly 1,000-user scale.
100ms
- India-based. RoomKit is the pre-built meeting UI package.
- Strong share in India and Southeast Asia. There's a separate live-streaming RoomKit, so live broadcast is bundled in.
- Price competitiveness is the strength.
Twilio Video
- Was the standard of enterprise camps, but closed new sign-ups in 2024 and is moving toward EOL in 2026. Twilio Voice and SMS are alive.
- As of now there is almost no reason to pick Twilio Video new.
AWS Chime SDK
- The first pick when building video calling inside the AWS world. Strong integration with IAM, CloudWatch, S3 recording, and the rest of the AWS ecosystem.
- Voice Focus (noise suppression), Echo Reduction, and friends are first-class built-ins.
- Downsides: pricing is expensive and the client SDK is not as polished as LiveKit's or Daily's.
Cloudflare Realtime / Calls
- Arrived in 2024. The new category of "WebRTC SFU thrown onto Cloudflare's edge".
- First-class global distribution and strong WHIP/WHEP standard support.
- The new pricing model makes a big difference depending on traffic shape. Well worth evaluating.
- Downside: ecosystem is still young. SDKs and docs trail LiveKit and Daily. But the catch-up rate is fast.
9. WHIP/WHEP — The New Standard Replacing RTMP
Live ingestion was long RTMP's seat. RTMP was made by Adobe in 2002, in the era of H.264 and Flash, and three weaknesses became decisive.
- Codec effectively locked to H.264. Can't do AV1, VP9, or HEVC.
- Latency is 2–5 seconds. WebRTC is 200–500 ms.
- TCP-based, so packet-loss recovery is sluggish.
WHIP (WebRTC-HTTP Ingestion Protocol) and WHEP (WebRTC-HTTP Egress Protocol) are the answer. IETF-standardized.
How WHIP works
- The publisher posts an SDP offer to the server over HTTP POST.
- The server returns an SDP answer with 200 OK.
- Once DTLS/SRTP negotiation completes, media starts flowing.
That's the whole thing. Signaling is one HTTP round trip. No need to spin up WebSockets or a separate signaling server.
A WHIP publishing client — fetch-and-done
// whip-publisher.js — publish microphone and camera over WHIP
async function publishWHIP(endpoint, token) {
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
});
// Add local media
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: { width: 1280, height: 720 },
});
stream.getTracks().forEach((track) => pc.addTrack(track, stream));
// Create the SDP offer
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// Wait for ICE gathering to complete (simplified)
await new Promise((resolve) => {
if (pc.iceGatheringState === 'complete') return resolve(null);
pc.addEventListener('icegatheringstatechange', () => {
if (pc.iceGatheringState === 'complete') resolve(null);
});
});
// POST the SDP to the WHIP endpoint
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/sdp',
Authorization: `Bearer ${token}`,
},
body: pc.localDescription.sdp,
});
if (!response.ok) {
throw new Error(`WHIP failed: HTTP ${response.status}`);
}
// Set RemoteDescription from the server's answer
const answer = await response.text();
await pc.setRemoteDescription({ type: 'answer', sdp: answer });
return pc;
}
// Usage
const pc = await publishWHIP(
'https://ingest.example.com/whip/my-stream',
'my-token',
);
Where WHIP/WHEP took root
- OBS Studio 30+ — WHIP egress is now a standard option.
- LiveKit Ingress — accepts WHIP, RTMP, and SRT at the same entry.
- Cloudflare Realtime — first-class WHIP/WHEP.
- Twitch and YouTube Live — under trial (as of May 2026).
- mediasoup and Janus — via plugins.
Why WHIP/WHEP replaces RTMP
- Codec freedom (VP9, AV1, H.264, Opus, and more — settled by SDP negotiation).
- Latency drops from single-digit seconds to 0.5 seconds.
- One HTTPS POST, so firewall traversal is easy (port 443).
- Sits on WebRTC standards, so all the standard debugging tools just work.
10. SFU vs MCU vs P2P — The Topology Decision
The topology of WebRTC infrastructure is a huge decision axis.
| Topology | How it runs | When it fits |
|---|---|---|
| P2P mesh | Every participant connects directly to every other | 2–3 people. Very small. |
| P2P star | One host sends to every other participant | 1-to-N streaming. Host upload bound. |
| SFU | The server receives incoming streams and forwards them to other participants as-is | Meetings, webinars, live. The de facto standard. |
| MCU | The server decodes, mixes and re-encodes all streams into one composite | Phone conferences. Lowest client load. |
Why SFU is the standard
- Server CPU cost is low. No decode/encode — it just routes RTP packets.
- Simulcast (multi-resolution) support. The receiver-appropriate track is chosen based on bandwidth.
- SVC (scalable video coding) support. One track contains multiple layers, more efficient.
MCU's place
- Phone conferencing (PSTN gateways) — everyone has to be mixed into one stream.
- Very weak clients (embedded, legacy devices) — they only need to receive one track.
- The final artifact of recording (one composite video).
P2P's place
- 1-to-1 video calls — if STUN connects them directly, the server bill is zero.
- Small family/friend apps. Above 3 people, SFU is the right answer.
11. The Codec Landscape — Opus, VP8, VP9, AV1, H.264, H.265
WebRTC's mandatory codecs are Opus for audio and VP8/H.264 for video. The rest is optional.
Audio
- Opus — effectively the only choice. 8–510 kbps variable. Handles music and speech well. Every WebRTC implementation supports it.
- G.711 / G.722 — appear at PSTN gateways. Almost never used inside WebRTC itself.
Video
- VP8 — mandatory since early WebRTC. Highest compatibility.
- H.264 — mandatory. First-class hardware acceleration on iOS Safari. Preferred in the U.S. market.
- VP9 — optional. The efficient codec preceding AV1. Chrome and Firefox support.
- AV1 — optional. The most efficient (30% better than VP9). Encoding cost is high so it doesn't fit every scenario. Desktop hardware acceleration went mainstream in 2026 and adoption is moving fast.
- H.265 (HEVC) — almost never used inside WebRTC. Licensing burden.
Simulcast and SVC
- Simulcast — the publisher sends the same video at multiple resolutions/bitrates simultaneously. The SFU picks one per receiver.
- SVC — one stream contains a base layer plus enhancement layers. The SFU strips layers as needed. Strong in AV1 and VP9.
Decisions
- Start with VP8 + Opus. Compatible everywhere.
- iOS-first → add H.264 too.
- Bandwidth-saving and high-quality → add AV1, factoring in encoding cost.
- Always turn simulcast on. Without per-receiver adaptation, a big room collapses.
12. Managed vs Self-Host Decision Matrix
The one big decision. This matrix is the guide.
| Situation | Recommendation | Reason |
|---|---|---|
| MVP, ship inside 6 months | Managed (LiveKit Cloud, Daily, 100ms) | Don't spend your time on media infrastructure |
| Voice-agent-centric (LLM, STT, TTS) | LiveKit (Cloud or OSS) | The Agents framework is waiting |
| Internal company meeting solution | Jitsi self-hosted | The "solution" lands as-is |
| WHIP live ingestion | LiveKit Ingress or Cloudflare Realtime | First-class WHIP support |
| Global distribution, edge routing | Cloudflare Realtime or LiveKit Cloud | SFU on the edge |
| Minimize infrastructure cost (mid-scale) | LiveKit OSS self-hosted | Avoid managed per-minute pricing |
| Total control over signaling and routing | mediasoup | Library-shaped, every decision is yours |
| Deep AWS ecosystem integration | AWS Chime SDK | Syncs with IAM, S3, CloudWatch |
| Telephony (PSTN) integration | Twilio Voice + LiveKit SIP | Twilio Voice is alive |
| India and Southeast Asia pricing | 100ms | Price competitiveness |
Signals to move from managed to self-hosted
- Managed bills start exceeding USD 5,000 a month → that's beyond the cost of self-hosted infra plus one DevOps engineer.
- Data sovereignty, HIPAA, or on-prem requirements → managed becomes hard.
- You need deep work on the media pipeline (custom transcoding, custom routing) → the managed abstraction blocks you.
The hidden costs of self-hosting
- TURN servers — you absorb traffic for the fraction of users behind corporate firewalls. Traffic is expensive.
- Load balancers and node clustering.
- Recording storage and transcoding workers.
- Monitoring and observability (WebRTC stats are the hardest part).
- Incident response — media servers are trickier than other servers.
13. Client-Side Libraries
The client matters as much as the server. Half the decision.
Plain RTCPeerConnection
- The browser default API. Lightest, but you write the signaling yourself.
- Fits small P2P demos, WHIP egress, very light situations.
LiveKit Client SDK
- Abstractions Room, Participant, Track. Auto-reconnect, simulcast, DataChannel.
@livekit/components-react— a meeting UI in minutes.
Daily's call-frame
- A one-line iframe embed. Simplest. Full SDK available separately.
mediasoup-client
- Pairs with a mediasoup server. Transport / producer / consumer abstractions.
Janus's JS adapter
- Pairs with a Janus server. REST/WebSocket signaling.
simple-peer
- The simplest P2P library. You drive the signaling yourself.
14. Operations — TURN, NAT, Monitoring
Half of operations goes into signaling, NAT, and observability.
STUN and TURN
- STUN — the server that helps a client learn its public IP/port. One UDP RTT.
- TURN — a media relay for users behind NAT (symmetric NAT, firewalls) where STUN doesn't work. Traffic flows through TURN, so it is expensive.
coturn— the de facto OSS TURN implementation.- TURN traffic ratio is usually 5–20%. With many corporate networks, up to 50%.
Observability via getStats()
- The standard
RTCPeerConnection.getStats()gives you RTT, jitter, packet loss, codec, resolution, and more. - Collect once a minute and stream it into your data warehouse.
- Managed (Daily, LiveKit Cloud) gives you a dashboard for this.
Call-quality KPIs
- MOS (Mean Opinion Score) — a 1–5 call quality score. Estimated from RTT, packet loss, jitter.
- Join-failure rate — the fraction that couldn't reach the room. The core SLI.
- Reconnect frequency — number of reconnects per call.
- Video freeze time — accumulated time the video was stuck.
15. Live-Streaming Scenarios
Live broadcast has settled into a separate area of WebRTC infrastructure. Per-scenario recommendations.
| Scenario | Publishing | Routing | Receiving |
|---|---|---|---|
| One speaker → 10,000 viewers | OBS WHIP egress | LiveKit or Cloudflare Realtime SFU | HLS transcode, then HLS viewers |
| One speaker → 100 interactive | OBS WHIP egress | LiveKit SFU | WHEP receive |
| Multi-party meeting recording → broadcast | LiveKit Room | LiveKit Egress | HLS transcode |
| Gameplay broadcast → interactive chat | OBS WHIP | Cloudflare Realtime | WHEP or HLS |
Where WebRTC live replaces RTMP live, and where it doesn't
- Very large viewer counts (100K+) → HLS/DASH still own CDN distance. WebRTC fits up to ~50K.
- Broadcast features like ad insertion and DRM run deeper in HLS.
- WebRTC live wins where "low latency + two-way interaction" matters.
16. Security, DRM, and E2EE
WebRTC is DTLS-SRTP encrypted by default. Media packets are always encrypted between client and server. But in SFU mode the SFU does see plaintext for routing decisions (codec info, simulcast layer selection, and so on).
E2EE — Insertable Streams
- For true end-to-end encryption, use Insertable Streams so even the SFU can't see plaintext.
- Adopted by LiveKit, Jitsi, and Google Meet. Managed key handling is the core problem.
- Cost: simulcast efficiency drops, and server-side recording/transcoding gets hard.
DRM
- WebRTC and DRM don't pair well. DRM is about content protection, WebRTC is about real-time interaction.
- If you need DRM for live broadcast, go HLS + Widevine.
17. Case Study — A Full-Stack AI Voice Agent
What happens when these tools come together? The most common scenario.
[User browser]
|
| WebRTC audio in/out
v
[LiveKit Server]
|
| LiveKit Agents worker joins the room automatically
v
[Agents Worker (Python)]
|
+-- Deepgram STT (streaming)
+-- OpenAI gpt-4o-mini (LLM)
+-- ElevenLabs TTS (streaming)
+-- Silero VAD (turn taking)
|
| Sends TTS audio back into the LiveKit room
v
[User browser — immediate playback]
Latency breakdown (target: under 700 ms)
- User stops speaking → VAD decides the turn: 100–200 ms
- Final STT result locked in: 50–100 ms
- LLM first token: 200–400 ms
- First TTS audio chunk: 100–200 ms
- WebRTC transport delay: 50–150 ms
Total: 500–1,000 ms. About the limit at which people feel "this is a conversation".
OpenAI Realtime + WebRTC direct mode
In the picture above Deepgram, OpenAI, and ElevenLabs collapse into one model. Latency drops to 200–400 ms.
[User browser]
|
| Direct WebRTC audio
v
[OpenAI Realtime endpoint]
|
| The model handles audio input/output itself
v
[User browser — response audio]
The trade-off
- Pros: very low latency. The model directly senses speech nuances (laughter, interruptions).
- Cons: pricing is high. Model choice is locked to OpenAI. You lose freedom in STT/TTS.
Most production systems run both. Fast conversation uses Realtime, while tool-calling and custom TTS run on a plain LLM plus separate STT/TTS.
18. Common Anti-Patterns
Things I have seen far too often.
- Trying to run a 4+ person room on P2P mesh — it collapses at 5. Go SFU from day one.
- Shipping without a TURN server — the moment users come in from behind corporate networks, call-failure rate hits 30%.
- Disabling simulcast and broadcasting one resolution — in a 10-person room, one person on mobile 4G drops everybody.
- Treating
getUserMediapermission as "one and done" — permission changes per page and per session. Re-check every time. - Trying to run the SFU inside one WebSocket signaling process — signaling is signaling and media is media. Don't merge them.
- Skipping WebRTC stats collection — one user reports "it's choppy" and you can't reproduce. Collect
getStats()once a minute. - Cramming recording/transcoding into the SFU process — one encoding session stalls the entire SFU. Split into a separate worker.
- Weak VAD in AI voice agents — the model interrupts before the user finishes, or doesn't respond when they do.
- Accepting only RTMP among WHIP/RTMP/SRT — in 2026 you can't push AV1 or VP9 over RTMP. Add WHIP as an option.
- Self-hosted with monitoring limited to 5 PromQL metrics — media-server observability runs a level deeper than general web servers.
19. The Big Picture — What Became the Standard
The summary as of May 2026.
- LiveKit is the standard for AI voice-agent infrastructure — Agents framework, OpenAI adoption, both OSS and Cloud.
- Pion is the WebRTC engine of Go — LiveKit, Galene, OBS WHIP all sit on Pion.
- WHIP/WHEP is taking RTMP's seat fast — OBS 30+ ships it by default.
- OpenAI Realtime added WebRTC direct mode — voice-agent latency at human-conversation level.
- Cloudflare Realtime created the edge-SFU category — first-class global distribution.
- The managed camp is still strong — Daily, 100ms, AWS Chime SDK. But under price pressure.
- Twilio Video is essentially gone — new sign-ups closed, EOL in progress.
- mediasoup, Janus, and Jitsi solidified as the three branches of self-host.
Decision checklist
- AI voice agents at the core? — LiveKit + LiveKit Agents.
- Need an internal meeting solution? — Self-host Jitsi.
- Live broadcast ingestion at the core? — WHIP + LiveKit Ingress or Cloudflare Realtime.
- Global edge distribution first? — Cloudflare Realtime or LiveKit Cloud.
- Need first-class managed analytics? — Daily.
- Need India/SEA pricing competitiveness? — 100ms.
- Need deep AWS integration? — AWS Chime SDK.
- Need to dig into a small SFU fragment in Go? — Pion directly.
- Want full control over signaling/routing in Node.js? — mediasoup.
- Want a very stable, very old C daemon? — Janus.
Anti-pattern summary
- 4+ people on P2P mesh.
- Shipping without TURN.
- Disabling simulcast.
- No WebRTC
getStats()collection. - Signaling, SFU, recording, and transcoding in one process.
- Weak VAD in AI agents.
- Receiving only RTMP (no WHIP).
- Forcing MCU in large rooms.
- Mixing managed and self-hosted without a decision.
- Enabling E2EE while expecting server-side recording to work.
Next post preview
Candidates for the next post: LiveKit Agents deep — token-streaming, tool calling, interruption handling, A month operating WHIP/WHEP ingestion — comparing OBS, Cloudflare, and LiveKit, 100 WebRTC getStats() metrics — what to watch and what to ignore.
"WebRTC is not one standard but a bundle of standards. The teams that can operate the bundle go the farthest."
— WebRTC Media Infrastructure 2026, end.
References
- LiveKit official
- LiveKit GitHub — livekit/livekit
- LiveKit Agents framework docs
- LiveKit Agents GitHub — livekit/agents
- LiveKit Cloud pricing
- Pion official
- Pion WebRTC GitHub
- Daily.co official
- 100ms official
- mediasoup official
- Janus Gateway official
- Jitsi Meet official
- Twilio Video docs
- AWS Chime SDK docs
- Cloudflare Realtime official
- Cloudflare Calls announcement
- WHIP IETF standard RFC 9725
- WHEP IETF draft
- OBS Studio — WHIP egress
- OpenAI Realtime API docs
- OpenAI Realtime + WebRTC guide
- Deepgram Nova models
- ElevenLabs TTS docs
- Cartesia TTS
- Silero VAD GitHub
- coturn GitHub — OSS TURN server
- WebRTC
getStats()on MDN - Insertable Streams on MDN
- Opus codec
- AV1 codec
- Galene SFU GitHub
- ion-sfu GitHub
- webrtc-rs GitHub