最近这几年作直播和短视频领域是真的很火,并且直播的领域也很普遍,能够预见,将来的音视频技术将会做为一种基础技术应用到更普遍的场景中。它能够与 AR/VR 结合,让你在远端体验虚拟与现实,如虚拟服装体验;也能够与人工智能结合用于提升服务质量,如用于教学上帮助老师提升教学质量;它还能够与物联网结合,用在自动驾驶、家庭办公等领域。那么这么火范围这么广的领域咱们可不能够参与一下呢,确定是能够的,下面咱们借助 Nginx 和 nginx-http-flv-module 搭建一个简易的直播服务器,固然若是对并发要求不是过高的,这个彻底能够知足了。css
因为笔者没有后台服务开发的经验而且对一些服务环境配置也不太懂,因此也是参考了一些博客最后总结了一套安装使用教程,下面附上详细的步骤。html
注意: 如下文字中若有出现 http://ip:port
,请替换成您本身的 IP 或域名。前端
国内常见公开的直播协议有几个:RTMP、HLS、HDL(HTTP-FLV)、RTP,咱们来逐一介绍。node
它是 Adobe 的专利协议,如今大部分国外的 CDN 已不支持。在国内流行度很高。缘由有几个方面:android
一、开源软件和开源库的支持稳定完整。如斗鱼主播经常使用的 OBS 软件,开源的 librtmp 库,服务端有 nginx-rtmp 插件。nginx
二、播放端安装率高。只要浏览器支持 FlashPlayer 就能很是简易的播放 RTMP 的直播,协议详解能够 Google 了解。相对其余协议而言,RTMP 协议初次创建链接的时候握手过程过于复杂(底层基于 TCP,这里说的是 RTMP 协议自己的交互),视不一样的网络情况会带来给首开带来 100ms 以上的延迟。基于 RTMP 的直播通常内容延迟在2~5 秒。git
即便用 HTTP 协议流式的传输媒体内容。相对于 RTMP,HTTP 更简单和广为人知,并且不担忧被 Adobe 的专利绑架。内容延迟一样能够作到 2~5 秒,打开速度更快,由于 HTTP 自己没有复杂的状态交互。因此从延迟角度来看,HTTP-FLV 要优于 RTMP。github
即 Http Live Streaming ,是由苹果提出基于 HTTP 的流媒体传输协议。HLS 有一个很是大的优势:HTML5 能够直接打开播放;这个意味着能够把一个直播连接经过微信等转发分享,不须要安装任何独立的 APP,有浏览器便可,因此流行度很高。社交直播 APP,HLS 能够说是刚需,下来咱们分析下其原理 。ajax
基于 HLS 的直播流 URL 是一个 m3u8 的文件,里面包含了最近若干个小视频 TS(一种视频封装格式,这里就不扩展介绍)文件。如 http://ip:port/live.m3u8
是一个直播留连接,其内容以下:正则表达式
假设列表里面的包含 5 个 TS 文件,每一个 TS 文件包含 5 秒的视频内容,那么总体的延迟就是 25 秒。固然能够缩短列表的长度和单个 TS 文件的大小来下降延迟,极致来讲能够缩减列表长度为 1,1 秒内容的 m3u8 文件,可是极易受网络波动影响形成卡顿。经过公网的验证,目前按同城网络能够作到比较好的效果是 5~7 秒的延迟,也是综合流畅度和内容延迟的结果。
即 Real-time Transport Protocol ,用于 Internet 上针对多媒体数据流的一种传输层协议。
实际应用场景下常常须要 RTCP(RTP Control Protocol)配合来使用,能够简单理解为 RTCP 传输交互控制的信令,RTP 传输实际的媒体数据。
RTP 在视频监控、视频会议、IP 电话上有普遍的应用,由于视频会议、IP 电话的一个重要的使用体验:内容实时性强。
对比与上述 3 种或实际是 2 种协议,RTP 和它们有一个重要的区别就是默认是使用 UDP 协议来传输数据,而 RTMP 和 HTTP 是基于 TCP 协议传输。为何 UDP 能作到如此实时的效果呢?关于 TCP 和 UDP 差异的分析文章一搜一大把,这里不在赘述,简单归纳:
UDP:单个数据报,不用创建链接,简单,不可靠,会丢包,会乱序;
TCP:流式,须要创建链接,复杂,可靠 ,有序。
实时音视频流的场景不须要可靠保障,所以也不须要有重传的机制,实时的看到图像声音,网络抖动时丢了一些内容,画面模糊和花屏,彻底不重要。TCP 为了重传会形成延迟与不一样步,如某一截内容由于重传,致使 1 秒之后才到,那么整个对话就延迟了 1 秒,随着网络抖动,延迟还会增长成 2 秒、3 秒,若是客户端播放是不加以处理将严重影响直播的体验。
总结一下:在直播协议的选择中,若是选择是 RTMP 或 HTTP-FLV 则意味着有 2~5 秒的内容延迟,可是就打开延迟开,HTTP-FLV 要优于 RTMP。HLS 则有 5~7 秒的内容延迟。选择 RTP 进行直播则能够作到1秒内的直播延迟。但就目前所了解,各大 CDN 厂商没有支持基于 RTP 直播的,因此目前国内主流仍是 RTMP 或 HTTP-FLV 。
原本我打算是在个人 我的博客 服务器上搭建的,最终仍是放弃了,由于以前的带宽跟容量也不是很大,也正巧遇见了 腾讯云 这几天在搞活动就又购买了一台服务器,之后关于后台服务的项目也基本上在这台部署了。
如下是我搭建以及测试的环境
搭建服务器环境
云服务器: 腾讯云
系统: centos
直播服务器: nginx
拓展模块: nginx-http-flv-module (支持 rtmp、http-flv、http-hls 等)
若是 NGINX 要支持正则表达式,须要安装 PCRE库。
若是 NGINX 要支持加密访问,须要安装 OpenSSL库。
若是 NGINX 要支持压缩,须要安装 zlib库。
测试环境:
电脑 : MAC
推流软件: obs-studio
MAC 拉流软件: VLC
Android 拉流软件: 前几天写的一个 Android 播放器 ykplayer 正好供于拉流测试
HTML5 FLV 播放器: bilibili 开源的 flv.js
原本以前我是借助 nginx-rtmp-module 来搭建的直播服务器(已成功),奈何它好像不支持 Http-flv 协议,因此替换成了 nginx-http-flv-module 模块,它是基于 nginx-rtmp-module 模块二次开发的,因此完美的继承了 rtmp 模块的全部功能。
# 经过 wget 命令下载
wget http://nginx.org/download/nginx-1.17.8.tar.gz
# 解压
tar -zxvf nginx-1.17.8.tar.gz
复制代码
提醒: 关于它的详细信息能够参考它的介绍
# 经过 wget 命令下载
wget https://github.com/winshining/nginx-http-flv-module/archive/v1.2.7.tar.gz
# 解压
tar -zxvf v1.2.7.tar.gz
# 重命名
mv v1.2.7 nginx-http-flv-module
复制代码
若是在执行 configure 以后报 OpenSSL 、PCRE 、Zlib error 那么就必须安装它们
#安装 openssl
yum install openssl
#安装 pcre
yum install pcre-devel
#安装 zlib
yum install zlib-devel
复制代码
等它们安装好了以后编译 nginx
在当前解压 nginx 目录中建立编译 nginx 和 http-flv 脚本
#!/bin/sh
# ../ 表明当前目录的上一级
HTTP_FLV_MODULE_PATH=../nginx-http-flv-module-1.2.7
OpenSSL_PATH=../openssl-1.1.1d
#--prefix=./bin 表明编译完成以后输出的路径地址
#--add-module 将拓展模块添加到当前一块儿编译
./configure --prefix=./bin \
--add-module=$HTTP_FLV_MODULE_PATH \
--with-openssl=$OpenSSL_PATH \
--with-debug
# 经过 make install 构建
make
make install
复制代码
若是中途没有报任何错误,而且输出了咱们指定的 bin 目录,那么就表明成功了。以下图所示:
在当前目录下输入 vim bin/conf/nginx.conf
进行配置 rtmp、http 直播协议,我直接贴上个人配置
user root;
worker_processes auto; #运行在Windows上时,设置为1,由于Windows不支持Unix domain socket
#worker_processes auto; #1.3.8和1.2.5以及以后的版本
#worker_cpu_affinity 0001 0010 0100 1000; #只能用于FreeBSD和Linux
worker_cpu_affinity auto; #1.9.10以及以后的版本
error_log logs/error.log error;
#若是此模块被编译为动态模块而且要使用与RTMP相关的功
#能时,必须指定下面的配置项而且它必须位于events配置
#项以前,不然NGINX启动时不会加载此模块或者加载失败
#load_module modules/ngx_http_flv_live_module.so;
events {
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
server {
listen 80;//自定义填写 http 的端口
location / {
root /root/nginx/nginx-http-flv-module-1.2.7/test/www;
index index.html index.htm;//默认首页
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /flvjsplay {//测试地址
root /root/nginx/flv.js-1.5.0;
index index.html;//flv.js 测试播放首页
}
location /flv {
flv_live on; #打开HTTP播放FLV直播流功能
chunked_transfer_encoding on; #支持'Transfer-Encoding: chunked'方式回复
#跨域
add_header 'Access-Control-Allow-Origin' '*'; #添加额外的HTTP头
add_header 'Access-Control-Allow-Credentials' 'true'; #添加额外的HTTP头
}
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /root/nginx/nginx-http-flv-module-1.2.7;
add_header 'Cache-Control' 'no-cache';
}
location /dash {
root /root/nginx/nginx-http-flv-module-1.2.7;
add_header 'Cache-Control' 'no-cache';
}
location /stat {
#push和pull状态的配置
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root /root/nginx/nginx-http-flv-module-1.2.7; #指定stat.xsl的位置
}
#若是须要JSON风格的stat, 不用指定stat.xsl
#可是须要指定一个新的配置项rtmp_stat_format
#location /stat {
# rtmp_stat all;
# rtmp_stat_format json;
#}
location /control {
rtmp_control all; #rtmp控制模块的配置
}
}
}
rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /root/nginx/nginx-http-flv-module-1.2.7;
rtmp {
out_queue 4096;
out_cork 8;
max_streams 128;
timeout 30s;
drop_idle_publisher 30s;
log_interval 5s; #log模块在access.log中记录日志的间隔时间,对调试很是有用
log_size 1m; #log模块用来记录日志的缓冲区大小
server {
listen 1935;//自定义 rtmp 端口
# server_name www.test.*; #用于虚拟主机名后缀通配
application devyk {
live on;
gop_cache on; #打开GOP缓存,减小首屏等待时间
}
application hls {
live on;
hls on;
hls_path /root/nginx/nginx-http-flv-module-1.2.7/hls;
}
application dash {
live on;
dash on;
dash_path /root/nginx/nginx-http-flv-module-1.2.7/dash;
}
}
#能够有多个 server 配置
}
复制代码
在根目录输入 bin/sbin/nginx -t , 如出现以下就说明配置成功。
#开启服务
bin/sbin/nginx
#中止服务
bin/sbin/nginx -s stop
#重启服务
bin/sbin/nginx -s reload
复制代码
http://ip:port
,若是出现以下,证实首页和基本配置没有问题了http://ip:port/stat
如出现以下监控页面,说明监控页面一切正常。如今服务器搭建完成,下面能够进入测试环节了。
咱们直接用开源 obs-studio 软件进行推流,据说不少游戏主播也用该款推流软件。
推流源设置:
如上图所示,证实已经推流成功了,下面咱们就来测试拉流。
注意: 其它播放也是以下格式,这里只是以 Html 举例说明:
例子:
假设在http
配置块中的listen
配置项是:
http {
...
server {
listen 8080; #不是默认的80端口
...
location /live {
flv_live on;
}
}
}
复制代码
在rtmp
配置块中的listen
配置项是:
rtmp {
...
server {
listen 1935; #也能够不是默认的1935端口
...
application myapp {
live on;
}
}
}
复制代码
而且发布的流的名称是mystream
,那么基于 HTTP-FLV 的播放url是:
http://ip:8080/flv?port=1935&app=myapp&stream=mystream
复制代码
播放器这里选择 bilibili 开源的 flv.js , 既然咱们已经有服务器了,那就直接把 flv.js 项目部署在服务器上吧
#安装 npm
yum install npm
#检查是否安装成功,若有输出证实安装成功
npm --version
复制代码
#经过 wget 下载
wget https://github.com/bilibili/flv.js/archive/v1.5.0.tar.gz
#解压
tar -zxvf v1.5.0.tar.gz
复制代码
进入 flv.js 根目录直接输入 npm install
命令,安装完成以后会出现一个 node_modules
模块
仍是在当前根目录下安装,输入以下命令:
npm install -g gulp
复制代码
#输入以下命令
gulp release
复制代码
这一步执行完成以后会生成以下文件:
将 demo 中 2 个文件(.ccs,.js) copy 到 dist 文件下,并修改 html 中 flv.js 路径,以下所示:
最后将 dist 文件夹重命名 flvjsplay
nginx.conf 配置网页加载路径:
location /flvjsplay {//测试地址
root /root/nginx/flv.js-1.5.0;
index index.html;#flv.js 测试播放首页
}
复制代码
修改了配置文件须要在 nginx 根目录输入以下指令,对 nginx 服务器重启:
#从新启动
bin/sbin/nginx -s reload
复制代码
左边是拉流,右边是推流
能够看到首屏加载速度仍是比较快延迟在 2-5s 之间,画面延迟有点高跟我服务器和网络有关。
VLC 点击文件->打开网络输入 rtmp 拉流地址点击播放
//配置rtmp 拉流格式
//ip:host
//rtmpPost:rtmp 服务的端口
//appname 配置在rtmp application 的名称
//streamname:推流的时候填写的密码
rtmp://ip:rtmpPort/appname/streamname
复制代码
左边是拉流,右边是推流
播放格式:
http://ip:port/hls/streamname.m3u8
复制代码
由于笔者不是作 H5 开发的,因此对浏览器播放 HLS 直播流兼容性不是太清楚,我就直接使用 video 标签在我电脑上用 chrome 浏览器测试, 结果是播放不出来的,查了资料好像说是原生 video 标签仅支持 MP四、WebM、Ogg 格式,那这怎么办呢?其实能够直接使用开源项目来解决的,好比 video.js 、videojs-contrib-hls 等,我这里直接使用的是 videojs-contrib-hls ,目前测试在 Android 浏览器、PC 谷歌浏览器 、IOS 微信、IOS Safari 浏览器 均已成功,下面是 Html 代码,以下所示:
<html>
<head>
<meta charset="utf-8" />
<title>Player</title>
<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
</head>
<body>
<video id="video" class="video-js vjs-default-skin" controls autoplay="autoplay" width="640" height="320" data-setup='{}'>
//换成你本身的直播连接
<source src="http://ip:8082/hls/live1.m3u8" type="application/x-mpegURL" />
</video>
<script src="https://unpkg.com/video.js/dist/video.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-hls/5.12.1/videojs-contrib-hls.min.js"></script>
</body>
</html>
复制代码
注意:在这儿使用的 js 等资源皆是在线的一些支持。若须要在项目中使用,最好下载到本地使用
为了测试方便,我也直接把该 Html 代码部署到了云服务器中,nginx.conf 配置以下:
location /hlsplay {
root /root/nginx/nginx-http-flv-module-1.2.7/hls;
index hlsplay.html; //指定首页,也就是咱们播放的页面,hlsplay.html 就是上面代码。
}
复制代码
重启 nginx 服务器以后,直接输入 http://ip:port/hlsplay
就能够播放了,测试效果以下图:
到这里您已经成功搭建直播服务器了,虽说该篇文章没有敲任何的代码,也许你会说没有学到什么,可是搭建服务器和部署一套简易直播环境这个过程也都是值得咱们做为一个移动或者前端开发者学习的。