短视频APP架构设计与实现

本文来自全民快乐研发高级总监展晓凯在LiveVideoStackCon 2018讲师热身分享,并由LiveVideoStack整理而成。分享中展晓凯介绍了短视频APP场景中视频录制、编辑、保存模块的相关技术与实践,以及变速不变调算法W-SOLA的实现。

大家好,我是展晓凯,今天与大家分享的内容是短视频APP的架构设计。2016~2017年短视频App呈现爆发式增长,并在大多数人的生活中扮演着十分重要的角色。短视频APP的用户停留时间长、黏性大、使用频次高,其次日留存、7日留存甚至是月留存同样也非常高,而大多数公司在进行自己产品APP的开发时,也会在其中集成垂直分类或一些社区化的短视频功能。接下来将介绍如何设计一个短视频APP架构并在对于关键细节进行分析与实现。

  1. 短视频APP的场景

一个短视频产品应该有哪几部分组成呢?第一个模块也是最重要的,是包括视频录制、剪辑、保存在内的视频生产功能。短视频APP势必需要为生产者表现其优秀的工具属性——让使用者以更低成本生产短视频;有视频生产就必须有视频消费,这也是短视频APP的第二个模块。这里的消费是指用户消费内容而非真正地花钱或送礼,我们期待的是用户点击某一个短视频,在看完短视频的内容后认为这是一个非常不错的作品并为其点赞、评论、分享甚至打赏,这个过程相当于消费者与视频的生产者产生了一定的关注关系,可以为让App具有社交属性;而在服务器端,包含运营后台(运营后台可以让内容运营人员会对视频内容进行标注、推荐从而有助于视频精准推荐与精品推荐)、人物画像,智能推荐系统用于分发Feed流、视频播放(从Feed流中跳转到一个短视频详情播放页面,其中的秒开与流畅程度依赖于CDN与播放器等组件的配合)、送礼打赏(包括消费与充值提现系统)、评论转发(短视频APP消费属性之体现,包括转发内容至第三方APP等,可有效提高内容以及用户转化率)。

而在业务服务器端,当生产者生产出一个视频并将其上传至业务服务器后,系统会入库这条短视频的Matedata并存储到数据源中,真正的短视频文件则会安放在存储中。这里需要注意的是,一些小运营商的DNS缓存会降低上传成功率,我们需要通过技术优化来克服此类问题。当某用户消费此短视频时,通过使用CDN对整体过程进行加速来提升消费体验,同时CDN也帮我们提高缓存命中率节省带宽成本。而用户经常消费的一些高质量视频内容离不开可靠的运营后台,运营后台可帮助视频生产者完成编辑、推荐、分类等工作。除此之外还有人物画像与智能推荐,平时我们使用的各种软件,无论是用来购买商品的淘宝、京东还是用以获取新闻的今日头条、网易新闻,都会根据用户行为构造人物画像并通过人工标注或算法生成等方式将这些内容进行标注,从而获知用户感兴趣的内容并进行精准化推荐,人物画像与智能推荐系统对大多数APP来说都是一个非常重要的系统,可有效增大用户黏性。

  1. 短视频生产

短视频生产包含视频录制、视频编辑、视频保存三大模块。视频录制包括视频预览、伴奏播放(例如学猫叫等需要用户对着伴奏完成手势或模仿嘴形的玩法,让用户以比较低的成本生产出一些趣味十足的视频)、视频录制/暂停(例如闪现、瞬间换衣等玩法)、倍速/半速录制(在一些特别场景中需要用户录制视频时加快或放慢背景音乐使其能够跟上节奏完成录制动作,而后再恢复原始速度从而达到流畅表演的效果);视频编辑模块包括视频播放、视频特效、音频特效、快放/慢放处理(用于倍速/半速录制的还原);视频保存模块的功能是按照视频播放的时间戳选择视频特效与音频特效并生成一个特效时间Model,然后按照此特效时间Model进行特效处理、编解码(一般选用H.264+AAC,最终以MP4格式直接上传到服务器,服务器需要经过转码从而保证视频播放的兼容性,而对于时间较长的视频可以考虑分片上传的做法,降低转码时长)、封装格式IO等。在选择编解码器时,一两分钟以上的长视频会通过分片方式上传,这里介绍一种比较不错的分片上传模式:假设一个GOP为一片,系统以每两秒一片的速度完成上传后服务端即可进行转码,最终一个视频文件上传完成后,只剩余两秒也就是一个分片未转码,系统可在完成这两秒转码工作后,即可生成一个用户可播放的完整视频文件,从而以最快速度让其他人在平台上看到制作者的作品。此思路对于一分钟以上的长视频而言具有明显意义。

