站点图标 Linux-技术共享

架设一个自己的网络电视台,直播加点播

livee021-1

近日笔者帮朋友办直播讲课,折腾了几天,不但目标完成,还支持多路节目多机直播,观众自动分配直播源。哈哈哈哈哈哈,这不就差不多搞成一个网络电视台了吗?可把笔者牛逼坏了。
OK,既然是通过网络学习,参考很多朋友的文章,最后有了点成绩,那就记录分享一下笔者的成果,写一个文章吧。

LIVE RTMP HLS Nginx Streaming Broadcast 直播 点播

目录
一:资源准备
二:直播点播技术简介
三:简单直播架设
四:进阶直播
五:录像等其他问题

前提:为啥要费劲心思的搞一个自己的直播平台呢?网上现成的平台多的是,为啥不用?提出需求是因为某个艺术品圈子里的朋友们在微信群等基本手段不能满足需要的时候,便提出了请前辈开视频课的需求。我们的主讲和听众里半数来自大陆,剩下的人都分布在好几个时区上。而斗鱼、抖音之类的直播平台其实都是分区经营的。并且要申请在大陆地区开放,而申请人是非大陆居民的直播间更加漫长和繁琐。其实对不在国内的几位主讲人来说,也有其他好用的直播平台,可惜这些平台在大陆又无法访问。于是建设一个方便的,全球通的视频直播就是个不错的方案了。

一:资源准备

首先要做网络电视台,实现直播或点播服务,必须要有网络服务器,笔者是用的几台VPS实现。由于不是土豪,手里的vps都不是什么太高配置,存储空间也有限,所以算下来成本很低。此次实现多机直播总共动用了5台主机,但是起步阶段只需要一台就够了。主机配置不能太低,1G内存起码是需要的,CPU也不能太差。搬瓦工、Vultr等家的vps提供的CPU还是可以的。但是要注意像谷歌、阿里的最低价最低突发性能cpu就不合适做这个直播,很容易触及性能警戒线。

存储空间的要求看你想放多少东西了。只做基础直播的话,有10G空余空间用来存放录像就可以了(记得及时转存和清理)。如果想开个电影院,那就要准备大大的硬盘了。

最后是网络带宽和流量的问题了,以720p画面,25帧速直播的话,平均上传带宽至少是300KB每秒,观众侧也大体相当。(注意这里使用的是HLS播放模式,并非rtmp广播,理由后文详说。)也就是说10个人看,下行带宽就需要300*10*8Kbps,大约24Mbps的带宽。(请注意KB和Kbps的区别)。实际上由于数据编码的容量弹性问题,以及我们还要采用http或https提供传输,消耗一定的打包流量,所以总下行带宽至少28Mbps才能基本保证观看的稳定。如果希望承载100观众,下行带宽需要250Mbps以上的才可以。我们知道大部分vps商家提供的网络接口都是千兆网或万兆网,似乎网络下行速率不是问题。但那都是共享带宽,实际上每个主机都无法保证连续的高带宽输出。至少在搬瓦工的主机上几乎是没法实现200Mbps稳定输出的(短时可以)。所以要想承载大量观众,就需要多台主机进行负载均衡。最后说说流量,简单来说就是一路上行,N路下行。一般主机商都是只计算下行流量的,目前只有搬瓦工计双向,vultr上下行只计算一路流量多的。以上边我们说的300KB一路直播,一个小时大约1GB流量,10个人就是10GB。请考量自己的流量套餐包喽。

二:直播点播技术简介

RTMP,全称 Real Time Messaging Protocol,即实时消息传送协议。Adobe 公司为 Flash 播放器和服务器之间音视频数据传输开发的私有协议。
HTTP-FLV 依靠 MIME 的特性,根据协议中的 Content-Type 来选择相应的程序去处理相应的内容,使得流媒体可以通过 HTTP 传输。相较于 RTMP 协议,HTTP-FLV 能够好的穿透防火墙,它是基于 HTTP/80 传输,有效避免被防火墙拦截。但是收到flash市场的萎缩影响,以及各大主要浏览器厂商正在逐步取消flash的支持影响。http-flv技术前景堪忧。
HLS (HTTP Live Streaming) 则是苹果公司基于 HTTP 的流媒体传输协议。主要应用于 iOS 设备,包含(iPhone, iPad, iPod touch) 以及 Mac OSX 提供音视频直播服务和录制内容(点播)等服务。但是HLS技术被主流浏览器厂商支持,现在又获得HTML5标准支持。成为未来的主流技术。

