A simple, powerful RTMP relay server that simultaneously streams to multiple platforms (Twitch, YouTube, Rumble, Kick, and more) from a single input stream.
- ✅ Stream to multiple platforms simultaneously
- ✅ HLS output with copy codecs (no re-encoding, low CPU usage)
- ✅ Automatic reconnection on failures
- ✅ Watchdog monitoring for stalled connections
- ✅ Detailed logging per destination
- ✅ Easy platform enable/disable
- ✅ Graceful shutdown handling
- ✅ PM2 process management support
- Node.js (v14 or higher)
- FFmpeg installed (
sudo apt install ffmpegon Ubuntu/Debian) - PM2 for process management (optional but recommended)
# Install dependencies
npm install
# Install PM2 (optional)
npm install -g pm2Edit app.js and update the destinations array with your stream keys:
const destinations = [
{
name: 'Twitch',
enabled: true,
url: 'rtmp://live.twitch.tv/app/YOUR_TWITCH_STREAM_KEY'
},
{
name: 'YouTube',
enabled: true,
url: 'rtmp://a.rtmp.youtube.com/live2/YOUR_YOUTUBE_STREAM_KEY'
},
// Add more as needed...
];Each destination supports these options:
name- Display name for loggingenabled- Set tofalseto disable a destinationurl- Full RTMP/RTMPS URL with stream keyautoReconnect- Auto-reconnect on disconnect (optional)watchdog- Monitor for stalls and restart (optional, default: true)
# Start the server
pm2 start app.js --name nms
# Save configuration
pm2 save
# Setup auto-start on boot
pm2 startup
# View logs
pm2 logs nms
# Stop the server
pm2 stop nmsnode app.jsPoint your streaming software (OBS, Streamlabs, etc.) to:
Server: rtmp://YOUR_SERVER_IP:1935/live
Stream Key: YOUR_STREAM_KEY (can be anything, e.g., "test123")
Example OBS settings:
- Service: Custom
- Server:
rtmp://45.55.54.155:1935/live - Stream Key:
mystream
The server automatically generates HLS streams for each active stream. HLS uses copy codecs (no re-encoding), keeping CPU usage very low.
How it works:
- HLS stream keys work exactly like RTMP - you use any stream key you want
- The HLS path is automatically derived from your RTMP stream path
- When you stream to
rtmp://server:1935/live/YOUR_KEY, HLS is created athttp://server:8001/hls/live__YOUR_KEY/index.m3u8
HLS URL Format:
http://YOUR_SERVER_IP:8001/hls/[STREAM_PATH]/index.m3u8
(Stream path has / replaced with __)
Examples:
When streaming with OBS settings:
- Server:
rtmp://server:1935/live - Stream Key:
mystream
The full RTMP path is /live/mystream, which becomes HLS path live__mystream:
| OBS Settings | Full RTMP Path | HLS URL |
|---|---|---|
Server: rtmp://server:1935/liveKey: mystream |
/live/mystream |
http://server:8001/hls/live__mystream/index.m3u8 |
Server: rtmp://server:1935/liveKey: test123 |
/live/test123 |
http://server:8001/hls/live__test123/index.m3u8 |
Server: rtmp://server:1935/appKey: streamkey |
/app/streamkey |
http://server:8001/hls/app__streamkey/index.m3u8 |
Note: The format is [APP_NAME]__[STREAM_KEY] where __ replaces the / in the full RTMP path.
Important: HLS uses copy codecs, so your input stream must be:
- Video: H.264 codec (most RTMP streams from OBS are H.264)
- Audio: AAC codec (most RTMP streams from OBS are AAC)
If your stream uses different codecs, the copy mode will fail. For typical OBS/Streamlabs streams, this works perfectly!
HLS Configuration:
You can customize HLS settings in app.js:
HLS_ENABLED: Enable/disable HLS output (default:true)HLS_HTTP_PORT: HTTP port for serving HLS files (default:8001)HLS_SEGMENT_TIME: Segment duration in seconds (default:2)HLS_PLAYLIST_SIZE: Number of segments in playlist (default:6)
Firewall: Make sure port 8001 (or your configured HLS port) is open:
ufw allow 8001/tcpTesting HLS: You can test the HLS stream using VLC or any HLS-compatible player:
- VLC: Media → Open Network Stream → Enter the HLS URL
- Or use in an HTML5 video player:
<video src="http://YOUR_SERVER_IP:8001/hls/live__mystream/index.m3u8" controls></video>All FFmpeg logs are saved to the logs/ directory:
logs/live__STREAMKEY--PlatformName.err.log- FFmpeg error outputlogs/live__STREAMKEY--PlatformName.out.log- FFmpeg standard output
View logs in real-time:
tail -f logs/*.err.logTo add a new streaming platform:
- Find their RTMP ingest URL and get your stream key
- Add to the
destinationsarray:
{
name: 'Facebook',
enabled: true,
url: 'rtmps://live-api-s.facebook.com:443/rtmp/YOUR_FB_KEY'
}Common platforms:
- Twitch:
rtmp://live.twitch.tv/app/STREAM_KEY - YouTube:
rtmp://a.rtmp.youtube.com/live2/STREAM_KEY - Facebook:
rtmps://live-api-s.facebook.com:443/rtmp/STREAM_KEY - Kick:
rtmps://fa723fc1b171.global-contribute.live-video.net/live/STREAM_KEY - Rumble:
rtmp://rtmp.rumble.com/live/STREAM_KEY
- Check FFmpeg is installed:
ffmpeg -version - Verify stream keys are correct
- Check logs:
pm2 logs nmsortail -f logs/*.err.log
- Check the platform's logs for specific errors
- Verify your stream key hasn't expired
- Some platforms have bitrate/resolution limits
- Ensure your server has sufficient CPU and bandwidth
- Check network connectivity to each platform
- Disable problematic platforms by setting
enabled: false
- CPU Usage: Uses very little CPU since streams are copied, not re-encoded
- RTMP relays: Copy codecs (near-zero CPU)
- HLS generation: Copy codecs (near-zero CPU, just remuxing/segmenting)
- Bandwidth: Upload bandwidth = (your bitrate) × (number of enabled platforms)
- Latency: Adds minimal latency (~1-2 seconds) to enable multi-platform distribution
- HLS Latency: ~2-12 seconds (depending on segment time and playlist size)
- Some platforms may have infrastructure issues causing extremely slow processing
- If a platform consistently fails, disable it with
enabled: false
Built with Node-Media-Server by illuspas.
MIT License - Feel free to use and modify for your needs.