本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请订阅2017年《程序员》
作者简介: 张亚伟,齐聚科技技术研究院技术总监,拥有多年跨平台直播开发经验与技术积累。
责编:屠敏,欢迎技术投稿、约稿、给文章纠错,请发送邮件至mobile@csdn.net。


导语:本内容包括A主播音视频数据合成,B主播音视频数据合成,UpServer转发音视频数据、传输协议介绍等小节。其中大量细节都是在第二篇《移动直播连麦实现——Server端合成》中定义的,如视频基本参数定义、显示位置定义、音频合成算法、时间戳定义和使用说明等,为避免重复说明,此处直接使用。更多内容详情见《移动直播连麦实现思路:整体篇》。

当A端合成连麦的音视频数据流后,会把该数据流推送给UpServer,再由UpServer推送给DeliveryServer集群,然后由DeliveryServer分发给移动直播的所有观众。DeliveryServer集群及后续的推送工作不涉及音视频合成,与连麦无关,不属于本文关注的范围,下文不再描述,结构图也仅绘制到DeliveryServer,望大家了解。

A主播视频


A主播端视频合成处理较为复杂,分为三步,第一步是A主播接收所有B主播视频,并进行解码和缓存;第二步是A主播本地视频的采集,与远程视频进行合成、显示等;第三步是编码、打包、发送合成好的视频图像给UpServer服务器。

下面分别对这三个步骤进行详细说明。

接收B主播视频

A主播负责视频合成时,需要先拿到所有B主播的视频数据,而B主播的视频都是由UpServer服务器转发给A端的,如图1所示。此时,所有B主播的视频数据都发给UpServer,再由UpServer转发给A主播;针对B主播的视频数据,UpServer不需要额外处理,按独立数据流发给A主播即可。

A主播需要创建不同的逻辑对象,分别用于接收B1、B2、B3主播的视频数据,并在接收排序后按时间戳拼帧、解码,得到并保存每个B主播的视频图像。

合成本地和远程视频

在直播中,A主播自身也要持续不断地采集视频,按照预定的时间间隔得到每帧本地视频后,与上一步得到的B主播视频进行合成;A主播本地视频采集帧率是十分稳定的,无需考虑丢包、延迟等造成帧率不稳定的问题,故视频合成后的帧率就是A主播本地视频采集的帧率。


图1 A主播接收视频数据流结构图

视频参数、显示位置预定义、视频尺寸的缩放、颜色空间的转换、视频图像数据的存储格式等都与第二篇Server端合成相同,这里不再说明。下面的A主播视频合成流程介绍中继续复用角色定义,B1、B2、B3代表各B主播的图像缓存逻辑对象,A代表A主播本地采集到的视频,合成后的视频图像仍然存储在VideoMixer中。

  1. 首先读取A主播的视频数据作为合成底图,由于是本地采集,无需考虑读取失败情况。
  2. 拷贝A图像上部的58行到VideoMixer中,行数计算公式是640-160*3-1*2-100=58。
  3. 接着读取B3主播的视频数据进行合成,有成功和失败两种情况,如读取成功接第5步,如读取失败也分为两种情况,一是有上一帧,二是没有上一帧。如有上一帧也是执行第5步,如没有上一帧或不存在B3主播则见下一步。
  4. 如读取B3视频失败且上一帧不存在,或者不存在该主播,则直接拷贝A的视频图像161(160+1)行到VideoMixer中。
  5. 如读取B3视频数据成功或有上一帧,则把B3和A主播视频图像进行合成,这里需要逐行合成,每行要分成2段进行拷贝,第一段拷贝A视频数据到VideoMixer中,拷贝列数360-120=240;第二段拷贝B3视频数据到VideoMixer中,120列。
  6. 如读取B3视频数据成功,合成之后还要备份B3的视频数据到指定位置,用于下次读取失败时复用上一帧;当B3主播停止连麦或较长时间卡顿后,还需要清除该数据缓存,避免引起歧义。
  7. 接下来拷贝B3、B2之间间隔部分,即A的视频数据到VideoMixer中,1行。
  8. 循环3-7步过程,把B2、B2与B1之间间隔(A的1行)的视频数据拷贝到VideoMixer中;再循环一次,把B1、B1下部(A的100行)的视频数据拷贝到VideoMixer中。
  9. 使用上述流程,就完成了“A+B1+B2+B3”视频图像合成,合成结果已存储在VideoMixer中。

