0%

基于Nginx搭建视频直播服务器

最近几年,网络视频直播处于蓬勃的发展期,各大直播平台的竞争也趋于白热化。在游戏直播领域,就有许多电子竞技的前职业选手,退役后转行游戏主播,收入不菲。当然,网络直播的用处不仅仅是娱乐行业,诸如实时视频监控等应用方向,同样潜力无限。如果没有太高的并发播放需求,完全可以自行搭建直播服务器。借助于Nginx和一些拓展模块,你就可以轻松地运行一个小型的直播平台。
博主在参看了大量教程后,成功地在VPS上搭建了这样的视频直播服务器,而且在昨晚经过测试,能够正常地使用OBS Studio推流,在浏览器上实现HTML5播放。下面附上具体步骤,请将所有yourdomain.com替换为你的域名或者服务器IP。


Nginx环境搭建

首先,需要下载可编译的Nginx源代码,以及必要的拓展库。

如果你对在Linux上安装配置Nginx有所了解,可以直接使用源码安装,不必通过lnmp等工具进行安装。Nginx源码在此处下载,configure的参数后文会讲到,可以参考。

如果你是萌新,请按照👇教程安装搭建lnmp环境!
lnmp环境一键安装脚本

1
2
3
4
5
#下载并安装lnmp环境,将1.4替换为最新版本
wget -c http://soft.vpser.net/lnmp/lnmp1.4.tar.gz
tar -xzvf lnmp1.4.tar.gz
cd lnmp1.4
./install.sh lnmp

请按照脚本的提示选择你要安装的各个组件版本,若不确定,选择默认选项即可。安装完成后,命令行输出:

此时访问服务器地址会出现如下界面:

注意:安装时生成的解压文件夹lnmp1.4先别删除!

安装Nginx的扩展模块

下载nginx-http-flv-module

GitHub项目地址:nginx-http-flv-module,克隆到本地即可:

1
2
3
4
5
#为nginx创建扩展模块目录
mkdir /usr/local/nginx/extend_module
cd /usr/local/nginx/extend_module
#下载扩展包到nginx扩展模块目录下
git clone https://github.com/winshining/nginx-http-flv-module.git

关闭nginx、php-fpm服务

1
2
3
4
#关闭nginx
systemctl stop nginx
#关闭php-fpm
systemctl stop php-fpm

注意:在部分系统下需要使用service代替systemctl命令。

查看nginx配置参数

执行nginx -V会输出配置参数,类似于这样:

复制configure arguments后的所有参数,例如:

1
--prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module --with-ipv6 --with-http_sub_module

这会在后面用到。

重新编译nginx

进入安装时生成的文件夹,并执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cd lnmp1.4/src
#解压nginx源码包,将1.14.0替换为你的版本,下同
tar -xzvf nginx-1.14.0.tar.gz
#进入nginx源码目录
cd nginx-1.14.0
#安装rtmp扩展模块,参数形式是:
#./configure 加上 刚才复制的nginx configure参数 加上 --add-module=nginx-http-flv-module扩展包的目录
#例如:
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-ipv6 --with-http_sub_module --add-module=/usr/local/nginx/extend_module/nginx-http-flv-module
#如果lnmp编译的nginx包含--add-module=openssl等,也需要一并解压,否则会报错找不到文件
#编译
make
#安装
make install
#重启nginx
systemctl start nginx
systemctl start php-fpm

重新启动nginx后,再次执行nginx -V查看安装状态,如果configure arguments后出现nginx-http-flv-module说明安装成功!

服务器开放1935端口

注:若服务器防火墙已关闭,请跳过此步。

1
2
3
4
5
6
7
8
9
#开放1935端口
/sbin/iptables -I INPUT -p tcp --dport 1935 -j ACCEPT
#保存配置
/etc/rc.d/init.d/iptables save
#或 service iptables save
#重启服务
/etc/rc.d/init.d/iptables restart
#查看端口开放状态
/etc/init.d/iptables status

执行iptables -L查看防火墙设置是否生效。

配置HLS或http-flv

nginx.conf进行修改:

1
2
#编辑配置
cd /usr/local/nginx/conf/nginx.conf

