[转]使用Nginx 和 RTMP 模块搭建视频直播系统

原文: Setting Up Adaptive Streaming with Nginx by Licson

最近我在为一个组织搭建视频直播系统。对于视频直播来说我是新手,经过一番调研,最终还是觉得Nginx + RTMP module是一个好的选择。
搭建这个系统还是很困难的。经过了好几天的测试和摸索,我得到了一种比较好的配置,值得给大家分享。

Recently, I’m working out a system to smoothly stream live events for an organization. That is pretty new to me and, after a bunch of research, found that Nginx with the RTMP module seems to be a good choice. There are many difficulties when setting all this up and after several days of testing, I found a good setting that is worth a post.

Setup Nginx and RTMP module

First, let’s get Nginx set up. In order to use the RTMP module, we need to compile that as an Nginx module. It would look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apt-get install git gcc make libaio1 libpcre3-dev openssl libssl-dev ffmpeg -y
# Installing the same thing in RHEL/CentOS
yum install git gcc make libaio libaio-devel openssl libssl-devel pcre-devel ffmpeg -y
# Download nginx and nginx-rtmp-module
wget http://nginx.org/download/nginx-1.9.4.tar.gz
git clone https://github.com/arut/nginx-rtmp-module.git
# Compile nginx with nginx-rtmp and libaio
tar zxvf nginx-1.9.4.tar.gz
./configure --prefix=/usr/local/nginx --with-file-aio --add-module=/path/to/nginx-rtmp/
make
make install
# Link nginx
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
nginx # Start Nginx
nginx -s stop # Stop Nginx

After all things are done, check whether nginx is compiled properly.

If you can see that Nginx RTMP is included, you can go to the next step. Before we proceed to configuring Nginx for live streaming, we should confirm what kind of resolution we should provide for live streams and how much hardware power you have.

Prerequisites

For converting live streams into several streams for adaptive streaming, you need to make sure your server have enough CPU for such workload. Otherwise, the live stream will suffer from continuous delays and/or server becomes unresponsive. I have spawn some EC2 c3.large and c3.xlarge instances, test with them and I found out their optimized CPU can handle such workload with ease. Something that also worth mention is about the I/O limits of the disks. If possible, store the HLS fragments generated to an high-speed SSD helps maintain smooth streaming experiences.

CPU Usage when using an EC2 c3.xlarge instance

Then, you also need to think about what kind of resolutions you will be offering for adaptive streaming. Generally about 4-5 variants are good enough to provide great loading speeds for different network speeds and devices. Here’s my recommended list of variants used for live streaming:

  1. 240p Low Definition stream at 288kbps
  2. 480p Standard Definition stream at 448kbps
  3. 540p Standard Definition stream at 1152kbps
  4. 720p High Definition stream at 2048kbps
  5. Source resolution, source bitrate

Configuring nginx for live streaming

Here is my own nginx.conf with comments that you can have references on.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
worker_processes auto;
events {
# Allows up to 1024 connections, can be adjusted
worker_connections 1024;
}
# RTMP configuration
rtmp {
server {
listen 1935; # Listen on standard RTMP port
chunk_size 4000;
# This application is to accept incoming stream
application live {
live on; # Allows live input
# Once receive stream, transcode for adaptive streaming
# This single ffmpeg command takes the input and transforms
# the source into 4 different streams with different bitrate
# and quality. P.S. The scaling done here respects the aspect
# ratio of the input.
exec ffmpeg -i rtmp://localhost/$app/$name -async 1 -vsync -1
-c:v libx264 -c:a libvo_aacenc -b:v 256k -b:a 32k -vf "scale=480:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://localhost/show/$name_low
-c:v libx264 -c:a libvo_aacenc -b:v 768k -b:a 96k -vf "scale=720:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://localhost/show/$name_mid
-c:v libx264 -c:a libvo_aacenc -b:v 1024k -b:a 128k -vf "scale=960:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://localhost/show/$name_high
-c:v libx264 -c:a libvo_aacenc -b:v 1920k -b:a 128k -vf "scale=1280:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://localhost/show/$name_hd720
-c copy -f flv rtmp://localhost/show/$name_src;
}
# This application is for splitting the stream into HLS fragments
application show {
live on; # Allows live input from above
hls on; # Enable HTTP Live Streaming
# Pointing this to an SSD is better as this involves lots of IO
hls_path /mnt/hls/;
# Instruct clients to adjust resolution according to bandwidth
hls_variant _low BANDWIDTH=288000; # Low bitrate, sub-SD resolution
hls_variant _mid BANDWIDTH=448000; # Medium bitrate, SD resolution
hls_variant _high BANDWIDTH=1152000; # High bitrate, higher-than-SD resolution
hls_variant _hd720 BANDWIDTH=2048000; # High bitrate, HD 720p resolution
hls_variant _src BANDWIDTH=4096000; # Source bitrate, source resolution
}
}
}
http {
# See http://licson.net/post/optimizing-nginx-for-large-file-delivery/ for more detail
# This optimizes the server for HLS fragment delivery
sendfile off;
tcp_nopush on;
aio on;
directio 512;
# HTTP server required to serve the player and HLS fragments
server {
listen 80;
location / {
root /path/to/web_player/;
}
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
}
root /mnt/;
add_header Cache-Control no-cache; # Prevent caching of HLS fragments
add_header Access-Control-Allow-Origin *; # Allow web player to access our playlist
}
}
}

Then, configure your live encoder to use these settings to stream into the server:

  • RTMP Endpoint: rtmp://yourserver/live/
  • RTMP Stream Name: [Whatever name you like]

Finally, configure your player for live playback. The HLS URL would look like this:
http://yourserver/hls/[The stream name above].m3u8

If you can adjust the encoder, the following settings can help to gain better experiences.

  • Full HD Resolution (1920×1080) is recommended
  • H.264 Main profile, with target bitrate of 4000Kbps, maximum 6000Kbps
  • 25fps, 2 second keyframe interval
  • AAC audio at 128Kbps, 44.1kHz sample rate

And that’s all! I hope you can enjoy doing live events with these techniques.