2.1 视频录制模块

视频录制由视频预览、伴奏播放、视频录制/暂停、倍速/半速录制四部分组成。

(1)视频预览

在Android&IOS平台我们可以使用自己的Camera+OpenGL ES进行视频的预览,这里的预览过程一般就是从相机获取纹理ID并进行诸如美颜、贴纸等特效的处理,之后再绘制到相应的View上。

(2)伴奏播放

伴奏播放是指将一个伴奏文件以m4a或mp3形式下载到本地,随后对文件进行解码。最常见的解码方案是FFmpeg。由于经过解码获取的PCM或WAV文件可被直接读取,伴奏播放的同时我们可将解码后的伴奏PCM文件写入磁盘中以方便后续编辑阶段更高效率的使用。

(3)视频录制暂停

开始录制之后系统将预览的视频帧编码并写入文件中,这相当于为录制开辟一条旁路。当得到一张图像后系统会将其送入编码器,此时这里的纹理ID保持不变并可再让其绘制到我们的View上。如果用户点击暂停则停止编码,当用户继续则将视频帧进行再次编码。这里需要注意的一点是关键帧的处理,如果不处理关键帧那么在手机端播放时就有可能会出现马赛克问题。

(4)倍速/半速录制

对短视频APP来说这一步骤十分重要,常用的方法是抽帧或者插帧操作。例如用户录制一段打篮球的视频并希望在扣篮或上篮时放慢动作,首先需要以正常速度录制而后再拉长视频以实现慢放效果。倍速与半速录制的关键是背景声处理,这里需要对背景声进行变速不变调处理。在FFmpeg的AVfilter模块中的Audiofilter里面有一个被称为Tempo的滤波器,而在SOX中也有tempo.c可实现类似功能。

2.2 变速不变调处理Tempo之W-SOLA实现

(1)基本概念

实现Tempo变速不变调处理的方法,比较常用的是SOLA。当然也存在很多改进算法,这里我们简单介绍一下W-SOLA。假设处理的样本为单声道、44.1k采样率的样本数据,其中有三个核心概念:Segment、Overlap、Search。Segment是指需要处理的音频数据窗口大小,例如规定以40毫秒作为处理音频数据的窗口大小;Overlap是指音频的重叠区域,一个Segment是40毫秒,而Overlap可覆盖的区域则可能为16毫秒;Segment是40毫秒,Overlap的一个覆盖范围是16毫秒,我们需要拿出这16毫秒并成功拼接才可加长。这里需要找寻相似度最高的位置进行拼接,并且要做fade_in和fade_out的拼接,否则就会出现杂音。我们可以设定为了查找相似度最高的地方而进行查找的范围Search为10毫秒,以上是Tempo中的三个核心基本概念。

(2)算法实现

算法实现如下:首先把送进来的数据保存到一个全局缓冲区中并定义为input_buffer ,并每次以Segment进行一个数据单位的处理。先在Search区域中搜索出与Overlap最佳匹配的位置,也就是波形的相似程度最高(overlap与搜索位置每个对应采样点相减的平方之和最小)的位置;从最佳匹配位置开始和Overlap中的数据进行Mix放入到全局的out_buffer中,Mix规则按照Overlap进行fade_out ,而原始数据进行fade_in并混合;从input_buffer中拷贝segment-2*overlap个采样到output_buffer中(中间位置保持不变);根据factor计算出skip的采样点个数并在input_buffer中进行skip操作。重复上述步骤,从而完成整个操作。

2.3 视频编辑模块

