使用nginx搭建rtmp+http_flv服务器实现直播推流

使用nginx搭建rtmp+http_flv服务器实现直播推流

1.概述

项目中要实现安卓手机上的直播功能,因为涉及网络安全,不允许使用第三方的直播推流服务器,所以需要自建一台直播推流的视频服务器,将搭建过程记录如下。

2.服务器配置

现场服务器均为Windows Server版本,但nginx安装第三方模块需要在Linux系统下进行,在Windows下的安装非常麻烦,而且稳定性不好,所以考虑在Windows服务器上安装CentOS的虚拟机,在虚拟机上安装nginx,然后使用端口映射到主机端口上实现相关功能

2.1.安装vmware虚拟机软件

在服务器上安装了VMware Workstation 12 Pro

2.2.安装CentOS7操作系统

使用CentOS-7-x86_64-DVD-1908.iso安装操作系统,安装时虚拟机网络使用NAT地址转换
安装后配置开机启用网络

cd /etc/sysconfig/network-scripts/
ls
#此处网卡配置文件名的数字可能为随机数字
#将其中的ONBOOT=yes改为ONBOOT=no 开机启动网络
#如需配置为静态地址,将BOOTPROTO=dhcp修改为static或none,然后配置IPADDR,PREFIX,GATEWAY,DNS1
sudo vi ifcfg-ens33
#重启网络服务
service network restart
#关闭防火墙
systemctl stop firewalld.service
#查看防火墙状态
systemctl status firewalld.service
#禁止防火墙开机启动
systemctl disable firewalld.service

ifcfg-ens33文件的核心内容

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=bb7e97e1-a6d4-44e6-80ee-212d82c9ca86
DEVICE=ens33
ONBOOT=yes
IPADDR=172.18.4.6
PREFIX=24
GATEWAY=172.18.4.2
DNS1=172.18.4.2

2.3.设置虚拟机为共享虚拟机

虚拟机必须设置为共享虚拟机才可以开机自启动,在左侧虚拟机列表中,右键虚拟机,然后选择“管理-共享”菜单,按提示一步一步设置为共享虚拟机,设置后即可开机自启动。

2.4.配置端口映射

在菜单:“编辑-虚拟网络编辑器”中打开虚拟网络编辑器,选择类型为“NAT模式”的行,在下面找到【NAT设置】按钮,点击后打开NAT设置窗口,点击添加即可添加端口映射

3.安装Nginx服务器软件

3.1.准备工作

打开命令行,安装编译相关软件

sudo yum -y install unzip gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel

如果需要在离线机器上安装,则可以预先在能上网的机器上下载安装包,然后在离线机器上进行离线安装

#下载安装包
yumdownloader --resolve kernel-headers glibc-headers libcom_err libselinux libsepol-devel cpp glibc-devel libgomp glibc-common keyutils-libs-devel libcom_err-devel libselinux-devel libverto-devel  krb5-libs   libkadm5 gcc libstdc++ libstdc++-devel krb5-devel  libcrypto.so.10 libssl.so.10 openssl-libs libc.so.6 libgcc_s.so.1 libm.so.6 libpthread.so.0 libstdc++.so.6 unzip gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
#压缩为tar包
tar cf rtmp-env.tar *.rpm
#解压tar包到指定目录
tar xf rtmp-env.tar -C ./env/
#离线安装rpm包
sudo rpm -ivh --replacefiles --replacepkgs *.rpm

3.2.下载Nginx源文件

从github下载nginx的源代码

https://github.com/nginx/nginx
#解压tar包
tar xf nginx-1.23.1.tar

注:打不开网站的话,安装【Steam++】软件进行网络加速

下载后,拷贝nginx源文件到/home/nginx下并解压,
解压后目录为/home/nginx/nginx-1.23.1

3.3.下载nginx-http-flv-module模块

从github下载nginx-http-flv-module的源代码

