# 直播功能实现
随之直播电商的快速发展,越来越多的平台开始往自己的平台中嵌入直播功能,如果我们要做一个直播功能该如何实现呢?如今,各大厂都推出了自己的直播解决方案,我们可以拿来借鉴或者直接使用其方案,直播的底层技术我们可以不必关心,但是整个直播的业务方案我们还是要有一定的了解,本文就让大家对直播功能的实现有一个快速的认识和了解。
# 概述
直播技术的基本框架主要由采集端、流媒体服务器(服务端)以及播放端三部分组成。这当中前端的主要工作内容是在采集端和播放端。
采集端是主要负责音视频的获取,这主要靠前端获取摄像头和麦克风来实现,采集好后对这些数据源进行预处理,如美颜、添加水印等,来增强直播效果满足特定需求。然后再对采集好的数据进行编码和封装适合直播的格式和传输协议进行推送到流媒体服务器上。
播放端顾名思义就是前端拿到视频流进行播放,其实直播视频流的播放和普通视频播放一样,就像video一样,直接用播放器播放视频流地址进行了,只不过要根据不同的视频流格式使用不同的播放器进行播放,不同的平台也会有不同的视频流播放格式。
而流媒体服务器也就是服务端则负责接收视频源数据进行转码、混流、录制、转推、分发等操作,当然这中间有很麻烦的处理过程,一般都是使用成熟的厂商服务进行解决,自己的前后端同学只需要关注直播的业务逻辑和使用哪种方案更合适就可以了。
# 推流与拉流
在整个直播过程中,有两个重要的概念需要搞清,就是推流和拉流,搞懂他们就对如何实现直播功能就有了一个大概的了解。
推流
推流是指将采集端收集的数据,比如使用手机,摄像机采集的音视频画面,通过特定的协议传输到服务端的过程。就是用什么设备获取画面,用什么方式上报上去。下面是常见的采集方式和传输协议。
推流协议:
RTMP 协议:主流的直播推流协议,延迟高,但平台兼容性好,操作简单,传统的单向推流,适合稳定网络。
SRT 协议:高质量、抗弱网抗丢包强、延迟低、安全、单向推流,适合专业公网推流。
WebRTC 协议:超低延迟,实时通信,浏览器原生支持,适用于实时互动直播,视频会议等。
混合协议:三者协同工作,推流、分发、实时互动,打造高质量直播应用。
推流方式:
移动端手机推流,通过第三方软件或直播SDK使用摄像头采集视频进行推送。主要用于个人直播。
台式机或笔记本,通过第三方软件使用使用摄像头或桌面录屏进行推送。如OBS(推荐)、XSplit、FMLE 等。主要用于录播回放操作。
视频采集设备:使用专业设置,如具备HDMI 或者 SDI 输出接口的高清摄像机类设备,接入编码器进行推流。主要用于直播间进行直播。
云推流/云端导播:将多路信号进行推送。用于大型活动、多地联动直播、企业级直播。
推流时我们一般不用太关心如何实现这些协议对应的推送方式,成熟的厂商会有提供好对应方案,我们只需拿来使用,参数配置好就可以了。比如腾讯提供的 云直播 (opens new window) 和 实时音视频 (opens new window) 两种技术方案都可以实现直播推流,并且还可以使用不同的协议在不同的端进行推流。
拉流
推流成功后,服务端会对流进行转推和分发,转成我们可以播放的协议地址,我们拿到对应的地址可以在不同的客户端播放,比如网页、APP、小程序进行播放就是拉流操作。
拉流协议:
直播协议 | 优点 | 缺点 | 播放延迟 |
---|---|---|---|
FLV | 成熟度高、高并发无压力 | 需集成 SDK 才能播放 | 2s - 3s |
RTMP | 延迟较低 | 高并发情况下表现不佳 | 1s - 3s |
HLS(m3u8) | 手机浏览器支持度高 | 延迟非常高 | 10s - 30s |
WebRTC | 延迟最低 | 需集成 SDK 才能播放 | < 1s |
播放地址:
因拉流协议的不同,所生成的流地址也不同,播放这些地址的播放器也会不同,我们要根据用户使用需求和播放器的兼容性来判断使用哪种协议最好,下面是各种协议对应的地址格式和各自的优缺点。
HLS:苹果特有的格式(m3u8),延迟较高(10s+),但兼容性好,IOS和高版本安卓都支持,也可以使用hls.js来支持其他平台进行播放。
地址格式:http://xxx.xxx.xxx.com/xxx.m3u8
m3u8可以直接使用video标签进行播放,为了兼容性可以使用hls.js进行支持低版本。
RTMP:很少用于拉流端,主要用于推流端。
地址格式:rtmp://xxx.xxx.xxx/xxx/xxx
浏览器无法直接播放,需要集成播放器插件。
FLV:由哔哩哔哩开源的播放器,延迟低,纯原生JS开发,主要用于PC端和H5直播,对原生APP不友好,IOS不支持。
地址格式:https://xxx/xxx/xxx.flv
播放需要集成 Flv.js (opens new window) 插件进行播放。
WebRTC:和推流一样延迟低,适用于实时直播、连麦互动场景,主要用于APP直播应用。
地址格式:webrtc://xxx/xxx/xxx
播放需要集成插件,无法直接播放,不过厂商都有提供播放器插件。
从这可以看出,没有哪种方式是一定完美的,选择哪种方式要根据应用场景来,比如,PC端游戏直播,像虎牙、斗鱼这种选择对浏览器支持比较好的FLV格式进行播放;又比如在移动端上对延迟没有高要求,不需要互动的体育直播,直播回放等就可以使用HLS进行播放;如果对延迟要求比较高,需要实时互动,像抖音、快手直播等,就需要WebRTC格式进行播放。当然,我们拉流并不是只使用一种格式,也可以多种格式混合使用。
通过上面分析,我们要弄懂一个概念,推流和拉流之间没有太大的关系,主播用什么形式和用什么协议去推流都只是主播往服务端去推流,只要把流推到服务端上就行,至于拉流用什么协议和什么形式去播放那就要看观众端的支持了,不要纠结直播用什么推,拉流就一定用什么拉。
推流和拉流成功,从主播开播到用户观看,直播最基础的功能也就实现了,其他功能都是基于此功能在这上面实现的。
# 即时通信IM
用户拉流成功,直播间有了画面,那用户和主播之间该如何进行互动,这就需要另一个功能 即时通信IM (opens new window) 了,主播与观众之间的所有互动,比如,实时评论,小黄车、弹商品卡片、点赞、送礼物等,都是靠它来实现。
直播间互动和推拉流是两套东西,推拉流负责播放画面,IM负责直播间的各种操作,他俩只在开关播等异常情况下才相互通知操作,其他情况所有操作都靠IM来通知,用户进入直播间就相当于进了一个群,在这个群中,主播是管理员,可以发群通知来上下架商品、发红包等,用户可以在群里发言评论,抢红包,可以一对一,也可以一对多进行相互通知。不论直播间功能多么复杂其基础逻辑都是这些,都是在此基础上的累加。
# 直播间搭建
主播调用本地摄像头采集音视频推送视频流,并告诉后端开播,后端根据厂商回调生成直播间列表和对应的IM群,用户访问应用,点击进入直播间加载拉流地址播放视频流和加入IM群,并根据群资料展示对应的信息,这样从开播到看播一整条链路就实现了。下面来讲用户进入直播间后各个功能如何实现和对应的难点梳理。
1、多直播间切换
有多个直播间同时存在时,直播间切换我们借助swiper轮播图进行切换,通常IM全局就只需创建一个实例就可,切换时只要进群退群操作就可以,不用担心额外性能问题,但播放视频流就不同了,如果同时把所有的直播间视频加载出来,会有多个实例,性能会吃不消。
我们需要保证在消耗性能最小的情况下,又能快速的把直播间加载出来。现在通用的做法就是只保留三个swiper,设置循环滚动,不论有多少个直播间,这三个swiper所初始化的实例一直存在,只切换其加载的数据,直播间数据只在这三个swiper中循环替换加载,滚动一次替换一个数据源,不但可以实现上下滚动,也可以进行预加载。
这实际上借助了虚拟列表的实现思路,不论直播间列表有多少,只保留3个播放器实例,第一次进入页面会先加载好三个实例,然后每次切换,先播放当前直播间,然后把下一个swiper的数据播放地址给替换掉,这样再次切换时就重复此动作进行数据源切换,反方向滚动也是如此。只需要在实际直播间列表的第一个和最后一个的时候进行限制就可以了。
在此基础上,可以衍生出多种操作,比如向下无限滚动,只要在加载到最后几个的时候,去请求新的直播间数据添加到原列表中就可以,或者无限循环滚动,直播间原列表也变成动态替换,从头到尾相连接。
2、直播间评论
直播间评论实现其实很简单,只要接入IM SDK (opens new window),就可以通过IM发送消息了。评论区就固定在直播间某个位置,在滚动区域监听IM消息事件,判断有没有新消息过来进行滚动操作,实时进行渲染,至于是文本还是图片消息,只需要根据消息类型判断展示不同的内容就可以了。这里一切都是通过IM消息进行通知,IM还可以在控制台实现关键词过滤,管理员禁言等功能。
3、商品上下架
商品上下架它不像评论直接调用IM的方法,它不仅需要让当前在直播间的人可以随时看到上架的商品,还需要让后面进入直播间的人也能看到。这种功能可以通过修改IM群资料来实现,我们通过后台调用IM修改群资料的接口修改群资料,修改后,IM会自动给所有的群成员发送一条自定义消息,这条消息中可以保存商品的信息,前端在接收到这个消息后来展示对应的商品,并且这个被修改的群资料会一直被保存,当其他人再次进入直播间时,前端查询群资料后自动上架商品。这样,就实现了既能实时更新信息,又能一直保留信息的功能了。
直播间的小黄车、弹商品卡片、发福袋、发红包、置顶评论、禁言、连麦等都是通过修改群资料来实现。
4、点赞
点赞功能需要设计给我提供几种不同的点赞小图标,我们根据屏幕双击次数和点击位置,来往一个数组中随机push一个小图标,然后把这些小图标在对应的位置渲染,渲染出来后去执行一个几秒钟的渐变消失的动画,等动画执行完成后,把数组里的元素给删除掉,这样一个一直点击显示一直消失的点赞效果就实现了。当然,点赞完成后要记录点赞的次数上报给后端进行更新群资料。
5、送礼物
送礼物功能主要有两个核心问题,一个是礼物特效播放的问题,一个是在礼物数量多的情况下,如何合理丢弃问题。
1、礼物特效播放
播放的礼物特效有很多种格式,常见的特效文件格式有下面各种:
webp格式小程序和原生都支持,但是IOS兼容性差,比较卡。
svga小程序和原生都支持,但是文件比较大,耗性能,播放容易卡顿。
gif小程序和原生都支持,但是效果不好比较糊,文件比较大,无法获取结束事件。
pag小程序和原生都支持,但是播放久了也是容易卡顿,耗性能。
mp4视频,没有兼容性问题,但是不支持透明底,无法进行覆盖。
双通道透明mp4,主流直播APP使用方案,通过特定方式制作出mp4视频文件,播放效果好,不卡顿,但是播放需要特定插件,小程序支持有限。
从上面可以看出,几乎所有文件都伴随一个播放卡顿的问题,这也是为什么最后会使用双通道透明mp4视频融合技术,它是经过编译的特殊视频文件,通过特定编码处理成透明的播放效果,也就解决了播放卡顿的问题,目前有腾讯Vap (opens new window)、YYEVA (opens new window)、AlphaPlayer (opens new window)这几个插件提供使用,他们提供播放了SDK以及制作对应视频的工具。
特效制作与格式转换网站:https://eff-tools.17ae.com/ (opens new window)
2、合理丢弃原则
正常情况下,播放礼物我们按照顺序一个一个播放,但是礼物特效是有播放时间的,如果直播间人数过多,送礼物会一直堆积在播放栈中,一直播放也会导致手机发热发烫卡顿,所以,我们要在多人多礼物的情况下,合理丢弃礼物,只播放关键的礼物特效,达到节省性能和快速展示的效果。
一般我们按照顺序给礼物添加到播放队列中,并给每个礼物设置播放顺序、时间、权重、所属人这些属性。然后给这个队列设置一个长度阈值,当大于这个阈值时,就需要按照权重和丢弃原理动态替换其中礼物的位置。
如果同一个人,同一时间内,连续发送一个礼物,如果这个礼物在队列中就都累加到同一个上面,不在队列中就重新添加到队列中排队;如果同一个人 ,同一时间内,连续发送多个礼物,就需要按照权重去替换此人在队列中的礼物。如果多个人,同时发送多种礼物,在某一个人的礼物权重替换完后,再按照所有人的礼物的权重再重新替换一遍,先比较同一人的,再比较所有人的,循环替换。
如果考虑的再完整一点,需要把丢弃的礼物也保存一个队列中,按照顺序在评论区和侧边礼物栏进行展示出来,防止出现用户刷礼物了却没有展示的问题。
6、直播连麦
连麦功能分为主播端、连麦观众端、未连麦观众端,主播和连麦观众是通过实时音视频进行连麦通话,连麦观众观看的不再是主播的拉流画面,而是替换成与主播的实时音视频画面,他俩连麦成功后需要经过后端进行混流操作,把连麦后的画面混到原来主播的拉流地址中,未连麦用户看到拉流地址一直未变。
# 直播中控台
主播开播后,直播间通常都会有一些群管理员禁言、商品上下架、发红包、发福袋等操作,主播在直播中肯定来不及去处理,所以在主播开播的背后,还会有一个直播中控台让助播对直播间进行管理,它显示的画面和主播一样,实时对直播间的各种状况进行处理。
直播中控台它是一个后台管理系统,它可以和主播使用同一个账号进行登录,可以对直播需要用到的商品、福袋、红包等进行管理,在开播前做好准备。
# UniApp原生应用直播方案探索
如果在uniapp开发的App应用中开发直播功能会有很多限制和兼容性问题,无法用纯web前端实现,需要借助uniapp中的各种 原生插件 (opens new window) 实现才行,这些原生插件不能在.vue文件中使用,需要使用.nvue文件进行开发,此文件有很多限制,开发起来很不方便,很多属性效果无法使用,使用uniapp开发原生直播应用请慎重考虑,最好使用原生或者Flutter开发。下面是借助腾讯实时音视频与即时通信SDK搭建的一套直播应用(云直播没有提供uniapp方案),仅供参考。
1、直播推流
通过 腾讯实时音视频TRTC (opens new window) 进行推流,其提供了uniapp版的原生插件供使用,下载此插件,按照使用方法放到本地项目中,重新制作自定义基座方可使用。这个插件可以打开本地视频和音频,打开后进房就可以把流推上去了。
开播步骤:
获取TRTC各种配置参数。
引入插件,创建 TRTC 实例。
打开本地音视频预览。
enterRoom进入房间,进房后会自动推流。
上报后端开播创建直播间。
参考文档:TRTC Demo(uni-app) (opens new window)、TRTC SDK 的接入(uni-app) (opens new window)、腾讯云实时音视频SDK (opens new window)、TRTC_UniApp (opens new window)、原生插件使用说明 (opens new window)
2、美颜插件
美颜也是使用腾讯提供的美颜插件,在腾讯的控制台打开美颜功能,提供美颜插件对应的鉴权Key秘钥,在代码中鉴权成功后美颜效果会自定生效在本地视频预览中,在哪设置美颜的参数它都会生效,不需要其他的联系。
设置步骤:
引入美颜特效插件
复制美颜资源,只需复制一次
获取鉴权key和秘钥进行鉴权
鉴权成功,设置美颜特效
参考文档:美颜特效使用方法(uni-app) (opens new window)、美颜特效SDK(uni-app) (opens new window)
3、直播拉流
直播拉流使用WebRTC协议进行拉流,由于腾讯播放器SDK (opens new window) 未提供uniapp版本的插件,所以得需要自己开发原生插件,可以参考文档 腾讯云LiteAVSDK文档 (opens new window) 和 原生插件开发文档 (opens new window) 自己开发一下IOS和安卓版本的插件。或者去插件库购买相应的原生插件,推荐这个 腾讯云直播播放器 (opens new window)。
还有一种纯前端实现的方式,但是这种方式可能会出现卡顿问题,也是借助腾讯播放器的Web版本,在uniapp中使用 renderjs (opens new window) 进行引入Web播放器SDK进行播放。
4、即时通信IM
IM的引入很简单,就是一个JS SDK,直接引入使用,不需要原生插件,直接参考 Web&小程序&uni-app集成 (opens new window) 文档进行安装就行了。
连接步骤:
按照引入IM插件
初始化IM实现
用户进直播间后进行登录IM
用户进直播间后进行进群
监听IM的各种消息事件
退出直播间用户退出群聊
退出直播间用户退出登录
参考文档:腾讯云即时通信 IM (opens new window)、 IM SDK文档 (opens new window)、Web&小程序&uni-app集成 (opens new window)
5、特效礼物
在uniapp开发的原生应用中特效礼物播放没有一个很好的解决方案,目前最优的解决方案是安卓上使用 Vap插件 (opens new window) 进行播放,IOS上使用 pag插件 (opens new window) 进行播放,但是都无法满足全部机型的兼容,更别说荣耀和纯血鸿蒙的机型。这个礼物播放是最占用手机内存和耗性能的,一但某些逻辑处理不好就会导致直播间卡顿、崩溃,App闪退。所以,在需求允许的情况下尽量减少大型特效礼物的播放,或者自己根据双通道mp4方案,开发安卓和IOS原生插件。
6、直播连麦
连麦与主播推流使用同样的方式进行,连麦观众通过 TRTC (opens new window) 打开本地音视频预览,然后进入房间与主播进行音视频通话,主播与连麦观众两边相互推流和拉流,监听对方进房播放对方的远端流,就相当于视频会议。
进房成功后,后端调用TRTC接口进行混流操作,未连麦用户观看的主播流画面会自动更新连麦双方的画面,进行无感观看。
大文件分片上传 →