在视频编辑模块中,我们需要一个集成时间轴的可正常预览视频的标准视频播放器从而让用户更精确地控制每一帧使用什么特效;视频特效方面可以添加贴纸或者实现灵魂出窍,井格,九宫格等特效;音频特效方面我们可以添加背景音乐、视频静音、添加声音特效等;也可进行快放慢放处理,如果在此之前我们已经有了快放慢放的数据,那么即可直接进行恢复;如果用户选择快放或慢放处理并记录时间点,那么在视频抽帧或帧复制后即可重新生成一段完整视频。

2.4 音频效果器之混响器的实现

无论是SOX还是大家常用的其他效果器开源库,基本都是基于施罗德混响器模型来实现多种功能。

施罗德混响模型使用四个并联的梳状滤波器与两个串联的全通滤波器建立混响模型。我们将混响看作是一个脉冲,那么前期声音被称为早期反射声。完成混响后的声音将会受到一连串长尾效应的影响,梳状滤波器的作用是提供混响效果中延迟较长的回声从而减弱长尾效应。而延时较短的全通滤波器则起到了增加反射声波密度的作用,从而实现更加保真的混响效果。但是传统滤波器在面对反射声不足或反射声时差过大的问题时容易显得力不从心,我可以在后期处理混响后,在混响脉冲之中加入一些echo增强反射声的效果。

3. 视频保存模块

最后一个需要介绍的便是视频保存模块。视频保存实际上就是将视频编辑阶段记录下来的模型数据在离线状态下重新运算一次并将效果用于目标片段上,完成音视频的编解码与读写文件过程。

(1)特效时间Model

当我们在视频编辑阶段点击保存按纽时,特效时间Model就已建立了,视频编辑阶段会把视频特效作用的起始时间和终止时间记录到Model中,在视频保存阶段的对应时间段内进行特效应用。

(2)特效处理

无论音频特效还是视频特效都会按照特效时间Model进行对应的特效处理,处理后的音频PCM或视频帧会被送至编码器(这里的编码器一般为H.264或AAC),一般我们会选择硬件编码器从而实现高效编解码处理过程。

(3)编解码器

解码器解码而成的原始数据可被解析为纹理ID和PCM,随后这些数据会被交给Processor进行处理, 最终交给编码器并编码为H264与AAC数据。

(4)封装格式IO

最终我们会将H264与AAC封装成MP4并存储到本地文件中,整体就是视频保存模块。

这里需要强调一下视频保存模块的输出部分与视频预览模块之间的差别。二者的差别在于输出对象,后者输出对象是耳机、屏幕等,前者则输出于统一的文件内。但其中的解码部分与处理部分则完全一致,只不过前者的应用环境为离线,而后者可直接上传至对应位置的CDN或一些云存储厂商。

Q&A:

Q:如何优化在视频播放器中一边拖动进度条一边预览的卡顿状况?

A:我们曾经尝试解决过这个问题,我们试图在拖动到某个位置就解码出一帧或几帧并直接放至一个Buffer中,而在此之前我们集成了一个视频输出模块,此模块从队列中不断往外获取视频并进行展示。这样的话无论用户拖动多快播放器都可从队列中拿出用来展示的数据,队列中也就是存放3~4帧。之前我们进行开发实践时手机的性能还没有现在这么高,但在安卓平台上测试也没有什么卡顿。

Q:如何实现预加载ViewPager下一页视频?

A:这个取决于视频文件的存储格式。如果是以MP4存储那么并不易实现预加载,而如果使用HLS加载第一个分片则很容易实现。

Q:如何应对人脸识别+特效视觉情景下的丢帧问题?

A:人脸识别需要注意以下几点:第一点是需要将人脸识别基于异步线程进行开发而非预览线程。第二点是除非需要对人脸进行追踪,没有必要对每一帧视频进行人脸识别,我们可以规定两帧或三帧进行一次识别。第三点是为需要人脸识别的帧视频打上时间戳,这样当后续使用它时,对比当前时间戳跟检测出来的数据时间戳超过某一阈值即可判断非机主访问。

应广大读者要求,已经将Video-recorder与Video-Player项目迁移到AndroidStudio环境

https://github.com/zhanxiaokai/Android-as_video_recorder

