视频直播系列(一):nginx服务器搭建

本文讲解了nginx流媒体服务器的搭建,nginx稳定,高效低消耗

nginx介绍

Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性:

作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型.

作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。

作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。

Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在 不间断服务的情况下进行软件版本的升级。

以上内容来源于nginx中文网:nginx中文站

直播的架构设计图示

nginx搭建步骤

  1. 安装编译依赖

    1
    sudo apt-get install libpcre3-dev libpcre3 libssl-dev build-essential
  2. 创建nginx工作目录,切换至工作目录

    1
    2
    mkdir -p /usr/temp/nginx
    cd /usr/temp/nginx
  3. 使用wget下载nginx和nginx-rtmp源码
    Nginx官网提供了三个类型的版本
    Mainline version:MainlineNginx目前主力在做的版本,可以说是开发版
    Stable version:最新稳定版,生产环境上建议使用的版本
    Legacy versions:遗留的老版本的稳定版
    具体可以在官网查看:nginx官网
    我这里选择最新的稳定版1.13.12

    1
    2
    wget http://nginx.org/download/nginx-1.13.12.tar.gz
    wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
  4. 解压nginx和nginx-rtmp安装包

    1
    2
    tar -zxvf nginx-1.13.12.tar.gz
    unzip master.zip

如果提示没有unzip,那么安装unzip

1
sudo apt-get install unzip

  1. 进入到nginx解压后的目录

    1
    cd nginx-1.13.12
  2. 添加nginx-rtmp模板编译到nginx

    1
    ./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master

--add-module后面是指定模块的路径
configure后面的参数可以自定义,常用自定义路劲如下

1
2
3
--sbin-path=/usr/local/nginx/nginx \ #指定执行文件安装目录
--conf-path=/usr/local/nginx/nginx.conf \ #指定配置文件目录
--pid-path=/usr/local/nginx/nginx.pid \ #指定pid位置

比如同时要指定以上三个目录,同时添加模块,那么使用以下命令

1
2
3
4
5
./configure --sbin-path=/usr/local/nginx/nginx \
--conf-path=/usr/local/nginx/nginx.conf \
--pid-path=/usr/local/nginx/nginx.pid \
--with-http_ssl_module \
--add-module=../nginx-rtmp-module-master

我这是使用默认目录,其默认位置是/usr/local/nginx
可以使用whereis nginx查看

  1. 编译安装
    1
    2
    make
    sudo make install

还可以设置软连接

1
sudo ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx

那么就可以直接使用nginx启动了

  1. 添加服务启动
    那么需要手动添加启动服务
    1
    vim /etc/init.d/nginx

然后添加如下启动配置
配置见附录配置
修改执行权限,注册服务

1
2
3
chmod 755 /etc/init.d/nginx
cd /etc/init.d/
sudo update-rc.d nginx defaults

  1. 启动和停止nginx服务,生成配置文件(之后要对其进行修改)

    1
    2
    sudo service nginx start
    sudo service nginx stop
  2. 确保80端口没被其他程序占用,查看端口占用情况

    1
    netstat -ano|grep 80

如果端口被占用,修改配置文件,使用其他端口

1
2
/usr/local/nginx/conf
vim nginx.conf

可以看见以下参数

