iPipe Developer Platform
iPipe is an enterprise-grade, developer-first real-time communications API platform designed as an open, high-performance alternative to Agora, Twilio Video, and 100ms. It provides complete infrastructure including a Selective Forwarding Unit (SFU) media router, WebSocket signaling, HMAC-SHA256 token security, and comprehensive client SDKs.
5-Minute Quickstart
Install the client and server SDK packages into your application:
npm install @ipipe/web-sdk @ipipe/server-sdk
Initialize in Web Application
import { iPipe } from "@ipipe/web-sdk";
// 1. Create client instance
const client = iPipe.createClient({ mode: "rtc", codec: "vp8" });
// 2. Listen to remote participant streams
client.on("user-published", async (user, mediaType) => {
const remoteTrack = await client.subscribe(user, mediaType);
if (mediaType === "video") {
remoteTrack.play("remote-video-container");
} else {
remoteTrack.play();
}
});
// 3. Create local camera & microphone tracks
const localAudio = await iPipe.createMicrophoneAudioTrack();
const localVideo = await iPipe.createCameraVideoTrack();
localVideo.play("local-video-container");
// 4. Join channel and publish local streams
await client.join("rtc_cloud_demo_app_prod_001", "room_alpha", token, "user_101");
await client.publish([localAudio, localVideo]);
Agora to iPipe Migration Guide
iPipe was purposefully engineered with 100% API compatibility with Agora Web SDK v4. Developers can transition existing codebases in minutes simply by updating the import package:
| Agora Web SDK v4 | iPipe Web SDK | Notes |
|---|---|---|
AgoraRTC.createClient({ mode, codec }) |
iPipe.createClient({ mode, codec }) |
Exact 1:1 parameter parity |
AgoraRTC.createCameraVideoTrack() |
iPipe.createCameraVideoTrack() |
Full resolution & frame rate support |
AgoraRTC.createMicrophoneAudioTrack() |
iPipe.createMicrophoneAudioTrack() |
Built-in AEC, ANS, AGC filters |
client.join(appId, channel, token, uid) |
client.join(appId, channel, token, uid) |
Compatible with numerical or string UIDs |
client.publish([audio, video]) |
client.publish([audio, video]) |
Dynamic track publishing |
client.on('user-published', (user, kind)) |
client.on('user-published', (user, kind)) |
Identical event naming & payload |
iPipe Client Core API
The core client interface provides complete channel state orchestration, signaling connection management, track publishing, and remote peer synchronization.
Creating a Client Instance
const client = iPipe.createClient({
mode: "rtc", // "rtc" (one-to-one or group) | "live" (interactive broadcast)
codec: "vp8", // "vp8" | "h264" | "vp9"
serverUrl: "ws://localhost:8088/ws" // Optional custom signaling endpoint
});
Client Methods Reference
| Method | Parameters | Return Type | Description |
|---|---|---|---|
join() |
(appId, channel, token, uid) |
Promise<string> |
Connects to the signaling gateway and enters the designated real-time channel. Returns assigned UID. |
publish() |
(tracks: LocalTrack | LocalTrack[]) |
Promise<void> |
Publishes local audio and/or video tracks to all participants in the channel via SFU routing. |
unpublish() |
(tracks?: LocalTrack | LocalTrack[]) |
Promise<void> |
Stops publishing specified tracks (or all tracks if omitted) without closing hardware devices. |
subscribe() |
(user: RemoteUser, mediaType: 'audio' | 'video') |
Promise<RemoteTrack> |
Subscribes to a remote participant's published audio or video stream and returns a playable track. |
unsubscribe() |
(user: RemoteUser, mediaType: 'audio' | 'video') |
Promise<void> |
Stops receiving the specified media stream from a remote participant. |
leave() |
None |
Promise<void> |
Leaves the channel, closes local tracks, releases hardware devices, and disconnects signaling. |
renewToken() |
(newToken: string) |
Promise<boolean> |
Renews authentication token without interrupting active audio/video calls. |
setClientRole() |
(role: 'host' | 'audience') |
void |
Switches user role in live broadcast mode between interactive broadcaster and passive viewer. |
setRemoteVideoStreamType() |
(uid: string, layer: 'high' | 'mid' | 'low') |
void |
Switches simulcast video layer received from a remote participant to conserve bandwidth. |
sendRtmMessage() |
(message: string, targetUid?: string) |
void |
Broadcasts real-time in-call text chat, reactions, or signaling metadata (to all or specific user). |
enableAudioVolumeIndicator() |
None |
void |
Activates 250ms periodic audio volume level metering for speaking indicators and active speaker detection. |
Connection States
Inspect client.connectionState to verify connection health:
DISCONNECTED: Initial idle state or call terminated.CONNECTING: Establishing WebSocket handshake and verifying HMAC token with gateway.CONNECTED: Successfully authenticated and active in the media room.RECONNECTING: Gateway transiently unreachable; client automatically attempting recovery.
Audio & Video Tracks
iPipe provides flexible media track creation for webcams, studio microphones, screen sharing, and synthetic procedural streams for zero-hardware automated testing.
Track Creation APIs
| Creation Function | Configuration Options | Description |
|---|---|---|
iPipe.createCameraVideoTrack(config) |
{ encoderConfig: '1080p_1' | '720p_2' | '480p_1', facingMode: 'user' | 'environment' } |
Captures hardware camera. Automatically falls back to high-definition procedural stream if hardware is blocked. |
iPipe.createMicrophoneAudioTrack(config) |
{ AEC: true, ANS: true, AGC: true } |
Captures microphone audio with Acoustic Echo Cancellation, Noise Suppression, and Automatic Gain Control. |
iPipe.createScreenVideoTrack(config) |
{ encoderConfig: '1080p_2', withAudio: boolean } |
Captures full desktop display, application window, or browser tab via getDisplayMedia. |
Track Control Methods
| Method | Parameters | Description |
|---|---|---|
track.play(elementOrId, options) |
(elementOrId: string | HTMLElement, { fit: 'cover' | 'contain', mirror: boolean }) |
Attaches track stream to target DOM element or container ID and begins smooth rendering. |
track.stop() |
None |
Removes stream from video/audio elements and halts local rendering. |
track.close() |
None |
Permanently stops hardware capture devices (webcam LED turns off) and frees memory. |
track.setMuted(muted) |
(muted: boolean) |
Mutes or unmutes media transmission instantly without breaking WebRTC session renegotiation. |
track.isMuted() |
None |
Returns boolean state indicating whether track is currently muted. |
track.getVolumeLevel() |
None |
Returns real-time audio volume amplitude integer between 0 and 100. |
track.applyVirtualBackground(mode) |
('blur' | 'none') |
Applies client-side background blur filter to webcam stream. |
Track Playback & Management Example
// Create local tracks
const micTrack = await iPipe.createMicrophoneAudioTrack({ AEC: true, ANS: true });
const camTrack = await iPipe.createCameraVideoTrack({ encoderConfig: "720p_2" });
// Render camera in DOM container
camTrack.play("local-camera-wrapper", { fit: "cover", mirror: true });
// Toggle mute state dynamically on button click
let isMuted = false;
document.getElementById("btnMute").onclick = async () => {
isMuted = !isMuted;
await micTrack.setMuted(isMuted);
console.log("Mic Muted:", micTrack.isMuted());
};
// Clean up tracks when session ends
function cleanup() {
camTrack.close();
micTrack.close();
}
HD Voice & Audio Calling (VoIP & Drop-in Rooms)
iPipe is optimized for low-latency, high-fidelity audio transmission using the Opus Fullband (48 kHz) codec. Build 1-on-1 VoIP phone calling, call center desks, or Clubhouse/Discord-style drop-in audio spaces with adaptive 16–64 kbps bitrates and Voice Activity Detection (VAD).
// 1. Create WebRTC Client in Audio-Only Mode
const audioClient = iPipe.createClient({ mode: "rtc", codec: "opus" });
// 2. Capture Studio Microphone with DSP Filters (AEC, ANS, AGC)
const micTrack = await iPipe.createMicrophoneAudioTrack({
AEC: true, // Acoustic Echo Cancellation
ANS: true, // Active Noise Suppression
AGC: true // Automatic Gain Control
});
// 3. Listen to remote participants and play incoming audio
audioClient.on("user-published", async (user, mediaType) => {
if (mediaType === "audio") {
const remoteAudio = await audioClient.subscribe(user, "audio");
remoteAudio.play(); // Direct speakerphone playback
}
});
// 4. Voice Activity Detection (VAD) Spectrum Volume Indicator
setInterval(() => {
const volume = micTrack.getVolumeLevel(); // 0 to 100
if (volume > 20) {
console.log("Speaking active! Volume level:", volume);
}
}, 100);
// 5. Join Room and Publish Audio Stream
await audioClient.join("app_id", "voice_room_101", token, "user_42");
await audioClient.publish([micTrack]);
Lifecycle Events
iPipe uses an event-driven architecture. Listen for remote peer connections, stream publishing, network quality changes, and token expiration using client.on(event, handler):
| Event Name | Callback Signature | Trigger Description |
|---|---|---|
user-published |
(user: RemoteUser, mediaType: 'audio' | 'video') => void |
Triggered when a remote participant publishes an audio or video track in the channel. |
user-unpublished |
(user: RemoteUser, mediaType: 'audio' | 'video') => void |
Triggered when a remote participant stops publishing or mutes their stream. |
user-joined |
(user: RemoteUser) => void |
Triggered when a participant joins the channel. |
user-left |
(user: RemoteUser, reason: 'QUIT' | 'DROPPED') => void |
Triggered when a participant leaves the channel or experiences a network disconnect. |
connection-state-change |
(curState: string, revState: string, reason: string) => void |
Notifies when connection transitions between CONNECTING, CONNECTED, or DISCONNECTED. |
volume-indicator |
(volumes: Array<{ uid: string, level: number }>) => void |
Periodic audio amplitude updates (0–100) for local and remote participants for speaking halos. |
network-quality |
(stats: { uplinkNetworkQuality: number, downlinkNetworkQuality: number, stats: object }) => void |
Telemetry statistics reporting real-time RTT latency, jitter, bitrate, and packet loss score (1–6). |
token-privilege-will-expire |
() => void |
Emitted 30 seconds prior to token expiration to request token renewal via client.renewToken(). |
token-privilege-did-expire |
() => void |
Emitted when the authentication token has expired. Subsequent actions will be rejected. |
rtm-message |
(data: { senderUid: string, message: string }) => void |
Triggered when an in-call real-time chat or signaling message is received from a peer. |
transcription-result |
(data: { uid: string, text: string, isFinal: boolean, confidence: number }) => void |
Triggered when AI speech transcription generates real-time closed captions. |
Lifecycle Events Example
const client = iPipe.createClient({ mode: "rtc" });
// Handle remote streams
client.on("user-published", async (user, mediaType) => {
const remoteTrack = await client.subscribe(user, mediaType);
if (mediaType === "video") {
remoteTrack.play(`remote-player-${user.uid}`);
} else {
remoteTrack.play();
}
});
// Remove UI when remote peer leaves
client.on("user-left", (user, reason) => {
console.log(`User ${user.uid} left channel. Reason:`, reason);
const container = document.getElementById(`remote-player-${user.uid}`);
if (container) container.remove();
});
// Telemetry & Network Health monitoring
client.on("network-quality", ({ uplinkNetworkQuality, stats }) => {
console.log(`RTT: ${stats.rttMs}ms, Bitrate: ${stats.bitrateKbps}kbps, Quality: ${uplinkNetworkQuality}`);
});
// Proactive Token Refresh
client.on("token-privilege-will-expire", async () => {
const res = await fetch("/api/v1/tokens/rtc", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ channel: "room_alpha" })
});
const { token: newToken } = await res.json();
await client.renewToken(newToken);
console.log("iPipe Token renewed successfully.");
});
Device Management
Enumerate available audio/video hardware, inspect system capabilities, and seamlessly hot-swap cameras or microphones mid-call without interrupting the active conversation.
Device Enumeration Methods
| Method | Return Type | Description |
|---|---|---|
iPipe.getDevices() |
Promise<MediaDeviceInfo[]> |
Returns a complete list of all connected audio inputs, audio outputs, and video capture devices. |
iPipe.getCameras() |
Promise<MediaDeviceInfo[]> |
Filters connected devices and returns only webcam and USB video input capture devices. |
iPipe.getMicrophones() |
Promise<MediaDeviceInfo[]> |
Returns all microphone input hardware (built-in arrays, USB mics, Bluetooth headsets). |
iPipe.getPlaybackDevices() |
Promise<MediaDeviceInfo[]> |
Returns all audio output playback devices (speakers, external monitors, headphones). |
iPipe.checkSystemRequirements() |
boolean |
Verifies whether the current browser supports WebRTC peer connections and media streaming. |
Building a Camera & Microphone Selector
// 1. Populate Camera Dropdown
const cameras = await iPipe.getCameras();
const camSelect = document.getElementById("cameraSelect");
cameras.forEach(cam => {
const opt = document.createElement("option");
opt.value = cam.deviceId;
opt.text = cam.label || `Camera (${cam.deviceId.slice(0, 8)})`;
camSelect.appendChild(opt);
});
// 2. Switch camera dynamically without dropping call
camSelect.onchange = async () => {
const newDeviceId = camSelect.value;
const newCamTrack = await iPipe.createCameraVideoTrack({
cameraId: newDeviceId,
encoderConfig: "720p_2"
});
await client.unpublish(currentCamTrack);
currentCamTrack.close();
currentCamTrack = newCamTrack;
currentCamTrack.play("local-video-container");
await client.publish(currentCamTrack);
};
Token Security & Generation (IPIPE007 Standard)
iPipe uses cryptographically signed HMAC-SHA256 tokens to ensure only authorized users access audio and video channels:
const { IPipeTokenBuilder, Role } = require('@ipipe/server-sdk');
const appId = "rtc_cloud_demo_app_prod_001";
const appCertificate = "8f93a1c5d0e24177b94101e4a6789f10";
const channelName = "room_alpha";
const uid = "user_101";
const role = Role.PUBLISHER; // PUBLISHER | SUBSCRIBER | ADMIN
const privilegeExpiredTs = Math.floor(Date.now() / 1000) + 3600; // 1 hour
const token = IPipeTokenBuilder.buildTokenWithUid(
appId,
appCertificate,
channelName,
uid,
role,
privilegeExpiredTs
);
console.log("Signed Token:", token); // Starts with IPIPE007...
IPipeClient REST API
Manage projects, query real-time channel status, kick unauthorized participants, and inspect billing statements via standard REST endpoints.
| Endpoint | Method | Parameters / Payload | Description |
|---|---|---|---|
/api/v1/health |
GET |
None | Returns platform uptime, cluster version, and real-time active session counts. |
/api/v1/tokens/rtc |
POST |
{ appId, appCertificate, channelName, uid, role } |
Generates an authorized IPIPE007 HMAC-SHA256 token programmatically. |
/api/v1/channels |
GET |
None | Lists all currently active real-time rooms and their connected peer counts. |
/api/v1/channels/:channel/users |
GET |
:channel route param |
Queries participant list, publish status, and audio/video tracks in a channel. |
/api/v1/channels/:channel/kick |
POST |
{ uid: string, reason: string } |
Remotely evicts a participant from the channel via signaling command. |
/api/v1/usage/summary |
GET |
None | Retrieves billable voice/video minutes, active project totals, and bandwidth usage. |
Querying Gateway Health via cURL
curl http://localhost:8088/api/v1/health
Webhooks & Event Dispatching
iPipe dispatches real-time webhooks with signature headers to notify your backend whenever channel state changes:
channel.created: New real-time room initializedchannel.destroyed: All participants left, room finalizeduser.joined: Participant entered roomuser.left: Participant left or disconnectedstream.published: Audio or video track startedrecording.started/recording.stopped: Cloud recording lifecyclequality.alert: High packet loss or latency detected
Verifying Webhook Signatures
const crypto = require('crypto');
function verifyWebhook(req, webhookSecret) {
const sigHeader = req.headers['x-ipipe-signature'] || req.headers['x-rtc-signature'];
const timestamp = req.headers['x-ipipe-timestamp'] || req.headers['x-rtc-timestamp'];
const expectedSig = crypto.createHmac('sha256', webhookSecret)
.update(`${timestamp}.${JSON.stringify(req.body)}`)
.digest('hex');
return sigHeader && sigHeader.includes(expectedSig);
}