https://github.com/zhanxiaokai/Android-as_video_player

应广大读者要求,已经将Android、iOS、PC平台的编译脚本上传到github上了

https://github.com/zhanxiaokai/cross_compile_project

购买地址

在线试读地址

为什么要写这本书

整个音视频领域的架构以及开发已经演进了很长的时间,从最开始的广电领域,到PC端的音视频领域,再到本书所介绍的移动端的音视频领域。在这几年中,移动端的音视频领域架构的演进也是巨大的。在移动互联网的发展热潮中,我有幸从事了音视频领域的设计与开发,并且是就职于最时尚的手机KTV—唱吧,这家充满人性化的公司,从而使得我开发出来的东西能够服务于几亿用户。对于音视频的移动端应用,不论是开发还是使用,在近两年内都达到了一个高峰,而作为一名工程师,如何高效地开发出一个音视频App,是一件非常困难的事情,特别是对于对音视频概念不太了解的工程师。我从事软件开发已有7年多的时间,接触音视频领域也已经有5年多的时间,在这5年多的开发过程中,每个时间段都会遇到新的挑战,尤其是在最开始涉足音视频领域的时候,真可谓举步维艰,首先对于音视频的基础概念不是特别清楚,再者在工作中边学边做,很难对整个音视频领域有一个全面的了解,并且市面上没有相关成熟的资料从更高的层次来介绍音视频领域在移动端的演进与发展。这几年的设计实战与开发经验,以及带新人入门的众多感触,让我有了写这本书的动力,同时也是这本书的和核心内容。我希望通过本书可以帮助到更多想要在移动端音视频领域上做出自己想法App的工程师,让大家可以顺利地建立起自己的音视频App。我非常希望能为刚入门的同学或者遇到困难的同学提供帮助,希望大家可以享受整个开发的过程、享受自己开发的产品为人们生活带来便利的成就感。另外从整个音视频开发领域来讲,我也十分希望能够通过本书贡献出自己的绵薄之力。

读者对象

  • 产品经理,这部分读者可以从中了解到音视频在移动端开发实践过程中遇到的很多问题以及对应的优化策略, 例如:如何通过音视频的统计数据为产品提供更加流畅的策略(视频观看的秒开、直播推流的流畅度、视频上传的成功率等)。
  • 项目经理,这部分读者可以从中了解到很多时下流行的名词与概念,不再会因为几个专业名词就让自己不知所措,并且可以有助于更好地评估音视频项目开发中的风险与进度。
  • 测试人员,这部分读者可以从中了解到音视频App中由于处理过程不同而导致的瓶颈问题,当然书中也提到了一些自动化测试相关的命令以及工具,可以对CPU的Load情况、内存的占用情况、内存泄漏问题等进行分析。
  • 架构师与工程师,这部分读者只需要一点移动开发经验就可以阅读本书了;当然如果你已经是一个Senior的移动开发工程师或者架构师的话,那么你读起本书来将更加游刃有余;再进一步,如果你已经是移动领域的音视频开发工程师了,那么恭喜你,我们之间将会有一场关于技术领域内部的对话。
  • 开设相关课程的大学院校。

如何阅读本书

为了避免说教式的讲解给读者带来枯燥乏味的阅读体验,本书会有大量的实例及生产环境下的案例。本书将分为四大部分,第一部分是入门篇,从理论基础开始讲解,最终会产生两个实践项目;第二部分是提高篇,会基于第一部分的项目添加特效,形成一个完整的多媒体项目;第三部分是提高篇,会结合当下比较流行的直播场景进行实际案例分析;第四部分是工具篇,其中介绍了当下大部分可以提高开发以及测试人员效率的工具。下面是各个章节的基本介绍。

第1章,对音视频的基础概念进行介绍,其中包括音视频的基础数据格式,编码后的数据格式以及不同格式之间的相互转换等。

第2章,从零开始讲解如何搭建一个iOS项目和Android项目,并且添加C++支持,因为音视频领域的开发毕竟有相当一部分的代码需要用C++来书写,这样就可以做到两个平台(Android和iOS平台)共用一套代码仓库,以提升开发效率。然后是讲解交叉编译,因为在音视频开发过程中会用到很多第三方开源库,如果将这些库编译到我们的项目中,势必就要进行交叉编译,因此本章会重点讲解这些内容。