1
2
3
server {
listen 80;
server_name localhost;

将其监听端口改为其他数值
端口号范围为0~65535,在更改监听端口的时候,尽量不要再1024之前,尽量靠后
我这里设置为25560
然后保存,开启设置的端口

1
sudo ufw allow 25560

查看端口是否开启,如果存在设置的端口,那么说明开启成功

1
sudo ufw status

  1. 开启nginx查看是否可以访问
    1
    sudo service nginx start

输入IP地址和端口号,查看是否可以访问
出现如下图表示启动成功

  1. 安装FFmpeg
    上传FFmpeg,解压,检查配置
    1
    ./configure --disable-yasm

编译

1
make

安装

1
make install

安装完成以后其默认位置为:/usr/local/bin/ffmpeg

  1. 配置nginx-rtmp服务器
    打开nginx配置文件
    1
    /usr/local/nginx/conf/nginx.conf

末尾添加rtmp配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
rtmp {
server {
listen 2018;
chunk_size 4096;

application live {
live on;
record off;
exec ffmpeg -i rtmp://localhost/live/$name -threads 1 -c:v libx264 -profile:v baseline -b:v 350K -s 640x360 -f flv -c:a aac -ac 1 -strict -2 -b:a 56k rtmp://localhost/live360p/$name;
}
application live360p {
live on;
record off;
}
}
}

配置说明:x264视频编码,acc音频编码,flv视频格式

  1. 保存配置文件,重新启动nginx服务

    1
    sudo service nginx restart
  2. 如果使用了防火墙,允许端口 tcp 2018

    1
    2
    3
    4
    iptables -I INPUT -p tcp --dport 2018 -j ACCEPT
    iptables-save
    sudo netfilter-persistent save
    sudo netfilter-persistent reload

如果是阿里云,也可以在控制面板设定

  1. 网页端也可同时接收到视频流,这里放一个flash播放器即可
    将播放器复制到目录:/usr/local/nginx/html/
    然后在src一行修改播放地址:IP:port
    播放器下载地址==>密码:ydeq

至此,服务端搭建完成

配置

配置

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
#! /bin/sh
### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: nginx init.d dash script for Ubuntu or other *nix.
# Description: nginx init.d dash script for Ubuntu or other *nix.
### END INIT INFO
#------------------------------------------------------------------------------
# nginx - this Debian Almquist shell (dash) script, starts and stops the nginx
# daemon for Ubuntu and other *nix releases.
#
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server. This \
# script will manage the initiation of the \
# server and it's process state.
#
# processname: nginx
# config: /usr/local/nginx/conf/nginx.conf
# pidfile: /usr/local/nginx/logs/nginx.pid
# Provides: nginx
#
# Author: Jason Giedymin
# <jason.giedymin AT gmail.com>.
#
# Version: 3.9.0 12-MAY-2015 jason.giedymin AT gmail.com
# Notes: nginx init.d dash script for Ubuntu.
# Tested with: Ubuntu 14.10, nginx-1.7.9
#
# This script's project home is:
# http://github.com/JasonGiedymin/nginx-init-ubuntu
#
#------------------------------------------------------------------------------
# MIT X11 License
#------------------------------------------------------------------------------
#
# Copyright (c) 2008-2013 Jason Giedymin, http://jasongiedymin.com
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Functions
#------------------------------------------------------------------------------
LSB_FUNC=/lib/lsb/init-functions

# Test that init functions exists
test -r $LSB_FUNC || {
echo "$0: Cannot find $LSB_FUNC! Script exiting." 1>&2
exit 5
}

. $LSB_FUNC

#------------------------------------------------------------------------------
# Consts
#------------------------------------------------------------------------------
# Include nginx defaults if available
if [ -f /etc/default/nginx ]; then
. /etc/default/nginx
fi

# Minimize path
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

PS=${PS:-"nginx"} # process name
DESCRIPTION=${DESCRIPTION:-"Nginx Server..."} # process description
NGINXPATH=${NGINXPATH:-/usr/local/nginx} # root path where installed
DAEMON=${DAEMON:-$NGINXPATH/sbin/nginx} # path to daemon binary
NGINX_CONF_FILE=${NGINX_CONF_FILE:-$NGINXPATH/conf/nginx.conf} # config file path

PIDNAME=${PIDNAME:-"nginx"} # lets you do $PS-slave
PIDFILE=${PIDFILE:-$PIDNAME.pid} # pid file
PIDSPATH=${PIDSPATH:-$NGINXPATH/logs} # default pid location, you should change it
RUNAS=${RUNAS:-root} # user to run as

SCRIPT_OK=0 # ala error codes
SCRIPT_ERROR=1 # ala error codes
TRUE=1 # boolean
FALSE=0 # boolean

#------------------------------------------------------------------------------
# Simple Tests
#------------------------------------------------------------------------------

# Test if nginx is a file and executable
test -x $DAEMON || {
echo "$0: You don't have permissions to execute nginx." 1>&2
exit 4
}

# You can also set your conditions like so:
# set exit condition
# set -e

#------------------------------------------------------------------------------
# Functions
#------------------------------------------------------------------------------

setFilePerms(){
if [ -f $PIDSPATH/$PIDFILE ]; then
chmod 400 $PIDSPATH/$PIDFILE
fi
}

configtest() {
$DAEMON -t -c $NGINX_CONF_FILE
}

getPSCount() {
return `pgrep -f $PS | wc -l`
}

isRunning() {
if [ $1 ]; then
pidof_daemon $1
PID=$?

if [ $PID -gt 0 ]; then
return 1
else
return 0
fi
else
pidof_daemon
PID=$?

if [ $PID -gt 0 ]; then
return 1
else
return 0
fi
fi
}

#courtesy of php-fpm
wait_for_pid () {
try=0

while test $try -lt 35 ; do
case "$1" in
'created')
if [ -f "$2" ]; then
try=''
break
fi
;;

'removed')
if [ ! -f "$2" ]; then
try=''
break
fi
;;
esac

try=`expr $try + 1`
sleep 1
done
}

status(){
isRunning
isAlive=$?

if [ "${isAlive}" -eq $TRUE ]; then
log_warning_msg "$DESCRIPTION found running with processes: `pidof $PS`"
rc=0
else
log_warning_msg "$DESCRIPTION is NOT running."
rc=3
fi

return
}

