Live Streaming Video on the Web
ffmpeg and nginx can be used to live stream video from any RTSP source like a CCTV camera on the web using DASH. The video can be viewed in any modern web browser.
Notes
- Video source must be
h264encoded for max compatibility. Set the camera to encode h264 at source so transcoding can be avoided later.
Step 1: Setup nginx (native)
apt install -y nginx libnginx-mod-rtmp# Nginx config for streaming RTSP/RTMP video feeds to DASH
# Filename: /etc/nginx/nginx.conf
# Comment the below if running natively via systemd
daemon off;
user www-data;
pid /run/nginx.pid;
load_module modules/ngx_rtmp_module.so;
events {}
rtmp {
server {
listen 1935; # default RTMP port
chunk_size 4096; # 4k chunk size
allow publish all; # Accept streams from anywhere
application live {
live on;
record off; # Don't save streams to disk
dash on;
dash_path /var/www/html/dash;
}
}
}
http {
server {
listen 80 default_server;
root /var/www/html;
server_name _;
location / {
try_files $uri $uri/ =404;
add_header Access-Control-Allow-Origin *;
}
}
# Mime types for all the files served
types {
text/html html;
application/javascript js;
application/dash+xml mpd;
audio/x-m4a m4a;
video/x-m4v m4v;
}
}Step 1.1 Custom Docker Container
Official nginx docker container does not include the RTMP module and a custom nginx container needs to be built from Alpine and nginx and nginx-mod-rtmp package.
Build custom docker container using alpine and below Dockerfile.
# Dockerfile for custom nginx image including RTMP module
FROM alpine:3.19
WORKDIR /root
RUN apk add --no-cache nginx nginx-mod-rtmp
EXPOSE 80/tcp
CMD ["nginx", "-g", "daemon off;"]Step 1.2 Docker Compose
# docker compose to run nginx with rtmp streaming
# Filename: docker-compose.yaml
name: livevideo-example-com
services:
livevideo:
build: .
container_name: livevideo.example.com
restart: always
volumes:
- ./www:/var/www/html:ro
labels:
- com.centurylinklabs.watchtower.enable=true
- traefik.enable=true
- traefik.http.routers.livevideo.rule=Host(`livevideo.example.com`)
- traefik.http.routers.livevideo.tls=true
- traefik.http.routers.livevideo.tls.certresolver=lets-encryptStep 2: Setup ffmpeg
ffmpeg used for pulling a camera feed over rtsp and forwarding to nginx with the correct streaming container format.
Input From File for Testing
ffmpeg -re -i test.mp4 -c copy -f flv rtmp://nginx-ip/live/streamNotes
-re: play back file in real time by reading input at native frame rate, eg 1 hour video will play back in 1 hour.-i test.mp4: sample input file for streaming to nginx.-c copy: don't transcode the audio/video stream, just copy to output.-f flv: suitable streaming format.rtmp://nginx-ip/live/stream: nginx rtmp server location for sending the output stream.
Input From CCTV Camera
HikVision CCTV cameras provide RTSP stream in the default tcp:554 port and no path is required. Username and password are the same as what is required to access the camera web portal. Ensure the camera is set for h264 encoding.
# nginx IP: a.a.a.a
# camera IP: c.c.c.c
ffmpeg -re -i rtsp://username:password@c.c.c.c -c copy -f flv rtmp://a.a.a.a/live/streamNotes
- If ffmpeg is segfaulting, use the ubuntu supplied ffmpeg binary (
apt install ffmpeg) and not the static builds from ffmpeg.org.
Step 3: Dash.js
The stream.mpd can be viewed in the browser using dash.js and the associated HTML player.
Place the following two flies into /var/www/html web root folder and open nginx base URL (eg http://nginx-ip) in your browser.
3.1 dash.all.min.js
wget http://cdn.dashjs.org/latest/dash.all.min.js3.2. index.html
<html>
<head>
<title>Livestream</title>
<style>
video {
width: 640px;
height: 360px;
}
</style>
</head>
<body>
<div>
<video id="videoPlayer" controls></video>
</div>
<script src="dash.all.min.js"></script>
<script>
(function(){
var url = "/dash/stream.mpd";
var player = dashjs.MediaPlayer().create();
player.initialize(document.querySelector("#videoPlayer"), url, true);
})();
</script>
</body>
</html>