@newgameplusinc/odyssey-stream-sdk
v1.0.0
Published
Odyssey Stream SDK - Receives space-live-broadcast via Socket.IO and forwards RTP to Unreal Engine
Downloads
82
Readme
Odyssey Stream SDK
RTP-based video stream forwarder for Unreal Engine. Receives video from MediaSoup server via PlainTransport and forwards to Unreal MediaPlayer.
Architecture
┌──────────────────────────────────────────────────────────────────┐
│ VUE.JS (Frontend) │
│ User clicks "Cast to Space Screens" │
│ Emits 'start-space-live-broadcast' via Socket.IO │
└──────────────────────────────────────────────────────────────────┘
│
│ WebRTC + Socket.IO
▼
┌──────────────────────────────────────────────────────────────────┐
│ MEDIASOUP SERVER │
│ Receives screen share as Producer │
│ Emits 'space-live-broadcast-available' │
│ Creates PlainTransport for SDK │
│ Sends RTP packets to SDK │
└──────────────────────────────────────────────────────────────────┘
│
│ RTP (UDP)
▼
┌──────────────────────────────────────────────────────────────────┐
│ ODYSSEY STREAM SDK │
│ (Runs alongside Unreal) │
│ │
│ 1. Connects via Socket.IO to MediaSoup server │
│ 2. Listens for 'space-live-broadcast-available' event │
│ 3. Requests PlainTransport from MediaSoup │
│ 4. Receives RTP packets (no decoding) │
│ 5. Forwards RTP to localhost:5006 │
│ 6. Generates SDP file for Unreal │
│ │
│ Output: RTP on udp://127.0.0.1:5006 + stream.sdp │
└──────────────────────────────────────────────────────────────────┘
│
│ RTP (localhost)
▼
┌──────────────────────────────────────────────────────────────────┐
│ UNREAL ENGINE │
│ MediaPlayer->OpenUrl("file:///path/to/stream.sdp") │
│ Receives raw RTP video on UDP port 5006 │
└──────────────────────────────────────────────────────────────────┘Latency
~100ms end-to-end (Vue → Unreal)
Setup
1. Install Dependencies
npm install2. Build
npm run build3. Run
npm start <serverUrl> <roomId>Example:
npm start wss://api.odyssey.dev.example.com room-abc-123Development with ts-node:
npm run dev wss://api.odyssey.dev.example.com room-abc-123Environment-Specific Server URLs
The SDK does not auto-detect environment. You must provide the correct serverUrl for your environment:
| Environment | Server URL (example) |
|-------------|---------------------|
| Development | wss://api.odyssey.dev.example.com |
| Testing | wss://api.odyssey.testing.example.com |
| Production | wss://api.odyssey.example.com |
Note: Get the actual server URL from your deployment config or the frontend's environment config (
odyssey-v2/src/config/).
Where Data Comes From
| Data | Source | How |
|------|--------|-----|
| serverUrl | You provide | Command line arg or programmatic |
| roomId | You provide | Command line arg or programmatic |
| producerId | Socket.IO event | space-live-broadcast-available event |
| Stream status | Socket.IO events | available / stopped events |
| RTP params | Socket.IO response | consume-plain-transport response |
No Firebase access required - all stream info comes from MediaSoup server via Socket.IO.
Configuration Options
Environment variables for runtime overrides:
| Variable | Default | Description |
|----------|---------|-------------|
| UNREAL_RTP_HOST | 127.0.0.1 | Host to forward RTP packets to |
| UNREAL_RTP_PORT | 5006 | Port to forward RTP packets to |
| SDP_OUTPUT_PATH | ./stream.sdp | Where to write the SDP file |
| RTP_LISTEN_PORT_MIN | 10000 | Minimum port for RTP reception |
| RTP_LISTEN_PORT_MAX | 10100 | Maximum port for RTP reception |
How It Works
- SDK connects to MediaSoup server via Socket.IO
- SDK listens for
space-live-broadcast-availableevent - When broadcast starts:
- Creates PlainTransport on server
- Starts receiving RTP packets
- Forwards RTP to Unreal (localhost:5006)
- Generates SDP file for Unreal
- When broadcast stops (
space-live-broadcast-stoppedevent):- Closes MediaSoup resources
- Stops RTP forwarding
- Deletes SDP file
Programmatic Usage
import { OdysseyStreamSDK } from 'odyssey-stream-sdk';
const sdk = new OdysseyStreamSDK({
serverUrl: 'wss://api.odyssey.example.com',
roomId: 'room-abc-123',
unrealHost: '127.0.0.1', // optional
unrealPort: 5006, // optional
sdpOutputPath: './stream.sdp', // optional
});
sdk.on('streamStarted', ({ sdpPath }) => {
console.log(`Stream ready! Open in Unreal: ${sdpPath}`);
});
sdk.on('streamStopped', () => {
console.log('Stream stopped');
});
await sdk.start();Unreal Integration
In Unreal, open the SDP file with MediaPlayer:
UMediaPlayer* Player = NewObject<UMediaPlayer>();
Player->OpenUrl(TEXT("file:///path/to/stream.sdp"));The SDP file location is printed when stream starts.
Files
odyssey-stream-sdk/
├── src/
│ ├── index.ts # Entry point
│ ├── config/ # RTP/Unreal config
│ ├── core/ # OdysseyStreamSDK, StreamManager
│ ├── services/
│ │ ├── mediasoup/ # MediaSoupClient
│ │ ├── rtp/ # RtpForwarder (UDP)
│ │ └── sdp/ # SdpGenerator
│ ├── types/ # TypeScript types
│ └── utils/ # Logger, network utils
├── package.json
├── tsconfig.json
└── README.mdServer Requirements
MediaSoup server needs these socket handlers:
| Event | Direction | Purpose |
|-------|-----------|---------|
| space-live-broadcast-available | Server → SDK | Notify when broadcast starts |
| space-live-broadcast-stopped | Server → SDK | Notify when broadcast stops |
| get-space-live-broadcast-status | SDK → Server | Check for active broadcast |
| create-plain-transport-consumer | SDK → Server | Create PlainTransport for SDK |
| consume-plain-transport | SDK → Server | Create consumer on transport |
| close-consumer | SDK → Server | Close consumer |
| close-plain-transport | SDK → Server | Close transport |
Socket.IO Event Payloads
space-live-broadcast-available (Server → SDK):
{
roomId: string;
producerId: string;
producerUserId: string;
}space-live-broadcast-stopped (Server → SDK):
{
roomId: string;
}get-space-live-broadcast-status (SDK → Server):
// Request:
{ roomId: string }
// Response:
{
isActive: boolean;
producerId?: string;
producerUserId?: string;
}create-plain-transport-consumer (SDK → Server):
// Request:
{
roomId: string;
clientIp: string;
rtpPort: number;
rtcpPort: number;
}
// Response:
{
success: boolean;
transportId: string;
serverRtpPort: number;
serverRtcpPort: number;
}consume-plain-transport (SDK → Server):
// Request:
{
roomId: string;
transportId: string;
}
// Response:
{
success: boolean;
consumerId: string;
producerId: string;
kind: 'video';
rtpParameters: object;
ssrc: number;
payloadType: number;
}Troubleshooting
"Connection timeout" or "Connection error"
- Check serverUrl is correct (wss:// for HTTPS servers)
- Check server is running and accessible
- Check firewall allows WebSocket connections
"No RTP packets received"
- Check firewall allows UDP on configured ports (10000-10100)
- Check MediaSoup server has PlainTransport handlers
- Verify producer is active with
get-space-live-broadcast-status
Unreal not showing video
- Check SDP file is generated (look for log message)
- Check Unreal MediaPlayer opened the SDP file
- Verify RTP packets are being received (check SDK logs)