A主播本地的视频显示也要包括各B主播视频(A+B1+B2+B3),故使用合成好的VideoMixer绘制即可。

发送合成视频

A主播生成“A+B1+B2+B3”视频图像后,需要把该视频帧编码、打包,并发送给UpServer服务器,再由UpServer服务器转发该视频流给各B主播和DeliveryServer,如图2所示。

图2 A主播发送视频数据流结构图

DeliveryServer接收并转发“A+B1+B2+B3”视频流,用于移动直播用户观看连麦视频,后续的发送流程与移动直播相同,不再赘述。各B主播接收“A+B1+B2+B3”视频流,用于显示A主播及其他B主播的视频,对于B主播视频合成和显示的细节,将在B主播视频合成小节中讲述。

总结,在移动直播连麦A端合成视频模式下,A端需要接收和发送大量媒体数据,执行的任务繁重、实现的业务功能复杂,需要消耗更多的CPU资源,所以A主播的手机网络状态和CPU处理性能是最大瓶颈,这点一定要注意。如果可以使用硬件编码和解码,就尽量使用,毕竟就算是最好的手机设备,若手机使用过程中发热量太大,也对业务应用有一定影响。

B主播视频


B主播视频处理过程与A主播相比要简单一些,主要分为发送、接收显示两个部分。发送部分也是采集、编码、打包、发送等,与其他合成模式下的流程一致,仅需注意下视频尺寸为160*120,毕竟视频尺寸小消耗的处理资源也少一些。B主播视频数据流发送的结构图,可参考上一节的图1,这里不再重新绘制。

接下来说B主播接收视频及后续的合成流程,有两种方式,以B1主播为例说明如下:

  • 第一种,UpServer推送合成好的视频“A+B1+B2+B3”给B1,与推送给普通观众的视频流相同,如上一节的图2所示。此时B1需要把本地采集到的视频合成到“A+B1+B2+B3”顶层上,替换掉原有的B1视频图像即可,从本地视频显示的实时性要求来看,这步替换是必须要做的。

  • 第二种,UpServer推送合成好的视频“A+B1+B2+B3”给B1,同时UpServer也把B2、B3的视频数据独立推送给B1,如图3所示。此时B1主播收到独立的3路视频数据流,需要把本地采集到的视频及B2、B3主播视频,合成到“A+B1+B2+B3”顶层上,替换掉A主播已经合成好的B1、B2、B3视频图像。

图3 B1主播接收视频数据流结构图

先描述下以上两种视频合成方式的细节。第一种方式与UpServer合成模式下的B主播视频合成流程完全相同,细节不再复述。而第二种方式B1的处理流程更为复杂一些,需要把“A+B1+B2+B3”、B2、B3的视频数据都解码,然后按照音视频同步的顺序读取和合成,得到的结果是新的合成图像“A+B1(新)+B2(新)+B3(新)”,视频合成流程与A主播视频合成类似。

接着比较下两种视频合成方式的优缺点。第一种方式以前就建议过,从功能和业务角度来说,可以满足需要。而第二种方式的优缺点更明显一些,缺点是需要处理的内容更多了,包括B2、B3主播视频的解码、同步和合成等,需要消耗更多的系统资源;优点也有以下两点:

  1. 与第一种方式相比,B2、B3主播视频的实时性更好一些,毕竟使用UpServer直接发送的B2、B3视频数据进行合成,比使用A合成好的B2、B3视频数据,处理延迟和网络延迟占用的时间可以明显降低。
  2. B2、B3主播的音视频同步效果会更好一些。一般情况下B1需要独立接收A、B2、B3主播的音频数据,当B1播放B2的音频、视频时,由于两路数据流都有,所以同步播出的效果会比较理想;而使用方式一,B2视频是由A合成好的,当B1主播播放B2的音频时,无法和B2视频进行同步。

