@vibe-rtc/rtc-core
v0.4.0
Published
[](https://www.npmjs.com/package/@vibe-rtc/rtc-core)
Downloads
22
Maintainers
Readme
@vibe-rtc/rtc-core
Core WebRTC signaling/transport package with reconnect behavior and typed errors.
Install
pnpm add @vibe-rtc/rtc-coreMain API
RTCSignalerRTCError,RTCErrorCode,toRTCError,isRTCErrorwithDefaultIceServers,DEFAULT_ICE_SERVERSSignalDBinterface for custom signaling backends
SignalDB Contract
Implement SignalDB from src/types.tsx with methods for:
- room lifecycle:
createRoom,joinRoom(role?),getRoom,endRoom - SDP exchange:
getOffer,setOffer,clearOffer,setAnswer,clearAnswer - ICE exchange: add/subscribe for caller/callee candidate streams
- cleanup:
clearCallerCandidates,clearCalleeCandidates
For multi-tab safety, adapters should also expose room slot ownership in RoomDoc.slots:
slots.caller.participantId/sessionId/...slots.callee.participantId/sessionId/...
Quick Example
import { RTCSignaler } from '@vibe-rtc/rtc-core'
const signaler = new RTCSignaler('caller', signalDb, {
debug: true,
waitReadyTimeoutMs: 10000,
rtcConfiguration: {
iceServers: [
{ urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'] },
],
},
})
const roomId = await signaler.createRoom()
await signaler.joinRoom(roomId)
await signaler.connect()
await signaler.sendReliable('hello')
await signaler.reconnectSoft()
await signaler.reconnectHard({ awaitReadyMs: 15000 })
await signaler.endRoom()Runtime Options
debug: enables internal console logs (console.log/console.error).
By default logs are enabled only in test runtime.waitReadyTimeoutMs: default timeout forwaitReady()andreconnectHard()if no timeout is passed explicitly.connectionStrategy:"LAN_FIRST"(default),"DEFAULT"or"BROWSER_NATIVE"."LAN_FIRST"starts with host-only LAN candidates and no STUN/TURN, then falls back to STUN on timeout."DEFAULT"createsRTCPeerConnectionwith regular STUN behavior immediately."BROWSER_NATIVE"passes full ICE config (stun/turn) to browser and lets WebRTC choose route natively.
lanFirstTimeoutMs: LAN-first fallback timeout in milliseconds (default1800).stunServers: STUN servers used in fallback/default STUN mode.
Defaults to[{ urls: "stun:stun.l.google.com:19302" }].rtcConfiguration: optionalRTCPeerConnectionconfig.
If omitted (or ificeServersis empty),rtc-coreinjects default STUN servers.
LAN-first Strategy
With connectionStrategy: "LAN_FIRST":
- Phase
LAN:RTCPeerConnectionstarts withiceServers: []and onlytyp hostcandidates are sent/accepted. - Phase
STUN: if not connected beforelanFirstTimeoutMs, the current peer is closed and rebuilt with STUN enabled. - Signaling payload format is backward-compatible. Signaling messages include
sessionIdand stale messages from old sessions are ignored. - Debug snapshots (
onDebug) include strategy phase, candidate counters by type (host/srflx/relay) and selected ICE route fromgetStats()(transport.selectedCandidatePairId/ nominated fallback).
Browser-native Strategy
With connectionStrategy: "BROWSER_NATIVE":
RTCPeerConnectionis created with the full configurediceServerslist (no STUN/TURN split).- ICE candidates are not filtered by transport phase (only stale-session safety checks remain).
- Path selection is delegated to browser ICE agent (native WebRTC behavior).
Takeover / Session Isolation
rtc-core supports "last tab wins" for the same role in the same room:
- adapter marks each role slot with
participantId+sessionId - any incoming offer/answer/candidate with foreign
sessionIdis ignored as stale - if current role slot owner changes (
participantIdmismatch) active signaler stops withINVALID_STATE(takeover detected) - if role slot keeps same participant but
sessionIdchanges, it is also treated as takeover (stale tab / old session) - during takeover shutdown
hangup()skips best-effortsignalDb.leaveRoom()write to avoid stale-tab writes
This prevents old tabs from corrupting signaling state after takeover/reload.
Error Handling
Use RTCErrorCode for stable UI/test handling:
ROOM_NOT_SELECTEDROOM_NOT_FOUNDAUTH_REQUIREDDB_UNAVAILABLESIGNAL_TIMEOUTWAIT_READY_TIMEOUTSIGNALING_FAILEDINVALID_STATEUNKNOWN
Development
pnpm --filter @vibe-rtc/rtc-core build
pnpm --filter @vibe-rtc/rtc-core test