https://github.com/winshining/nginx-http-flv-module

拷贝nginx-http-flv-module源文件并解压到/usr/local/nginx下,nginx目录不存在时则创建之
解压后目录为/usr/local/nginx/nginx-http-flv-module

#解压命令
tar -zxvf nginx-1.23.1.tar.gz
unzip nginx-http-flv-module-master.zip
sudo mkdir /usr/local/nginx
sudo mv nginx-http-flv-module-master /usr/local/nginx/nginx-http-flv-module/

注:nginx-http-flv-module模块是基于 nginx-rtmp-module 的流媒体服务器,所以在编译时无需再引入nginx-rtmp-module,而且nginx-rtmp-module的各项配置也是兼容的。

3.4.编译安装Nginx软件

进入/home/nginx/nginx-1.23.1目录下执行以下命令
sudo ./configure --prefix=/usr/local/nginx --with-http_ssl_module --add-module=/usr/local/nginx/nginx-http-flv-module
sudo make
sudo make install

此时nginx已安装成功,可以执行/usr/local/nginx/sbin/nginx -V查看版本号,会输出以下内容:

nginx version: nginx/1.23.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --add-module=../nginx-http-flv-module

如果安装之后需要增加模块,可以使用configure命令添加配置,然后make,之后不要make install ,将编译的二进制文件手动拷贝到sbin目录下即可

cp ./objs/nginx /usr/local/nginx/sbin/

3.5.修改nginx配置文件

安装后的nginx配置文件中没有rtmp的相关配置,需要自行配置相关内容,以下是完整的配置文件内容

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}

rtmp {
    server {
        listen 1985;

        application live {
            live on;
            gop_cache on;
            publish_notify on;
            on_publish http://172.16.70.234:8080/swms/oa/index_notifyLiveStart.action;
            #on_update http://172.16.70.234:8080/swms/oa/index_notifyLiveStart.action;
            on_publish_done http://172.16.70.234:8080/swms/oa/index_notifyLiveStop.action;
        }
    }
}


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

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       8080;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        location /live {
            flv_live on;
        }

        location /flv {
            add_header 'Access-Control-Allow-Origin' '*';
            flv_live on;
            chunked_transfer_encoding on;
        }

        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            root nginx-http-flv-module/;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

}

其中rtmp段和http->server->location中的/live, /flv, /stat, /stat.xsl为新增段落

3.6.启动nginx

现在就可以启动nginx了,使用以下命令控制nginx

#启动
sudo /usr/local/nginx/sbin/nginx
#停止
sudo /usr/local/nginx/sbin/nginx -s stop
#重新加载配置文件
sudo /usr/local/nginx/sbin/nginx -s reload

3.7.安装nginx为服务

创建服务描述文件

sudo vi /usr/lib/systemd/system/nginx.service

内容如下:

[Unit]
Description=nginx - web server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
ExecQuit=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

然后重新加载服务配置

systemctl daemon-reload

然后就可以使用服务命令控制nginx了

#停止Nginx服务
sbin/nginx -s stop

#开启Nginx服务
systemctl start nginx

#查看Nginx服务状态,出现【active (running)】表示服务正在运行
systemctl status nginx

#设置开机启动
systemctl enable nginx.service

#查看进程是否已启动
ps aux | grep nginx

#查看端口启用情况
netstat -tunlp
#使用sudo可以查看pid和程序名,然后再按nginx过滤
sudo netstat -tunlp | grep nginx

4.推流测试

使用ffmpeg进行测试

#视频文件推流:
ffmpeg.exe -re -i c:\ffmpeg\inputfile.mp4 -vcodec libx264 -acodec aac -f flv rtmp://127.0.0.1:1985/live/mp4

#桌面推流
ffmpeg -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f flv rtmp://127.0.0.1:1985/live/desk1

#拉流测试
ffplay.exe rtmp://localhost:1985/live/mp4

5.网页播放

