Stream In (Ingress)
Stream into BaxCloud rooms from OBS Studio, FFmpeg, or any RTMP/WHIP-compatible encoder
Overview
BaxCloud Ingress allows external video sources like OBS Studio, FFmpeg, vMix, or hardware encoders to stream directly into a BaxCloud room. Viewers in the room see the ingress stream as a regular participant, enabling professional broadcasting setups with your existing streaming tools.
RTMP / RTMPS
Use OBS Studio, vMix, Wirecast, or any RTMP encoder. Supports secure RTMPS with TLS.
WHIP
WebRTC-HTTP Ingestion Protocol for ultra-low latency browser-based ingest (~300ms).
Any Encoder
Works with FFmpeg, GStreamer, hardware encoders, and mobile streaming apps.
RTMP vs WHIP: Which to Use?
RTMP / RTMPS
- Best for OBS Studio, vMix, Wirecast
- Widely supported by all streaming software
- RTMPS provides TLS encryption
- Latency: ~1-2 seconds
- Codecs: H.264 video + AAC audio
WHIP (WebRTC)
- Best for browser-based ingest
- Ultra-low latency (~300ms)
- Can bypass transcoding for lower CPU usage
- OBS 30+ supports WHIP natively
- Codecs: VP8/VP9/H.264 video + Opus audio
How Stream In Works
1. Start Streaming In
Use the API or SDK to create an ingress endpoint for a specific room. You'll receive an RTMP URL + Stream Key (for RTMP) or a WHIP URL + Bearer Token (for WHIP).
2. Configure Your Encoder
Enter the URL and stream key into OBS Studio, FFmpeg, or your preferred encoder. For RTMPS, use rtmps://rtmps.your-domain.io:1935/live with the stream key. For WHIP, use the WHIP URL with the bearer token.
3. Start Streaming
Press "Start Streaming" in your encoder. The stream appears in the BaxCloud room as a participant. All room viewers see the stream with low latency via WebRTC.
4. Monitor & Control
Monitor ingress status via the dashboard or API. The ingress transitions through states: INACTIVE → BUFFERING → ACTIVE → COMPLETE. You can delete the ingress endpoint to disconnect the encoder.
SDK Methods
All available ingress (stream-in) methods across every SDK
| Method | Node.js (Server) | React / React Native | Flutter | Kotlin | Swift |
|---|---|---|---|---|---|
| Start stream in | startStreamIn() | startStreamIn() | startStreamIn() | startStreamIn() | startStreamIn() |
| List stream in | listStreamIn() | listStreamIn() | listStreamIn() | listStreamIn() | listStreamIn() |
| Get stream in | getStreamIn() | getStreamIn() | getStreamIn() | getStreamIn() | getStreamIn() |
| Stop stream in | stopStreamIn() | stopStreamIn() | stopStreamIn() | stopStreamIn() | stopStreamIn() |
startStreamIn() — Start Streaming In
Create an RTMP or WHIP ingress for streaming into a room from OBS, FFmpeg, etc.
1import { BaxCloudClient } from '@baxcloud/server-sdk';
2
3const client = new BaxCloudClient({
4 apiKey: process.env.BAXCLOUD_API_KEY!,
5});
6
7// Create RTMP ingress (for OBS Studio)
8const rtmpIngress = await client.startStreamIn({
9 inputType: 'RTMP_INPUT',
10 roomName: 'my-live-room',
11 participantIdentity: 'obs-streamer',
12 participantName: 'OBS Studio',
13 enableTranscoding: true,
14});
15
16console.log('RTMPS URL:', rtmpIngress.rtmpsUrl);
17console.log('Stream Key:', rtmpIngress.streamKey);
18
19// Create WHIP ingress (for browser/OBS 30+)
20const whipIngress = await client.startStreamIn({
21 inputType: 'WHIP_INPUT',
22 roomName: 'my-live-room',
23 participantIdentity: 'whip-streamer',
24 participantName: 'Browser Streamer',
25 bypassTranscoding: true,
26});
27
28console.log('WHIP URL:', whipIngress.whipUrl);
29console.log('Bearer Token:', whipIngress.token);Server-side recommended
listStreamIn() — List Active Streams In
List all ingress endpoints, optionally filtered by room name
1const { items } = await client.listStreamIn({
2 roomName: 'my-live-room', // optional filter
3});
4
5for (const ingress of items) {
6 console.log(`[${ingress.inputType}] ${ingress.participantName}`);
7 console.log(` Status: ${ingress.status}`);
8 console.log(` Stream Key: ${ingress.streamKey}`);
9}getStreamIn() — Get Stream In Details
Get the status and details of a specific ingress endpoint by ID
1const ingress = await client.getStreamIn('IN_abc123');
2console.log('Status:', ingress.status);
3// → INACTIVE | BUFFERING | ACTIVE | ERROR | COMPLETE
4console.log('Input Type:', ingress.inputType);
5console.log('Room:', ingress.roomName);stopStreamIn() — Stop a Stream In Endpoint
Remove an ingress endpoint and disconnect the encoder
1await client.stopStreamIn('IN_abc123');
2// Encoder is disconnected immediatelyConfigure OBS Studio
Set up OBS to stream to your BaxCloud room
In OBS Studio, go to Settings → Stream:
- Service: Custom...
- Server:
rtmps://rtmps.your-domain.io:1935/live - Stream Key: paste the stream key from
startStreamIn()
- Service: WHIP
- Server: paste the WHIP URL from
startStreamIn() - Bearer Token: paste the token from
startStreamIn()
RTMP Encoder Settings
FFmpeg & Other Encoders
1# Stream a file via RTMPS
2ffmpeg -re -i input.mp4 \
3 -c:v libx264 -preset veryfast -b:v 3000k \
4 -c:a aac -b:a 128k \
5 -f flv "rtmps://rtmps.your-domain.io:1935/live/YOUR_STREAM_KEY"
6
7# Stream webcam via RTMPS (macOS)
8ffmpeg -f avfoundation -i "0:0" \
9 -c:v libx264 -preset veryfast -b:v 2500k \
10 -c:a aac -b:a 128k \
11 -f flv "rtmps://rtmps.your-domain.io:1935/live/YOUR_STREAM_KEY"
12
13# Stream webcam via RTMPS (Linux)
14ffmpeg -f v4l2 -i /dev/video0 -f pulse -i default \
15 -c:v libx264 -preset veryfast -b:v 2500k \
16 -c:a aac -b:a 128k \
17 -f flv "rtmps://rtmps.your-domain.io:1935/live/YOUR_STREAM_KEY"Webhook Events
Receive real-time notifications for ingress lifecycle events
BaxCloud sends webhook events when an ingress stream starts, updates, or ends. Configure webhooks in your project dashboard settings.
| Event | Description | When |
|---|---|---|
| live.started | Ingress stream has started | Encoder connects and stream begins buffering/active |
| live.updated | Ingress state changed | State transitions (BUFFERING → ACTIVE, etc.) |
| live.ended | Ingress stream has ended | Encoder disconnects or ingress is deleted |
| live.failed | Ingress stream failed | Connection error, encoding failure, etc. |
1// Webhook payload for live.started
2{
3 "event": "live.started",
4 "timestamp": "2026-03-29T14:30:00Z",
5 "data": {
6 "ingressId": "IN_abc123",
7 "roomName": "my-live-room",
8 "inputType": "RTMP", // "RTMP" or "WHIP"
9 "participantIdentity": "obs-streamer",
10 "participantName": "OBS Studio",
11 "status": "ACTIVE"
12 }
13}
14
15// Webhook payload for live.ended
16{
17 "event": "live.ended",
18 "timestamp": "2026-03-29T15:45:00Z",
19 "data": {
20 "ingressId": "IN_abc123",
21 "roomName": "my-live-room",
22 "inputType": "RTMP",
23 "participantIdentity": "obs-streamer",
24 "status": "COMPLETE",
25 "durationSec": 4500
26 }
27}
28
29// Webhook payload for live.failed
30{
31 "event": "live.failed",
32 "timestamp": "2026-03-29T14:31:00Z",
33 "data": {
34 "ingressId": "IN_abc123",
35 "roomName": "my-live-room",
36 "inputType": "RTMP",
37 "status": "ERROR",
38 "errorMessage": "Connection timeout — encoder stopped sending data"
39 }
40}REST API Reference
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/ingress | Create a new ingress endpoint |
GET | /v1/ingress | List all ingress endpoints |
GET | /v1/ingress/:id | Get ingress details by ID |
DELETE | /v1/ingress/:id | Delete an ingress endpoint |
Create Ingress Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| inputType | string | Yes | RTMP_INPUT or WHIP_INPUT |
| roomName | string | Yes | Target room name |
| participantIdentity | string | Yes | Unique identity for the ingress participant |
| participantName | string | No | Display name shown in room |
| enableTranscoding | boolean | No | Enable server-side transcoding (default: true) |
| bypassTranscoding | boolean | No | WHIP only — bypass transcoding for lower latency |