Create an simple Live Webcast with Nginx RTMP

Introduction

This blog demonstrates how to build a live streaming server using Nginx with RTMP module and Docker. Here are some things we should know:

  • Accept live video streams from sources like OBS or ffmpeg via RTMP protocol
  • Convert RTMP streams to HLS (HTTP Live Streaming) format for browser playback
  • Set up a complete streaming infrastructure using Docker Compose
  • Test your setup with a sample video player

By the end, you'll have a working live streaming server that can receive streams on port 1935 and deliver them to viewers via HTTP on port 8181.

Concept

This guide shows a minimal, practical setup to accept an RTMP stream (from OBS or ffmpeg), produce HLS segments with Nginx RTMP, and serve them over HTTP for browser playback.

In the final setup used for this post:

  • RTMP ingest endpoint: rtmp://localhost/live/stream-test
  • HLS playback URL: http://localhost:8181/hls/stream-test.m3u8

How it flows

Project layout

Files in this repo used for the demo:

Docker/
    rtmp.Dockerfile
docker-compose.yml
nginx.conf
player.html
videos/

All commands below are meant to be run from the repository root.

Docker Compose services (summary)

This example uses three services:

  • nginx-rtmp: a Debian-based container with nginx + RTMP module to accept RTMP and produce HLS.
  • publisher: an ffmpeg container that loops a sample video and pushes it to the RTMP ingest (useful for testing).
  • viewer: a simple static nginx used to host player.html so you can open a browser UI.

1) nginx-rtmp service

Example docker-compose service snippet:

nginx-rtmp:
  build:
    context: .
    dockerfile: Docker/rtmp.Dockerfile
  ports:
    - "1935:1935"   # RTMP
    - "8181:80"     # HLS / HTTP
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
    - /tmp/hls:/tmp/hls
    - ./videos:/var/recordings:rw

Dockerfile (Docker/rtmp.Dockerfile):

FROM debian:bookworm-slim
RUN apt-get update && \
    apt-get install -y nginx libnginx-mod-rtmp && \
    apt-get clean && rm -rf /var/lib/apt/lists/*
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 1935 80
CMD ["nginx", "-g", "daemon off;"]

Notes:

  • We copy nginx.conf directly so the RTMP module and HLS paths are configured as shown below.
  • Mounting /tmp/hls makes HLS segments visible on the host for debugging.

2) nginx configuration

Save this as nginx.conf (the repo already contains the file). Key points:

  • load the RTMP module
  • set hls on and hls_path inside the RTMP application
  • expose the HLS folder via the HTTP server with correct MIME types and CORS headers

Example nginx.conf (trimmed for clarity):

worker_processes auto;
load_module modules/ngx_rtmp_module.so;

events { worker_connections 1024; }

http {
  include mime.types;
  default_type application/octet-stream;

  server {
    listen 80;
    server_name localhost;

    location / {
      root /var/www/html;
      index index.html;
    }

    location /hls {
      types {
        application/vnd.apple.mpegurl m3u8;
        video/mp2t ts;
      }
      root /tmp;
      add_header Cache-Control no-cache;
      add_header Access-Control-Allow-Origin *;
    }
  }
}

rtmp {
  server {
    listen 1935;
    chunk_size 4096;

    application live {
      live on;
      hls on;
      hls_path /tmp/hls;
      hls_fragment 3s;
      hls_playlist_length 60s;

      # optional recording settings
      record all;
      record_path /var/recordings;
      record_unique on;
      record_suffix .flv;
    }
  }
}

3) publisher (test source)

This service uses the jrottenberg/ffmpeg image to loop a local video and push to the RTMP server for testing.

publisher:
  image: jrottenberg/ffmpeg:4.1-alpine
  command: ["-re", "-stream_loop", "-1", "-i", "/videos/input.mp4", "-c", "copy", "-f", "flv", "rtmp://nginx-rtmp:1935/live/stream-test"]
  depends_on:
    - nginx-rtmp
  volumes:
    - ./videos:/videos:ro

If you prefer to publish from your machine or OBS, use rtmp://localhost:1935/live/stream-test as the target.

4) viewer (static player)

Host player.html with a plain nginx container so you can open http://localhost:8081 in a browser.

viewer:
  image: nginx:latest
  ports:
    - "8081:80"
  volumes:
    - ./player.html:/usr/share/nginx/html/index.html:ro
  depends_on:
    - nginx-rtmp
    - publisher

Quickstart

  1. Build and start the services:

    docker compose up -d --build
    
  2. If you use the included publisher service, it will continuously push /videos/input.mp4 to the RTMP server.

  3. Open the viewer UI and point it at the HLS playlist:

    http://localhost:8081/?url=http://localhost:8181/hls/stream-test.m3u8

    Or open the HLS playlist directly in a player (VLC, mpv):

    http://localhost:8181/hls/stream-test.m3u8

    Your live streaming setup!

Result