因为rtmp协议在网页上播放时需要使用flash插件,但现在各大浏览器已经不再支持flash插件了,所以需要使用http_flv协议实现网页播放的功能,这也是选择了nginx-http-flv-module模块的原因,在网页上播放http_flv需要使用bilibili开源的flv.js组件

https://github.com/bilibili/flv.js

可以下载源码进行编译,也可以直接下载编译好的Releases 版本的flv.js文件

http://bilibili.github.io/flv.js/dist/flv.js
https://github.com/bilibili/flv.js/releases/download/v1.6.2/flv.js

使用方法如下:

 <script src="flv.js">script>
 <video id="videoElement" width="360" height="480">video>
<script>
	var url = 'http://localhost:8080/flv?port=1985&app=live&stream=mp4';
  if (url && flvjs.isSupported()) {
      var videoElement = document.getElementById('videoElement');
      window.flvPlayer = flvjs.createPlayer({
          type: 'flv',
          url: url
      });
      flvPlayer.attachMediaElement(videoElement);
      flvPlayer.load();
      flvPlayer.play();
  }
script>

可以对FlvPlayer进行封装,监听相关事件,实现网络中断再次接通后重新加载播放功能

var liveOpt = {
	liveStat:0,//直播是否开始,0未开始 1已开始
	livePlayUrl:'http://....',//直播观看地址
	flvPlayer:null,
	startLive : function(){
		if (this.liveStat==1 && flvjs.isSupported()) {
			var videoElement = document.getElementById('videoElement');
			var flvPlayer = this.flvPlayer = flvjs.createPlayer({
			    type: 'flv',
			    isLive:true,
			    url: this.livePlayUrl
			}, {isLive:true});
		    flvPlayer.attachMediaElement(videoElement);
			flvPlayer.on(flvjs.Events.ERROR, ()=>{
				console.log('ERROR', arguments);
				this.restartHandle = clearTimeout(this.restartHandle);
				this.restartHandle = setTimeout(this.restartLive.bind(this), 3000);
			});
			this.metaArrived = false;
			flvPlayer.on(flvjs.Events.METADATA_ARRIVED, ()=>{
				console.log('METADATA_ARRIVED', arguments)
				if(this.metaArrived){//如果第二次发来Meta信息,说明是断线后重连了,此时重新初始化控件
					this.restartLive();
				}
				this.metaArrived = true;
			});
	     	flvPlayer.load();
	      	flvPlayer.play();
		}
		else{
			setTimeout(startLive, 600);
		}
	},
	stopLive : function (){
			if(this.flvPlayer){
				try{
					this.flvPlayer.destroy();
				}
				catch(e){}
				this.flvPlayer = null;
			}
	},
	restartLive:function(){
		console.log('try to restart live!')
		this.stopHandle && clearTimeout(this.stopHandle);
		this.startHandle && clearTimeout(this.startHandle);
		this.stopHandle = setTimeout(this.stopLive.bind(this), 1000);
		this.startHandle = setTimeout(this.startLive.bind(this), 2000);
	}
};

6.降低直播延迟

这一套环境搭建起来之后,跑通测试一番,结果发现在百兆局域网的条件下,延迟最小只能到3秒左右,而且flv.js稳定性还比较差,经常出现卡死不能播放的情况,后来无意中发现一款商用播放器NodePlayer,经测试可以达到1.3s左右的延迟,经过对比发现flv.js使用的是html5的video标签,而NodePlayer默认使用canvas进行渲染,当强制NodePlayer强制使用video标签渲染时,延迟也在3秒左右,所以说应该是使用video标签导致延迟过高,但因为NodePlayer是闭源软件,商用需要收费,所以在这里就不放链接了,给大家一个选择

7.资源下载

nginx源码
nginx-rtmp-flv模块
nginx.conf

你可能感兴趣的:(rtmp,nginx,服务器,nginx,html5)