处理延迟时间是指A合成B2、B3视频消耗的时间,包括解码、合成、编码,打包等;网络延迟时间是指B2、B3的视频数据,要先由UpServer要发给A,A完成视频合成后再发送回UpServer网络传输使用的时间。这两个时间加在一起,在处理比较好的情况下,估计也需要1秒以上,此处还不考虑网络比较差导致的丢包、网络中断导致的卡顿情况,毕竟网络质量差,连麦的体验效果也必然非常差。

使用方式一,A主播合成的“A+B1+B2+B3”视频时间戳必然是A主播的,可以很好的和A主播音频进行同步,但不能和独立的B2、B3主播音频数据时间戳同步。由于延迟占用时间,A主播合成的B主播视频必然比独立发送的B2、B3主播音频更晚到达B1主播,导致B1主播播放B2、B3音频时,与B2、B3视频出现不同步的可能性很大。

总结,以上两种方式,方式一的处理流程简单一些,消耗的资源也少,而方式二处理流程更为复杂,且消耗的资源也多;但在用户体验效果方面,方式二会更好一些,结论是如果非常重视用户体验,且消耗的资源可以承受则使用方式二,否则使用方式一。如果是第一次实现,建议先使用方式一实现,待收到更多效果反馈后,再确定是否改为方式二,毕竟方式二仅对B主播的用户体验改善有效,而与移动直播的众多接收用户体验效果无关。

UpServer


这个小节是否需要,笔者也是反复进行了考虑,最终还是确定保留下来,为什么犹豫不决呢?原因是在A主播音视频合成模式下,UpServer转发工作相当简单了,仅需要按设计要求,把每路音视频数据转发给相应的对象。且媒体数据转发的流程都已在各小节进行详尽介绍和绘图说明了,故感觉增加本小节的意义不大。

然而,如没有本小节也总感觉文章不够完整,毕竟UpServer是移动直播连麦的重要组件,其负责的转发媒体数据工作也是连麦实现的重要环节,故决定单独列出。

表1列出了UpServer转发各媒体数据的源、目标等,供大家整体参考。


表1 UpServer转发源目标说明

A主播音频


A主播音频与视频处理流程类似,先介绍其步骤,第一步是A主播要接收所有B主播音频,并进行解码、合成和播放;第二步是A主播本地音频的采集,与远程音频数据进行合成;第三步是编码、打包、发送合成好的音频数据给UpServer服务器。

需要注意的是第二步和第三步,当A主播负责合成音频时,需要生成两路音频数据流,都推送给UpServer,一路是“A+B1+B2+B3”,用于移动直播用户收听连麦语音,另一路是A本地音频,用于B1/B2/B3主播收听A主播音频。这样做的原因在上一篇文章解释过,在用户体验上,B主播肯定不希望听到自己的声音(类似回音),即B1/B2/B3主播都不能使用合成好的音频数据。

下面分别对这三个步骤进行说明。音频合成算法,仍使用上篇文档介绍过的直接相加算法,该算法简单高效,且适用范围还不错。

接收、合成和播放B主播音频

A主播负责音频合成时,需要先拿到所有B主播的音频数据,而B主播的音频数据都是由UpServer服务器转发给A的,结构图与第一节图1相同。此时,所有B主播的音频数据都发给UpServer,再由UpServer转发给A主播;针对B主播的音频数据,UpServer不需要进行额外处理,直接发给A主播即可。

A主播需要创建不同的逻辑对象,分别用于接收B1、B2、B3主播的音频数据,并在接收后按包序号排序和按时间戳顺序解码,之后合成所有B主播音频数据。继续复用角色定义,各B主播音频缓存对象分别用B1、B2、B3代表,合成后的音频数据存储在AudioMixerB中。

