We offer customization solutions and support ([email protected]) | Visit us on bitbyte3 for complete VOD solutions with apps.
NixStream
Guides

Live Streaming

RTMP ingest, OBS setup, multistream, recording to VOD

NixStream includes a dedicated live streaming server (bin/media-live) for RTMP ingest and HLS/DASH output. Create streams in the admin panel, push from OBS, and viewers watch through the player or share links.

Live streaming is fine for personal streams and occasional events. Running many concurrent live channels on one small server is not recommended. CPU, packaging, and ops overhead add up quickly.

How it works

RTMP ingest listens on port 1935 (OBS or ffmpeg push). The media API is on 8888 for stream control and health checks.

In Docker, the live server runs as the nixstream_live container. On manual installs, you start bin/media-live directly or via Supervisor.

Create a stream

  1. Open Live in the admin panel
  2. Click Create stream and give it a title
  3. Optionally enable Save recording as VOD (off by default)
  4. Copy the stream key and RTMP URL
  5. The RTMP URL format is: rtmp://{MEDIA_SERVER_INGEST_IP}:1935/live/{stream_key}

MEDIA_SERVER_INGEST_IP is auto-detected by install.sh in Docker. On manual installs, set it to your server's public IP.

OBS setup

  1. Open OBS and go to Settings > Stream
  2. Set service to Custom
  3. Server: rtmp://your-server-ip:1935/live
  4. Stream key: paste the key from the admin panel
  5. Click Start Streaming

Make sure port 1935 is open in your firewall and any cloud security group. RTMP uses TCP.

  • Output: x264 or hardware encoder (NVENC if available)
  • Keyframe interval: 2 seconds (matches typical HLS segment length)
  • Bitrate: 2500-6000 kbps for 1080p depending on your audience bandwidth
  • Use H.264 + AAC when you plan to restream (destinations must accept the source codecs)

Multistream (restream)

Restream forwards the live packets to other platforms. It does not transcode per destination.

  1. Open Settings > Live streaming (Multistreaming)
  2. Enable a platform and set its RTMP ingest URL and stream key (YouTube, Twitch, etc.)
  3. Start your live stream from OBS
  4. Open the stream in the panel and toggle destinations under Multistreaming (only available while the stream is active)

Notes:

  • Destinations must accept the codec OBS is sending (H.264 + AAC is safest)
  • Viewer ABR (HLS ladder) is separate from restream; enabling transcoding affects panel playback, not the RTMP push
  • Destinations are not auto-started when you go live. Toggle them while active.
  • Instagram/TikTok often need special ingest; plain RTMP may fail even when NixStream pushes correctly

Recording > VOD

Recording is optional. Enable Save recording as VOD on the stream when you create or edit it. When enabled, media-live writes an FLV and archives it under storage/app/public/live_archive/ when the stream ends.

Import archived recordings into the normal VOD encoding queue:

docker compose exec app php artisan live:import-recordings

The scheduler runs this every five minutes. Imports use the tenant default VOD encoding profile and default storage provider (same as manual uploads). Finished recordings show up in Media > VOD > Live Recordings under your library root.

To link recordings that were encoded before this folder existed:

docker compose exec app php artisan live:import-recordings --backfill-orphans

After VOD encoding succeeds, the FLV and live session directories are removed so disk usage stays bounded.

Live playback security

Live HLS segments on disk are not AES-128 encrypted. That's expected. Live security is enforced by signed Edge URLs:

  • Panel and embed players only receive Edge URLs (EDGE_BASE_URL), not direct paths to storage/app/media/live/.
  • Each playback session uses an opaque URL prefix (p/…); stream keys never appear in manifests or segment URLs.
  • Sessions expire after EDGE_SESSION_TTL_LIVE (default 6 hours). Expired URLs return 403.

VOD uses segment AES-128 plus signed URLs. Live uses signed URLs only. See Encoding, Edge delivery.

Optional Require user or share-link auth (Settings > Integrations > Edge) binds live sessions to a user or share link for instant revocation. See Security, Playback authorization.

Stale live_media sessions and old archives are purged hourly:

docker compose exec app php artisan live:cleanup
docker compose exec app php artisan live:cleanup --dry-run

Local E2E (not in the repository)

Operator live/encoding smoke tests (live:test, encoding:test-profiles) are local-only scripts and are gitignored. They are not required to run NixStream.

Firewall rules

Open these ports on your server:

sudo ufw allow 1935/tcp    # RTMP ingest
sudo ufw allow 8888/tcp    # Media API

Health check

Confirm the live server is responding:

curl http://localhost:8888/health

Check logs:

docker compose logs nixstream-live

Client API

Monitor streams programmatically:

  • GET /api/client/v1/live-streams lists all streams (paginated)
  • GET /api/client/v1/live-streams/active returns currently broadcasting streams
  • GET /api/client/v1/live-streams/{id} returns a single stream with manifest URLs

Active streams include a manifest object with HLS playback URLs.

Environment variables

VariablePurpose
MEDIA_SERVER_HOSTInternal API URL (e.g. http://nixstream-live:8888)
MEDIA_SERVER_API_KEYAuth key for media server API
MEDIA_SERVER_INGEST_IPPublic IP or hostname for RTMP
MEDIA_JWT_SECRETJWT for stream tokens
MEDIA_LIVE_API_PORTDefault 8888
MEDIA_LIVE_RTMP_PORTDefault 1935

Troubleshooting live streams

OBS can't connect

  • Verify port 1935 is open externally
  • Confirm MEDIA_SERVER_INGEST_IP is your public IP, not 127.0.0.1
  • Check that nixstream_live container is running

Stream shows inactive in admin panel

  • The media server may be down. Run curl http://localhost:8888/health
  • Verify MEDIA_SERVER_API_KEY matches between app and live server

Playback stutters

  • Lower your OBS output bitrate
  • Check server CPU during the stream
  • Confirm adequate bandwidth on the ingest path

Restream fails

  • Confirm the stream is active before toggling destinations
  • Check platform RTMP URL and stream key in Settings > Live streaming
  • Use H.264 + AAC from OBS

See the full troubleshooting guide for more scenarios.

On this page