需要修改的是httpserver的配置,其内容可参照:

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
server
{
listen 80 default_server;
#listen [::]:80 default_server ipv6only=on;
server_name yourdomain.com;
index index.html index.htm index.php;
root /home/www/; #服务器的根目录
#error_page 404 /404.html;
include enable-php.conf;

#加入hls支持
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
#或 application/x-mpegURL
video/mp2t ts;
}
alias /home/hls/; #视频流文件目录(自己创建,与下方hls_path相同)
expires -1;
add_header Cache-Control no-cache;
}
#加入http-flv支持
location /flv {
flv_live on;
chunked_transfer_encoding on;
}
#server下的其余配置无需改变,此处省略
}
#在文档末尾加入rtmp配置
rtmp {
server {
listen 1935; #监听的端口
chunk_size 4000;
application live { #rtmp推流请求路径
live on;
record off;
#publish_notify on; #推流验证,和下一行需一起使用
#on_publish http://localhost/auth.php; #推流验证,具体可参照后文

hls on;
hls_path /home/hls/test; #视频流hls切片文件目录(自己创建)
hls_fragment 3s; #hls单个切片时长,会影响延迟
hls_playlist_length 32s; #hls总缓存时间,会影响延迟

meta on; #如果http-flv播放时首帧出现问题,可改为off
gop_cache on; #可以减少首帧延迟
}
}
}

参数说明:

  • rtmp 协议名称
  • server 说明内部中是服务器相关配置
  • listen 监听的端口号,rtmp协议的默认端口号是1935
  • application 访问的应用路径是,这里设置为了live
  • live on 开启直播
  • record off 不记录数据

修改完后执行nginx -s reload重载nginx配置

创建目录及文件

根据前面配置文件中的hls_path创建子目录hls,例如/home/hls,确保nginx服务器对其具有读写权限。
在服务器的根目录,例如/home/www下创建test.html文件,进行hls播放:

1
2
3
4
5
6
7
8
9
10
11
12
<!--test.html-->
<html>
<body>
<video autoplay webkit-playsinline controls>
<source src="http://yourdomain.com/hls/test.m3u8" type="application/vnd.apple.mpegurl" />
<p class="warning">Your browser does not support HTML5 video.</p>
</video>
<video controls>
<source src="http://yourdomain.com/hls/test.m3u8" type="application/x-mpegURL">
</video>
</body>
</html>

开始推流

如果要使用OBS Studio等软件推流,地址设置为rtmp://yourdomain.com:1935/live/test
ffmpeg也可以进行推流,用法是:

1
ffmpeg -re -stream_loop -1 -i /path/to/your/video.mp4 -vcodec libx264 -acodec aac -f flv rtmp://yourdomain.com:1935/live/test

版本较老的ffmpeg无法设置-stream_loop -1,可以前往官方网站下载最新版本。

hls播放

用http访问之前创建的test.html,即可观看直播。
如直播没有声音,请参考ffmpeg没有声音
附录:浏览器对hls的支持

如果浏览器并不原生支持hls,可使用第三方插件,例如hls.js;或者使用video.js配合videojs-contrib-hls,这也是不错的解决方案。

http-flv播放

对于http-flv播放,可以使用VLC等软件测试拉流,拉流地址为http://yourdomain.com/flv?app=live&stream=test
如果要实现HTML5播放,可以使用B站开源的flv.js,更多内容可以参照其文档,此处不做更多说明。

推流验证

如果配置文件中开启了publish_notify,那么on_publish项设置的页面将会被用作推流验证。如果验证失败,使这个页面返回404头即可。
比如你设置了on_publish http://localhost/auth.php,那么在auth.php中加入一下内容即可实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
@$name = $_POST['name'];
@$pass = $_POST['pass'];
//在某些情况下,$_POST需要改为$_GET或$_REQUEST,请自行测试
if (empty($name) || empty($pass)) {
header("HTTP/1.0 404 Not Found");
echo "串码流不正确!";
}
else {
if ($pass == "password") {
echo "串码流正确!";
}
else {
header("HTTP/1.0 404 Not Found");
echo "串码流不正确!";
}
}
?>

这时的推流地址也要对应改为rtmp://yourdomain.com:1935/live/test?pass=password


参考文章:
Mac上搭建直播服务器Nginx+rtmp
H5视频直播扫盲
基于Nginx搭建RTMP/HLS视频直播服务器
更多内容可以参考文中提到的模块在GitHub上的文档。

原文使用的是nginx-rtmp-module,其功能被本文介绍的模块完全涵盖,故不再赘述。

本文更新于2018年5月30日:
由于nginx-http-flv-module一直在更新中,其配置文件的参数设置可能略有调整,请以文档为准,本文仅供参考。

本文更新于2018年11月:
在很多文章中都提到了一个RTMP源:rtmp://live.hkstv.hk.lxdns.com/live/hks,不过最近它已经失效了,不能用于拉流。你可以使用前面提到的OBS Studio和ffmpeg进行测试。

🍭支持一根棒棒糖!