B主播音频数据合成的流程如下。

  1. 先找到可以合成的音频数据,若没有就不必合成了。若只有一路音频数据,也无需合成直接拷贝其到AudioMixerB中即可。
  2. 音频数据合成必须有两路以上,一般是先找B1主播再找B2主播,依次类推,直到找到可以合成的所有音频数据。
  3. 通过循环遍历所有采样点,把各B主播的音频数据直接相加,结果放到AudioMixerB中,即完成了音频数据合成;直接相加算法需要对音频数据溢出进行保护,务必注意。

最后是播放B主播合成好的音频数据(B1+B2+B3),与一般的移动直播用户播放方法相同。

合成本地和远程音频

在移动连麦直播中,A主播自身也要持续不断地采集本地音频,之后与上面合成好的音频数据(B1+B2+B3)再次合成,供广大直播观众收听。合成方法与上面相同,结果存储在AudioMixerA(A+B1+B2+B3)中。

发送合成音频和独立音频

发送音频数据给UpServer是A主播音频处理的最后一步,要分别把A主播自己的音频数据,合成好的音频数据(A+B1+B2+B3),编码、打包、发送;即使用两个逻辑对象分别存储和维护独立的音频数据与合成的音频数据,如图4所示。


图4 A主播发送音频数据流结构图

这里有需要特别注意的一点,与一般的移动直播情况不同,移动直播连麦A主播合成音频,在与UpServer建立媒体数据传输通道时,需要建立两个音频通道且可以同时发送数据。在A主播和UpServer之间建立两个音频通道时,交互信息一定要做好,使UpServer可以很容易的区分,哪路音频数据是发给B主播的,哪路音频数据是发给DeliveryServer的。

B主播音频


B主播音频处理过程与A主播相比要简单一些,仍然是分为发送、接收播放两个部分。首先说B主播的音频发送,其也是由采集、编码、打包、发送等几个环节组成,以B1主播举例,其直接把音频数据推送给UpServer即可,与其他合成模式下的流程一致。

在UpServer转发B1主播的音频数据时需要进行广播,分别发送到A主播、B2、B3主播处,如图5所示,只有这样做才能使每个主播合成声音时达到最理想的效果,具体的原因见以前分析。第二节讲UpServer推送B1主播视频时有两种方式,其第二种是把B1主播视频推分别送给A主播、B2、B3主播,这种方式与B1主播音频数据推送的形式比较接近。


图5 B1主播发送音频数据流结构图

接下来说B主播接收音频及合成流程,以B1主播举例,由于UpServer已向其转发了A主播、B2、B3主播的音频数据,如图6所示,所以合成流程清晰明确。B1主播音频合成与播放流程,可参考上一节的A主播合成所有B主播音频数据及播放流程,它们之间的差异很小,不再重复。


图6 B1主播接收音频数据流结构图

传输协议


在移动直播连麦的过程中,A主播、各B主播、UpServer之间需要非常及时的媒体数据交互,故网络传输协议的选择非常重要,当前常用的有RTP、RTMP、HLS等,本节将对这三种协议进行比较分析,从而给出建议。

RTP和RTMP都是设计用来进行实时媒体数据通信的网络协议,能很好地支持音视频传输和数据通信,而HLS协议则是把媒体数据进行切片后,使用 HTTP 渐进下载方法实现的,HLS协议是准实时的。一般情况下,RTP协议底层使用UDP包进行传输,RTMP使用TCP或轮询HTTP连接进行传输,HLS使用HTTP(TCP)连接进行传输。

UDP、TCP(HTTP)协议之间的优缺点相信大家都已非常了解,故不再阐述,下面讨论下在移动直播连麦各终端之间,协议选择的一些建议。