直播技术实现有很多小众技术,但是目前最普遍的还是rtmp流媒体技术加HLS。其他的直播技术就不废话了,反正不开源,也不好用。直入正题rtmp是基于tcp协议的媒体流数据传输协议,相比rtsp这种基于udp的协议,rtmp更适合互联网采用。观众这边我们建议使用HLS协议观看,而不建议使用rtmp协议直接收流。理由是rtmp协议在有些观众的网络环境内会遇到防火墙限制,考虑到全球观众的网络环境差异,rtmp方式变得不是十分可靠。同时rtmp容易受网络状况波动影响,出现卡顿或者马赛克花屏。推荐使用的HLS是一种基于http协议的媒体播放协议,由苹果公司推动,获得Html5标准支持。其实HLS并不是针对直播服务设计的,它主要是用来在线提供视频播放服务。HLS并不是真正的实时直播,但是它使用http或https协议,带来的优点是:可以轻松穿过各种防火墙,不受特殊网络限制,主流浏览器完美支持。有一点点缺点就是直播视频会存在无法根除的延时(最低极限也要大于8秒,一般在20~30秒)。HLS对比rtmp协议还有一个问题就是无法使用广播方式来节约带宽(在内网有效,在互联网环境广播方式基本无法使用),也不方便使用多码率实现多种清晰度的切换(可实现但是很复杂)。

流媒体直播基本结构

简单说一下直播的工作流程:
首先主播通过PC或Ipad等终端,进行录音录像,将数据编码后通过rtmp协议推送给流媒体服务器;服务器对音视频进行切片加工或保存后,分发给所有观众;观众通过浏览器或者播放器观看视频内容。很简单吧。
再看看点播工作流程就更简单了,这里没有主播,只有服务器,观众通过web页面浏览到某个电影视频,点击播放,就会访问服务器的流媒体接口,服务器把视频文件地区出来,分片编码,通过流媒体接口发送给客户的浏览器或播放器进行显示。其实点播服务器比直播需要更高的硬件配置,对磁盘性能和内存、CPU都有一定的要求。
以上内容看似简单,却也隐含着很多技术细节。下文我们将一起实现它。

三:简单直播架设