removePIDFile(){
if [ $1 ]; then
if [ -f $1 ]; then
rm -f $1
fi
else
#Do default removal
if [ -f $PIDSPATH/$PIDFILE ]; then
rm -f $PIDSPATH/$PIDFILE
fi
fi
}

start() {
log_daemon_msg "Starting $DESCRIPTION"

isRunning
isAlive=$?

if [ "${isAlive}" -eq $TRUE ]; then
log_end_msg $SCRIPT_ERROR
rc=0
else
start-stop-daemon --start --quiet --chuid \
$RUNAS --pidfile $PIDSPATH/$PIDFILE --exec $DAEMON \
-- -c $NGINX_CONF_FILE
status=$?
setFilePerms

if [ "${status}" -eq 0 ]; then
log_end_msg $SCRIPT_OK
rc=0
else
log_end_msg $SCRIPT_ERROR
rc=7
fi
fi

return
}

stop() {
log_daemon_msg "Stopping $DESCRIPTION"

isRunning
isAlive=$?

if [ "${isAlive}" -eq $TRUE ]; then
start-stop-daemon --stop --quiet --pidfile $PIDSPATH/$PIDFILE

wait_for_pid 'removed' $PIDSPATH/$PIDFILE

if [ -n "$try" ]; then
log_end_msg $SCRIPT_ERROR
rc=0 # lsb states 1, but under status it is 2 (which is more prescriptive). Deferring to standard.
else
removePIDFile
log_end_msg $SCRIPT_OK
rc=0
fi
else
log_end_msg $SCRIPT_ERROR
rc=7
fi

return
}

reload() {
configtest || return $?

log_daemon_msg "Reloading (via HUP) $DESCRIPTION"

isRunning

if [ $? -eq $TRUE ]; then
kill -HUP `cat $PIDSPATH/$PIDFILE`
log_end_msg $SCRIPT_OK
rc=0
else
log_end_msg $SCRIPT_ERROR
rc=7
fi

return
}

quietupgrade() {
log_daemon_msg "Peforming Quiet Upgrade $DESCRIPTION"

isRunning
isAlive=$?

if [ "${isAlive}" -eq $TRUE ]; then
kill -USR2 `cat $PIDSPATH/$PIDFILE`
kill -WINCH `cat $PIDSPATH/$PIDFILE.oldbin`

isRunning
isAlive=$?

if [ "${isAlive}" -eq $TRUE ]; then
kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin`
wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin
removePIDFile $PIDSPATH/$PIDFILE.oldbin

log_end_msg $SCRIPT_OK
rc=0
else
log_end_msg $SCRIPT_ERROR

log_daemon_msg "ERROR! Reverting back to original $DESCRIPTION"

kill -HUP `cat $PIDSPATH/$PIDFILE`
kill -TERM `cat $PIDSPATH/$PIDFILE.oldbin`
kill -QUIT `cat $PIDSPATH/$PIDFILE.oldbin`

wait_for_pid 'removed' $PIDSPATH/$PIDFILE.oldbin
removePIDFile $PIDSPATH/$PIDFILE.oldbin

log_end_msg $SCRIPT_OK
rc=0
fi
else
log_end_msg $SCRIPT_ERROR
rc=7
fi

return
}

terminate() {
log_daemon_msg "Force terminating (via KILL) $DESCRIPTION"

PIDS=`pidof $PS` || true

[ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE`

for i in $PIDS; do
if [ "$i" = "$PIDS2" ]; then
kill $i
wait_for_pid 'removed' $PIDSPATH/$PIDFILE
removePIDFile
fi
done

log_end_msg $SCRIPT_OK
rc=0
}

destroy() {
log_daemon_msg "Force terminating and may include self (via KILLALL) $DESCRIPTION"
killall $PS -q >> /dev/null 2>&1
log_end_msg $SCRIPT_OK
rc=0
}

pidof_daemon() {
PIDS=`pidof $PS` || true

[ -e $PIDSPATH/$PIDFILE ] && PIDS2=`cat $PIDSPATH/$PIDFILE`

for i in $PIDS; do
if [ "$i" = "$PIDS2" ]; then
return 1
fi
done

return 0
}

action="$1"
case "$1" in
start)
start
;;
stop)
stop
;;
restart|force-reload)
stop
# if [ $rc -ne 0 ]; then
# script_exit
# fi
sleep 1
start
;;
reload)
$1
;;
status)
status
;;
configtest)
$1
;;
quietupgrade)
$1
;;
terminate)
$1
;;
destroy)
$1
;;
*)
FULLPATH=/etc/init.d/$PS
echo "Usage: $FULLPATH {start|stop|restart|force-reload|reload|status|configtest|quietupgrade|terminate|destroy}"
echo " The 'destroy' command should only be used as a last resort."
exit 3
;;
esac

exit $rc

Donate comment here