首先排除HLS协议,该协议的传输实时性与切片大小直接相关,切片大延迟太长,无法满足连麦的实时性要求,而切片小维护成本高,得不偿失只能放弃了。

接着分析RTMP和RTP协议,第一步先比较网络资源消耗方面,RTMP使用TCP连接传输媒体数据,为维护TCP连接,一般比RTP使用的UDP消耗网络资源更多一点,尤其当网络条件转差后,传输同样的数据消耗的资源跟多,延迟更大,所以网络质量比较差时,使用UDP收发数据包的RTP协议更有优势。

第二步比较复杂网络结构的适应性,在穿透防火墙和跨越复杂网络方面下,可以使用HTTP请求数据的RTMP协议更有优势;而使用UDP协议传输数据时可能受到防火墙阻止,或者异构网络的限制,各种特殊现象的处理需要增加很多额外工作。

第三步比较网络处理功能实现难度,由于UDP协议传输数据易丢包、乱序,为提高用户体验,需要使用缓冲池、补包、按序排列等技术手段进行保护,必然增加处理难度。TCP协议保证数据不会丢失和乱序,最多也就是传输慢或网络连接断开,所以上层处理媒体数据时不需要考虑重传、排序等,难度明显下降。

另外,在媒体数据分发CDN层面,当前RTMP协议已得到了很好的支持,而RTP协议支持尚现不足,在外部资源复用方面,也是一个需要考虑的因素。

总结,在网络资源使用方面UDP包传输数据的适应能力更加宽广,带宽好或差都可以达到很好的实时性,但其开发难度也比使用TCP(HTTP)更大。个人建议,如果追求极致效果,且有足够强大的研发团队,建议移动直播连麦时,各主播之间使用RTP(UDP)协议实现媒体数据传输;如果开发力量一般且追求产品快速上线,建议使用RTMP(TCP)协议开发。

后记


通过以上介绍,相信读者对移动直播连麦的A端合成实现细节已基本了解。针对A主播合成,笔者个人看法是支持的,是否使用还请自行决定,列举已知的特点如下。

  • 复杂度:该模式下A主播需要把本地采集的音视频数据,与UpServer转发的音视频数据进行合成,实现复杂度较高,但考虑到连麦时A主播的业务逻辑本就复杂,复杂度的适当增加也是可接受的。
  • 主播端性能: A主播实现复杂度高,必然要消耗更多的系统资源,需要依赖比较好的硬件设备,支持硬件视频编解码的移动设备应当是前提条件;同时,直播软件的性能优化也是研发团队需要特别关注的。
  • Server性能: UpServer仅实现按要求转发媒体数据功能,无需参与音视频的解码、合成、编码等,CPU使用少,业务应用成本大幅度下降了。
  • 时间戳: A主播合成音视频数据,生成的媒体数据流都以A主播本地时间戳为准,故在远端不存在参考歧义,观众方更易实现音视频同步。

了解最新移动开发相关信息和技术,请关注 mobilehub 公众微信号(ID: mobilehub)。