首先选择软件方案。实现rtmp流媒体直播,过去是real公司的流媒体服务Helix系统比较多,后来Flash、QuickTime和微软等公司也提供了类似的服务产品。之后很多开源产品也加入了进来,比如Red5,OSS,Live555,DSS,YASS等等吧。这些有基于linux平台的也有基于windows平台的。这些商用级别的大家伙功能强大,管理能力也更强,但是搞起来难度也着实的高。最重要的是他们需要的硬件资源也更高。我们在性能孱弱的vps小鸡上实现直播,还是应该在性能要求上尽可能的轻量化。况且小鸡上一般都是采用debian或centos系统,所以我们首选就是nginx的rtmp插件(Nginx-rtmp-module)来实施,这个插件同时还支持流录制和转发,HLS服务等功能。总之我们所需的它都有了。而且nginx和rtmp插件也有windwos版本,可以在windows环境同样实现。
nginx-rtmp-module是nginx的一个功能插件,开源,免费,稳定,高性能,可扩展。
nginx的安装这里不做详解,网上教程太多了。更有方便的lnmp一键安装包。(https://lnmp.org/notice/lnmp-v1-6.html) 网上找的nginx安装教程,一般都不包含rtmp模块。所以说一下在lnmp环境上增加rtmp模块的方法。
登录主机ssh后,找到lnmp安装包目录,比如笔者这里是 /usr/lnmp1.6 (具体位置取决于你安装lnmp时,下载安装包,自动解压所在的目录位置)。 我们编辑一下 lnmp.conf 配置文件。给Nginx_Modules_Options 这一项添加插件参数 –add-module=/usr/nginx-rtmp-module ,注意两侧单引号别丢了。

编辑 lnmp.conf 安装配置文件

我们添加的参数里指定了一个目录位置,这是可以根据需要改写的,目的是更新nginx时到指定的目录里编译加载插件。所以我们随后要做的就是按照指定的目录,去下载rtmp模块。

执行命令
cd /usr
git clone https://github.com/arut/nginx-rtmp-module

至此完成了rtmp模块的克隆。然后就可以运行 ./upgrade.sh nginx 升级(更新)一下nginx就行了。
顺带说一下,以后我们还需要用到nginx的一个插件stream来实现端口转发,但是这个模块从nginx1.9就是默认安装的,所以不用手动添加,如果你的nginx是自行手工配置编译的,请注意是否包含了这个模块。
至此一个简单的直播服务软件部分已经最低限度的搞好了。下一步进行配置工作。

先去lnmp里架设一个web站点,以后用于观众访问。执行lnmp vhost add ,之后按照提示输入域名,目录,选择https证书等等常规建站操作。(域名的dns解析,需要你提前做好,并且确认dns指向已经生效。)
站点建设完成后,lnmp会在 /home/wwwroot 目录下生成这个站点的根目录。我们再新建一个用于直播和存储的目录,我们就在wwwroot 目录下再mkdir一个 LIVE 目录,在LIVE 之内分别新建 RTMP和record 目录,分别用于观看直播和录像存储。(顺便说一句,linux环境下是严格区分大小写的,所以目录和文件名也需要确认大小写,否则是找不到目录和文件的。目录名称可以随你喜欢,主要是下边配置文件种要与实际一致。)

新建直播需要的存储目录

之后我们开始修改配置文件。

3.1 配置直播推流侧

执行 vim /usr/local/nginx/conf/nginx.conf 命令,可以看到 原本的文件内有一大段http配置。在http段之前,我们增加一个 rtmp段,内容见下图。

Nginx 的主配置文件 nginx.conf

先看一个 listen 1935 这个定义了服务端口号,默认rtmp协议就是使用1935号tcp端口。再来看 application live这段,这里的 live是一个路径名,并不是物理目录,请区别于我们之前设置的LIVE目录。这个live段的配置实现了一个直播服务的接口。内部参数 live on 表示直播服务开启; hls on 表示HLS播放服务开启; hls_path 指定了HLS播放媒体的物理目录。 后边几个hls开头的参数分表表示了缓冲列表最大时长60秒,媒体切片10秒,自动清理切片开启等等。 再下边record开头的几个参数配置了录像信息,内容很好理解,笔者不想多费口舌了。 请注意 allow publish 127.0.0.1 以及下边 deny publish all 这两行信息。 这里是说明只允许 从本机127.0.0.1地址进行推流进来,随后阻止其他任何推流。其他地址尝试推流连接会被服务器拒绝。这么写有什么用呢? 这里仅是提供了一个简单的安全防护,用于防止主机被扫描,被强推流。 我们真正的服务端口可以是其他的,比如使用1905.

通过上图,可以看到在rtmp段之前还添加了一个stream段。这就是前文提到的stream模块。上图我们实现了两个端口转发服务。1905和1904分别转发至本机1935和1934端口。这样当主播推流到1905端口后,就会被转发至127.0.0.1本机的1935端口上。根据你的喜欢,你也可以使用443或者3389等端口实现直播服务。

3.2 配置观众播放服务

观众是通过http/https站点读取的HLS文件数据观看直播内容的。所以要在开始时建立的网站上配置播放信息实现。我们进入 /usr/local/nginx/conf/vhost 目录,编辑之前我们开设的站点配置文件,比如 vim mywebsite.com.conf 。

每个站点有一个conf 配置文件

站点配置文件里默认是配置80端口的。当你站点启用https和证书后,会再增加443端口的配置。两个server段(80和443)里的内容除了证书加密方面的区别,其他基本相同。上图中80段里的配置笔者都给删除了,改写成301跳转,见红线部分。意思是这个站点强制使用https访问,任何访问80端口的请求,都会被301强制跳转到443端口上去。下图是443段里的配置,如果你不启用https,仅使用http服务的话,下图中的内容,就请填写到80段中去。

图中 location /live 段配置了一个url路径live, 内部配置指定了文件类型、物理路径等信息。实际上观众就是通过 https://mywebsite.com/live/节目名/index.m3u8 这个路径观看直播的。m3u8 类型文件本身就是一个索引文件,内部引用了一个 ts文件序列,这个序列是被HLS
服务不断更新的,观众获取这个文件后,根据内部指定的ts文件名去下载ts切片文件进行播放,从而实现观看直播视频。后边还有一个 Location /hls段,这个段不是必须,其实这是笔者配置的另一个播放点而已,与live性质相同。 图片中部有 location /stat 和 /stat.xsl 两个段,这两个段的意义是,管理员可以通过 https://mywebsite.com/stat 这个路径查看rtmp服务器运行状态,监控连接数,数据流量等信息。至此,一个简单的直播服务已经架设完成了。

stat 服务器状态

验证一下直播服务,通过PC端的OBS软件或者iphone上的易推流app,我们就可以发起直播了。
推流地址应该是: rtmp://mywebsite.com:1905/live/my001 推流的其他配置请参考推流软件上的帮助,选择合适的视频码率,和音频参数。 点击开始直播推流。
观众可以通过 https://mywebsite.com/live/my001/index.m3u8 观看,直接把这个地址贴在浏览器上就可以查看(主流浏览器 safari,chrome,edge 浏览器都可以),也可以把这个地址写入某个网页上,进行页面播放。
上文url中的live 我们可以理解为频道名,这个是服务器约定的,不能随便更改, my001 就是节目名,是推流主播可以自行决定的(一般也是约定好的),但是观众也需要知道,否则播放地址就找不到了。

LIVE RTMP HLS Nginx Streaming Broadcast 直播 点播

目录
一:资源准备
二:直播点播技术简介
三:简单直播架设
四:进阶直播
五:录像等其他问题

四:进阶直播

所谓进阶,就是在上文我们那个基本的直播服务上,增加一些实用的功能。 可能有人已经注意到,推流地址是固定的,且没有安全验证(虽然我们用端口转发进行了一点隐藏工作,但只能防止端口扫描)。也就是说一旦泄露出去,任何人都可以强行推流进来。所以我们首先要做的就是对推流进行身份验证。

4.1 添加身份验证

要想让rtmp模块增加身份验证,可以通过修改源代码的方式实现。但那难度太高,不适合大家推广。我们还可以通过动作事件来进行身份验证。看下图红线部分,通过 on_publish 事件来指定一个验证页面。这个页面可以是本机上的一个php页面(现成的nginx和php环境对吧),也可以是互联网上其他位置的页面。笔者这里指定了一个自己写的验证服务,方便实现更复杂的验证工作(其实php水平太烂)。注意下图还有一句 notify_method get 不要丢了。

on_publish 事件 指定一个验证页面

同理其实 on_play 事件也可以用来验证播放者身份。但是,我们这里用hls播放而非rtmp播放,所以这里没用了(要实现播放鉴权,可以参考后文多机直播部分的多地址分发服务)。
说回这个身份验证页面,如果你指定本机一个 mywebsite.com/yanzheng.php 页面。那么这个页面可以这么写 :

yanzheng.php 页面文件

请注意上图中验证的用户名和密码通过 $_GET[‘user’]和$_GET[‘pass’] 取出了 Url中的user和pass参数,这些参数其实是可以随便改的,完全可以用name和tok代替。验证方式可以是简单的密码比对,也可以是数据库查询。最终验证通过,只要页面正常返回即可,输出什么内容无所谓。验证不通过,就返回一个404错误码就行了。这样没有正确密码的推流端就会被断开。愿意的话,可以把每次验证的信息、IP、结果存在服务器日志或数据库中。

当服务器配置好推流验证信息后,推流主播的推流地址也要相应调整。原来主播推流地址是 rtmp://mywebsite.com:1905/live/my001 。此时我们要改写成
rtmp://mywebsite.com:1905/live/my001?user=zhuboming&pass=mima
的形式。有些软件会要求推流地址和节目名分开写,那么就是这样

OBS 里将推流地址与串流码分开写的形式

到此,我们给主播推流加上了一个账号密码的验证。但是说实话,这样的用户名密码太不安全了。可否将用户名、密码、节目名、主播IP地址等等进行联合验证吗?当然可以,只要你自己写验证页面就行了。 笔者把验证的请求抓包出来,给各位看看,验证页面到底可以得到多少东西用来做安全检验。

rtmp 服务器使用get 方法调用验证页面时 传递的参数

上图展示了rtmp向验证页面发送的数据中最重要的部分,来简单解释一下。 app=live 这个就是对应服务器上配置的 application live 接口,参数值就是接口名或者说我们规定的频道名。 下面的url不用解释了。 addr=127.0.0.1 表示了rtmp服务接受到的主播连接的对端IP地址(我们通过端口映射,所以这里变成了127.0.0.1,要想得到真实主播地址,可以不用端口映射,直接修改rtmp的端口就行了)。 Call=publish 表示触发验证的动作原因是推流。 Type=live这里说的是直播动作类型,这个live跟之前的app参数不是一个意思。 Name=my001表示的是节目名。User和pass就是我们推流地址上写的用户名和密码。 这些信息都是通过 Query_string参数穿进来的。 有了这些信息,我们可以采用联合验证的方式进行身份验证,比如主播的IP地址可以通过白名单筛选;比如用户名密码的参数名可以更换其他的误导词汇;比如把主播用户名与节目名和频道名联合验证,限定某主播只能在特定频道下特定节目名直播等等。只要你能写代码,都可以实现。

4.2 多机直播

前边提到过,当观众比较多的时候,对网络带宽压力比较大。对于这个问题,当然可以通过多花钱,买大带宽来解决。不过那样花费会比较大,我们也可以通过主机数量解决。毕竟小鸡的价格比带宽便宜,来的更实惠一些。我们之前配置好的那台主机,就叫主播服务器Core吧。然后我们再增加两台从属主机,叫边缘服务器edgeA和边缘服务器edgeB。当直播开始后,主播通过推流软件把媒体流推给主播服务器,主播服务器把媒体流分发给两个边缘服务器。观众就可以通过者三台主机访问观看了。承载能力立马翻三倍(理论上)。 媒体流从Core分发给edgeA和B的方式可以选择推或拉(push或pull指令)。经过测试两种方式效果相同。区别就是Core主动推给A和B还是A和B主动去Core上拉。这三台主机的推拉流还是需要rtmp协议,而不是通过HLS协议的。

多机直播图

当然,只要你愿意,可以设置多级服务器,也可以根据用户数量动态的加入新服务器,连推带拉,手忙脚乱,哈哈哈哈。

边缘服务器的 nginx.conf 文件

这是一个edgeA服务器的 nginx.conf 配置文件, 可以对比前文的主服务器上配置文件看。重点是增加了一行 pull 指令。通过rtmp协议向主服务器啦一个媒体流回来。要注意的时候,拉流的时候就必须指定好频道和节目名,这里是mr1900 。所以多机直播必须事先约定好节目名。 然后这里不能再配置 on_publish 的身份验证。由于我们主服务器上已经配置了录像record,所以这个边缘服务器上就不在重复录像了。如果你愿意,也可以在这里录像。其他信息与主服务器类似就不废话了。 边缘服务器上也要同主服务器上配置一个网站,除了域名地址与主服务器不同外,其他配置与主服务器类似,都是在站点.conf文件里添加好相应的 location 节点。节点名可以与主服务器相同或不同。 开始笔者猜测,如果采用主服务器向边缘服务器push的方式,相比pull方式会更及时一些。猜测边缘服务器的pull动作需要有观众触发才去拉流。但是经过测试是笔者多虑了。使用pull模式,也是三台服务器同时可以观看。

假设我们三台服务器都配置好了。 主播推流没有任何变化,还采用之前的配置。 观众就有了三个可观看地址:
主服务器 https://mywebsite.com/live/my001/index.m3u8
边缘服务器A https://a.mywebsite.com/live/my001/index.m3u8
边缘服务器B http://b.newweb.com/live/my001/index.m3u8
假设三台服务器配置相同,原一台服务器可以承载15个观众,现在三台可以承载45人以上了。而这三个地址如何分配给相应的观众,就不是本文的核心问题了。所以笔者本着比较负责的态度来简单说说算了。 首先我们可以通过DNS的智能线路分配,让来自不同网络位置的观众得到不同IP地址解析。这里隐含的要求就是服务器要考虑这种工作模式,多台主机上要配置相同的主机名,相同的访问路径。 还有就是可以通过CDN服务进行内容转发来实现不同客户访问不同服务器。但是这样一般需要收费服务才能实现智能分配,同时还不能让CDN服务缓存m3u8和ts文件,必须是实时转发。 最后当然有个免费方案,就是如果你有一定的编程能力,就可以自己写一个简单的分发服务。比如写一个页面 http://ccccc.com/cdn.aspx?chan=live&pg=my001 这个页面取参数chan和pg 。在配置表里取出 真实播放地址加工一下 输出301跳转 到 https://mywebsite.com/live/my001/index.m3u8 即可。 再比如我们的直播观看页面上嵌入了一个媒体播放器,播放器里就可以将媒体URL写成 http://ccccc.com/cdn.aspx?chan=live&pg=my001 。 那么至于 cdn.aspx页面里是按照什么规则分发真实地址就看你的喜好了。可以使用计数器,让多个地址均衡的承载观众数量;也可以根据权重和客户位置实时计算,得出最优的播放地址;甚至可以什么都不考虑,直接随机分配。

.net 输出 301 或 302 跳转

五:录像等其他问题

5.1录像问题

我们在之前的服务器配置上开启了录像功能。录像不是必须的,但是经常用到。录像功能可以设置为直接开启、关闭、只录图像、只录音频、只录关键帧、主播推流端控制等等。在record命令上的详细参数可以百度。 录像文件的体积是由推流的码率决定的。一般720p画面,每秒25帧,2000Kbps码率的音视频录像一小时在1.5GB上下。仔细看服务器配置的朋友已经知道,录像文件也是切片存储的。每个切片的大小可以通过多个条件限定,包括最大时长,文件体积,帧数等等。一般用文件体积做限定条件最多。建议录像切片文件体积不要限定的太小,会增加文件系统开销,也不要太大,会对内存和磁盘造成压力,一般2~8MB最好。切片文件还有其他参数可设,用于设定关键帧,时间戳,文件名等等。可以参考文末的参考资料。

5.2 录像的导出和整理

前文说了,录像都是以切片文件存放的。更准确的说是以flv文件格式存储的。(展开一点,这个flv文件用一般播放器都可以直接播放,查看内部包含的是adv视频编码,aac音频编码。似乎跟MP4
的adv+aac一个意思。但是文件真的不一样,很多视频编辑软件比如vegas里,这个flv文件是无法使用的。转码MP4后才可以用。)一个小时的录像可能有100~300个文件之多(看分片文件大小)。这些文件要下载回来留档是很不方便的。要留档还是要合并成一个文件比较好。这个问题看似是小问题,也不算直播主旨的核心问题。但确实是搞直播玩的朋友都会遇到的一个比较头疼的问题。很多合并和转码工具,合并出来的文件都会有缝隙。就是一段一段的切片合并后,每隔一定时间间隔画面或声音会停顿一下,或者跳几帧。有的很明显,有的不太明显而已。 笔者对文件合并和转码进行过很多试验,总结出了一套较效果理想,速度又快的方案。暂时不想说。等笔者爽够了再更新到这里吧。哈哈哈哈

5.3 美颜、特效、导播问题

这几个问题也不算是直播的核心问题。这里简单说说给新手指个路。美颜和特效都属于前期处理,就是在推流之前的事。一般直播服务器不会进行此类处理。(但是不排除可以在直播服务器上增加处理特效的模块。)一般来说美颜和特效都是在视频采集阶段进行处理的。比如通过手机上带美艳功能的录像软件拍摄,比如在OBS软件上直接加载特效滤镜进行编码。要想美颜效果好,特效玩的好,这些东西都有专业设备。在这些前期设备处理好图像以后,再给直播服务推流。
如果再想玩的复杂点,就需要导播的介入了。导播并不是指一个专业的人,可以是OBS这种轻量级的软件,也可以是一个专业的团队。拿简单的游戏主播来说吧,至少是涉及两套视频画面,一个是主播本人的画面,一套是游戏画面,再加上一些美颜、炫彩特效,还可能有背景音乐和主播变声。这种多路资源的合成与调度就是导播干的工作。类似于OBS这种软件可以实现一些简单的资源合并,图像合成。要实现复杂的多路合并于切换,音频的调整与合成。你需要一个专业导播台。简单的导播台可能是这样:

更高级一点的是这样:

退出移动版