第3章,将探讨ffmpeg开源库,对于音视频开发来讲,ffmpeg开源库是众所周知也是普遍使用的,本章首先从编译开始,接着是命令行使用,再到源码结构介绍,以及最后的API调用,以层层递进的方式对ffmpeg开源库展开探讨。

第4章,将讲解如何利用各自平台的API进行声音与画面的渲染以及解码,对于画面的渲染,推荐使用OpenGL ES,并且两个平台可以使用同一个代码仓库。

第5章,有了前四章的基础,我们已经完全可以构建起一个视频播放器了,本书最大的特点就是经过几章基础知识的学习就能立即开始一个项目的实践,通过本章的视频播放器项目,我们将会熟悉播放器是如何工作的。

第6章,本章会重点介绍音视频的采集与编码器。特别是硬件编解码器在各个平台上的使用,使得我们的应用能够更高效(耗电更少、发热更少、界面更流畅)地运行在用户的手机之上。

第7章,有了之前的基础,本章可以继续开发一个视频录制的新项目,该项目可以使得我们更加熟悉音视频应用在各个平台下的实现。

第8章,将讲解如何处理音频流,毕竟让别人听采集出来的干声是很不礼貌的,本章将利用各种特效来美化采集的声音。

第9章,将讲解如何处理视频流,使视频中的颜值变得更高,毕竟爱美之心人皆有之,本章将介绍如何对视频实现美颜滤镜。

第10章,将在第7章的项目基础之上,增加第8章的音频特效,第9章的视频特效,从而构建一个实际生产过程中的多媒体应用。

第11章,继续以项目作为驱动,详细讲解如何基于之前学习的内容构建一个直播的应用,本章将重点介绍推流以及拉流端,同时还会涉及礼物特效、聊天以及第三方云服务的内容介绍。

第12章,由于一个直播应用是很难在一章的篇幅中讲解完毕的,所以本书会将一些核心的处理放在本章中逐个进行讲解。

第13章,将介绍我和我的同事们经常用到的工具和排错方法,与大家分享在日常开发中如何才能更有效率地解决问题,本章并不仅限于音视频的开发领域。

附录里面会有本书的代码以及很多工具的参考内容。

勘误和支持

由于作者的水平有限,编写的时间也很仓促,书中难免会出现一些错误或者不准确的地方,不妥之处在所难免,恳请读者批评指正。为此,我特意创建了一个在线支持与应急方案的二级站点http://music-video.cn。你可以将书中的错误,发布在Bug勘误表页面中,同时如果你遇到任何问题,也可以访问Q&A页面,我将尽量在线上为你提供最满意的解答。书中的全部源文件都将发布在这个网站上,我也会将相应的功能更新及时更正出来。如果你有更多的宝贵意见,也欢迎你发送邮件至我的邮箱zhanxiaokai2008@126.com,我很期待能够听到你们的真挚反馈。

致谢

感谢唱吧与唱吧的每一位同事,是这个公司让我的职业生涯发展到了今天,也是这个公司让我能在音视频领域达到今天的成就,可以说没有唱吧就不会有这本书的问世。

感谢唱吧里的每一位用户,感谢你们对唱吧的长期支持和贡献,没有你们就不会有唱吧的今天,也就不会有这本书的问世。

感谢我的老婆,感谢你对我工作以及写作的支持,是你在我背后默默做了很多事情,才让我把更多的时间和经历放到工作以及写作中。

感谢机械工业出版社华章公司的编辑Lisa老师,感谢你的魄力和远见,在这一年多的时间中始终支持我的写作,正是你的鼓励和帮助引导了我顺利完成全部书稿。

感谢互联网,我从不怀疑我们在互联网上迈出的任何一步都是人类历史向前迈进的一步,感谢众多互联网人的辛苦工作,为我们创造了这么多机遇。

谨以此书,献给我最亲爱的家人、同事,以及众多互联网从业者们。

展晓凯

中国,北京,2017年9月