移动直播连麦实现——A端合成相关推荐

  1. 移动直播连麦实现——Server端合成

    虽未经允许,我还是转载了 本文为<程序员>原创文章,未经允许不得转载,更多精彩文章请订阅2017年<程序员>  作者简介: 张亚伟,齐聚科技技术研究院技术总监,拥有多年跨平台直 ...

  2. 移动直播连麦实现思路:整体篇

    导语:本文专为介绍移动直播连麦实现架构和思路而写,介绍了移动直播连麦的整体情况.各种实现架构和优劣比较等,包括连麦介绍.角色定义.连麦特点要求,合成思路介绍.各种合成方式比较等几个小节. 移动直播连麦 ...

  3. 直播带货app源码,实现直播连麦和PK

    一.概述 连麦:是指直播带货app源码中,由观众向主播发起连线请求,在主播和该观众之间建立低延迟的通讯链路,而其他观众可以看到"主播+连麦观众"的合成音视频内容. PK:是指直播过 ...

  4. WebRTC + 直播 + 连麦 = AnyRTC ?

    WebRTC + 直播 + 连麦 = AnyRTC ? 看到这个题目,您似乎瞬间就懵逼了,小编是在梦游中写作文吗?这四个词有什么联系?WebRTC是Google的, 直播是现在最火的,连麦是直播中略吊 ...

  5. 解读直播连麦与点播加密

    摘要: 本文PDF摘自阿里云视频服务高级产品专家徐刚于10月13日在2016年杭州云栖大会上发表的<视频服务特色解决方案--直播连麦与点播加密>. 近年来,直播热潮持续升温.有需求就会有变 ...

  6. 实现连麦_微信年底放了个大招,视频号重磅升级,打赏直播连麦美颜抽奖齐上...

    期待已久的视频号连麦功能来了.这次来的不仅有连麦功能,还有视频号打赏的微信豆体系,创作者想要的入口也有了.让我们一起来看看有什么新功能吧!太长不看版本:「附近的人」变「附近的直播和人」连麦上线,还有美 ...

  7. 实现连麦_微信重磅更新,视频号直播连麦打赏美颜上线,新增巨大流量入口

    12月23日晚,微信迎来重大改版!在最新7.0.20版本的微信中,视频号大招不断,不仅上线了连麦功能,支持美颜瘦脸.打赏等功能. 此外,微信还给视频号开放了两个重大入口,包括微信个人名片和" ...

  8. 基于anyrtc的sdk实现直播连麦互动

    基于anyrtc的sdk实现直播连麦互动 前言 1.由于粘贴了较大的代码,造成内容比较长,可能会花费您较长的时间.  2.项目里面没有做权限判断,所以如果发现有页面发生崩溃可能是权限没有打开,请打开权 ...

  9. anyRTC,一站式低延迟直播连麦解决方案

    全新的一站式"低延时直播连麦"解决方案,主打直播连麦和多画面特效,通过移动直播SDK打造跨平台一对多.多对多的超清酷炫直播场景.anyRTC音视频直播连麦解决方案方案包括,视频直播 ...

最新文章

  1. Operation Queues并发编程
  2. php 尾递归,关于尾递归的使用详解
  3. [导入][转]跨越域的Cookie
  4. 配置环境将win32项目移植到Android
  5. Python科学计算扩展库NumPy之np.array()与np.asarray()区别
  6. 前端获取浏览器标识_浏览器缓存机制
  7. 高性能计算中并行的概念理解
  8. OpenGL GPU粒子
  9. 网站三级分销数据库如何设计,简单案例
  10. 华为Mate 30 Pro曝光:双曲面刘海屏 支持3D人脸识别
  11. notepad++ python指定anaconda环境以及代码补全设置
  12. pyspark的ALS协同过滤推荐算法-小结1
  13. could not extract ResultSet/could not execute statement
  14. 学以致用:让visualstudio爱上sublime
  15. PHP中的的一个挺好用的函数 array_chunk
  16. [LeetCode] Rotate Array
  17. 图像特征的匹配-OpenCV3.0
  18. 注塑车间维修师傅如何快速解决9种注塑机故障?
  19. The type of the expression must be an array type but it resolved to ListObj
  20. 前沿Perspective | 空间转录组数据分析方法最新进展

热门文章

  1. html ul超出div,解决ul宽度超出div宽度常用解决办法
  2. 一起学设计模式 - 工厂模式
  3. 雅思口语考试分享(北京)
  4. CSS简笔画:纯CSS绘制一辆婴儿车
  5. pythonsqrt取整函数_python取整函数
  6. 一直没发现的磁盘管理功能
  7. 解决Hbuilder打包的app返回键直接退出
  8. 【Android -- RxJava】RxJava2.0 教程(七),如何使用 Flowable
  9. 正则自编码器之稀疏自编码器
  10. 计算机操作系统的同步和异步,操作系统中的同步和异步有什么区别?分别应用在什么场合?...