NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

怎样实现一款「视频录制」应用?

  • 2019-10-10
  • 本文字数:3697 字

    阅读完需:约 12 分钟

怎样实现一款「视频录制」应用?

随着智能手机的普及和网络传输技术的发展,人类的传播媒介正在由图文向视频过度。短视频作为一种底层的内容形态,可以渗入到任何领域、任何行业的 App 中。如今,例如社交、金融、电子商务、政务民生等相当一部分的 APP 都在持续集成这一功能。


相比图片和文字,视频所传递的信息更为具象和丰富,视频录制正从「专业短视频制作功能」演变为「一个基础功能」,从而嵌套在各个 APP 的使用场景里。


那么对于有「视频录制」需求的 APP 来说,要怎样实现这一功能呢?在这里,主要以七牛短视频 SDK 中的 Android 平台为例来简单讨论一下此功能的实现方法(当然感兴趣的伙伴也可以直接拉到文末,扫描二维码进行体验)。


需求分析可以更好地辅助落地执行的实施,所以在下手之前,可以先对「视频录制」这样一个需求做一下简单的分析。从功能性需求点上,可以分为以下几块:


1.核心需求


  • 摄像头拍摄视频

  • 麦克风采集音频

  • 能够预览

  • 编码压缩

  • 能够在本地保存为一个 mp4 文件


2.控制型需求


  • 能够控制摄像头拍摄,支持曝光度,闪光灯,前后摄像头切换,画面对焦等功能

  • 能够控制麦克风采集,包括声道数,采样率,音频格式等参数

  • 能够控制最终输出视频的分辨率,码率,FPS 等参数


3.开放型需求


  • 能够支持一些第三方的视频特效(美颜特效,AR 特效等)

  • 能够支持一些第三方的音频特效(变声等)


4.性能和兼容性需求


  • 整个过程的耗时不可太长

  • 能够覆盖尽可能多的 Android 机型


5.高级需求


  • 支持录制时增加背景音乐混音

  • 支持分段拍摄


从以上归纳可以看出,除了核心需求外,在大家的使用场景中,潜在的需求是比较多的。需求决定着架构的设计,只有真正理清楚需求之后,才能去谈如何设计。


比如,NO.3 就决定着我们应该有丰富的回调接口,能够把视频或者音频数据回调给外部,从而满足多样化的二次开发。NO.4 则需要七牛云同时支持硬编码和软编码来减少时耗和增加兼容性。而 NO.5 则是一些比较高级的功能,是一些发散的需求,可能会发散出很多的玩法,这就要求我们对需求的发展及外延有一定的预判能力。


从逻辑层面来说,我们整体的架构图可以是这样的:



宏观来讲,整个过程可分为数据的采集、处理、编码、封装和输出这几个部分。接下来咱们分别简单讨论一下每一个模块大致是如何实现的。

采集模块

采集模块是整个数据的输入源头。对于 Android 平台来说,视频和音频的采集模块主要是用 Camera 和 AudioRecord 来分别实现的。


Camera 能够分别回调 YUV 和纹理两种形式的数据,其相应的方法分别如下:


// 从摄像头回调 YUV 数据void Camera.setPreviewCallbackWithBuffer(PreviewCallback cb);// 从摄像头回调纹理数据void Camera.setPreviewTexture(SurfaceTexture surfaceTexture);
复制代码


这两种数据分别由 CPU 和 GPU 来处理,我们主要用纹理来传递数据,以帮助客户减少耗时。当把一个 SurfaceTexture 作为 Camera 的预览目标,Camera 则会把 SurfaceTexture 创建的 Surface 作为一个输出源,我们通过调用 updateTexImage() 方法,从摄像机采集的图片流中取得每帧图片的纹理。


这里需要说明的是,从 Camera 中获取的纹理并不是我们常用的 GL_TEXTURE_2D 类型,而是 GL_TEXTURE_EXTERNAL_OES 类型,所以我们对纹理设置参数也要使用 GL_TEXTURE_EXTERNAL_OES 类型。同样的,在 shader 中也需要使用 samplerExternalOES 采样方式来声明纹理,如在 FragmentShader 的代码如下:


public static final String TEXTURE_EXTERNAL_FS =        "#extension GL_OES_EGL_image_external : require\n" +        "precision mediump float;\n" +        "uniform samplerExternalOES u_tex;\n" +        "varying vec2 v_tex_coord;\n" +        "void main() {\n" +        "  gl_FragColor = texture2D(u_tex, v_tex_coord);\n" +        "}\n";
复制代码


音频采集则相对简单一些,AudioRecord 的关键使用方法如下:


// AudioRecord 的构造函数,我们可以把一些配置相关的参数传递进去
AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes);// 创建好了AudioRecord实例之后,通过该方法开始麦克风采集void AudioRecord.startRecording();// 在采集的过程中,通过该方法不断的从缓冲区循环提取 PCM 数据int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes);// 停止采集,释放资源void AudioRecord.stop();
复制代码

处理模块

处理模块可以分为「外部处理」和「内部处理」两部分,外部处理是指对第三方合作伙伴的可扩展,内部处理是我们自有的处理逻辑。


拿到摄像机和麦克风采集的数据之后,首先要把数据回调给最外层。当第三方的合作伙伴拿到我们传出的纹理或者 PCM 数据,就可在此基础上做一些特效处理,如音频相关的变声特效、视频相关的人脸识别、美颜、AR、滤镜等等,继而把处理完的数据再次返回给我们。当数据进到的内部处理模块之后,又可以根据自身的处理业务来进行二次处理,例如纹理的裁剪,旋转或者音频相关的混音。


层与层之间的数据传输是通过回调接口来实现的,我们可以设计如下接口来实现视频和音频的数据传输:


// 视频 yuv 数据回调public interface VideoYUVFrameListener { boolean onVideoFrameAvailable(byte[] data, int width, int height, int rotation, int fmt, long timestampNs);}
// 视频纹理数据回调public interface VideoTextureFrameListener { void onSurfaceCreated(); void onSurfaceChanged(int width, int height); void onSurfaceDestroy(); int onVideoFrameAvailable(int texId, int texWidth, int texHeight, long timestampNs, float[] transformMatrix);}
// 音频 PCM 数据回调public interface AudioFrameListener { void onAudioFrameAvailable(byte[] data, long timestampNs);}
复制代码


视频处理模块的主要原理是通过回调机制,用 OpenGL 把相应的特效离屏渲染到纹理上,进而把纹理进行裁剪,缩放,旋转等操作。作为「一张纹理的艺术之旅」,经过如此层层处理后,最终的纹理囊括了各层处理的效果之和。而相比于视频,音频处理模块的主要原理是通过重采样、混音、或一些 3A 算法直接对 PCM 数据作修改。

预览编码模块

视频帧处理完成之后,我们需要把纹理数据传递给一个 SurfaceView 用于预览。此时,上一阶段对纹理的处理结果便可以在此 SurfaceView 上表现出来。另外,我们还需要把该纹理数据传递给视频编码器进行编码。预览和编码虽然是两个线程,但是却共享一个纹理,如此会减少资源的占用,帮助效率的提高。


为了适配更多的 Android 机型,系统在支持 MediaCodec 的同时,也要支持 x264 软编,不过最主要的编码方式应该还是以硬编码为主,原因是硬编码在时耗上要远远优于软编码。在硬编模式下,整个拍摄模块核心实现图如下所示:



可以看出,整个流程是生产者/消费者模式,摄像机首先作为数据的生产者向外提供数据,数据会输出到一个 Surface 上,此 Surface 即 SurfaceTexture 内部创建的。与此同时,我们会通过 SurfaceTexture 源源不断的获取数据,接着把数据通过 GLES 分别渲染到 SurfaceView 的 Surface 和 MediaCodec 的 Surface 中。


下一步, SurfaceFlinger 作为消费者,负责把 SurfaceView 的 Surface 中的数据输出到屏幕。同理,MediaServer 作为消费者,负责把 MediaCodec 的 Surface 中的数据输出到编码器进行编码。


以上是视频编码的方式,相较于视频编码,音频编码则简单的多,我们只需对编码器设定编码参数后持续向编码器输入 PCM 数据即可,编码器会把编码后的数据回调给开发者。

封装和输出模块

mp4 的封包可以用 MediaMuxer 来实现,但从兼容性上来考虑,最好用 FFmpeg 来封包。例如,倘若编码出来的视频带有 B 帧,那么如下图所示,MediaMuxer 仅仅在 Android 7.0 以上才能够支持。



无论是使用 MediaMuxer 抑或 FFmpeg 来封包,最终都会在本地输出一个视频文件,至此大家即完成了从拍摄视频到最终输出的整个流程。


综上流程,我们实现「视频录制」中主要用到的 API 如下图所示:



可以看到,多媒体开发和 APP 开发有所不同,主要用到的是更偏底层的一些 API。除此之外,还需要对音视频的编码标准,常用格式,FFmpeg,OpenGL 等知识有一定的了解,所以开发的门槛还是相对高的。


正是因为有这些门槛,中小型团队、创业初阶段的公司、或不把视频拍摄作为核心业务的团队实在无需像这样从 0 到 1 的重量化地造轮子。这就譬如厨师无需从除草、耕作、施肥、种菜都一一亲力亲为,而是需要把时间和精力用来钻研食材的味道和烹饪本身。


同样的道理,开发者们选择直接用一款适合自己公司的音视频 SDK 其实是效率最高的做法。七牛云短视频 SDK 包含量以上所有需求的实现,帮助 B 端用户节省时间成本和人力成本,帮助用户专注精力于自己的核心业务。在 SDK 的使用上,七牛云大大简化了接入流程,力求缩短从想法到产品的距离。


自从 2017 年上线以来,七牛云已经帮助数以千计的客户快速地集成音视频能力,受到了业内合作伙伴和客户的高度评价。未来,七牛云短视频 SDK 将持续在音视频领域深耕,为更多的客户提供优质的解决方案。


本文转载自公众号七牛云(ID:qiniutek)。


原文链接:


https://mp.weixin.qq.com/s/c4XiFNs66Qa5Yyb3k2zhbw


2019-10-10 18:27748

评论

发布
暂无评论
发现更多内容

一文详解前端发展趋势

不在线第一只蜗牛

前端 前端开发 前端框架

智能合约系统开发原理介绍丨智能合约开发源码详情

西安链酷科技

合约系统开发

华为云开年采购季云上云下一体化安全解决方案,打造高效、安全管理平台

轶天下事

SD-WAN解决企业在工业互联网时代的新困境

Ogcloud

SD-WAN 企业网络 SD-WAN组网 SD-WAN服务商 SDWAN

量化交易系统开发技术实现方案及源码

西安链酷科技

量化交易系统

Kyligence 亮相 Gartner 数据与分析峰会,生成式 AI 落地赋能业务

Kyligence

区块链项目媒体发稿:海外宣发是企业宣传的长远布局

西安链酷科技

项目推广 项目宣发 媒体包装

为什么投递的简历无响应?

王磊

Java 面试

挖矿系统开发技术详解丨挖矿APP开发源码案例

西安链酷科技

BCI矿机搭建

华为携手伙伴再出发,引领空间智能新潮流,创造无限可能

HarmonyOS开发者

低代码与数智制造:引领软件开发的革新之旅

EquatorCoco

低代码 制造 数智化

解锁区块链游戏数据解决方案

Footprint Analytics

链游

聚道云连接器助力航信费控与用友U8无缝对接,赋能供应链管理

聚道云软件连接器

案例分享

Flink 流处理框架核心性能

木南曌

flink 实时计算

PlayBook 详解

不在线第一只蜗牛

Linux 网络 服务器

从基础到代码实战,带你进阶正则表达式的全方位应用

快乐非自愿限量之名

php 正则表达式 代码

区块链项目宣发、媒体推广、项目孵化,一站式服务

西安链酷科技

项目推广 媒体包装

全栈开发与自动化测试高薪私教班,带你从0到1拿到高薪Offer

霍格沃兹测试开发学社

智能合约DAPP系统开发详解介绍丨智能合约源码程序

西安链酷科技

量化交易系统开发技术阐述丨量化交易源码开发

西安链酷科技

量化交易

区块链项目包装攻略,区块链项目包装运营

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

Python中的机器翻译技术与应用

技术冰糖葫芦

API API 接口

CCR智能量化机器人系统开发详解方案

西安链酷科技

量化交易

2024 年 2 月公链行业研报

Footprint Analytics

比特币 公链 defi Layer 2

全栈开发与自动化测试高薪私教班,带你从0到1拿到高薪Offer

测吧(北京)科技有限公司

测试

Flink 简述

木南曌

flink 实时计算

科技创新引领零售商品部降本增效的未来

第七在线

赛博威获颁“华南区数字营销优秀案例”奖及“广东省名优高新技术产品”证书,领先的数字营销能力获双重认可!

赛博威科技

SD-WAN怎样提高网络管理的效率?

Ogcloud

SD-WAN 企业网络 SD-WAN组网 SD-WAN服务商 SDWAN

SpaceX 星舰发射「成功一半」;首位具身 AI 机器人面世丨 RTE 开发者日报 Vol.166

声网

百度智能云加速「低代码+大模型」融合,爱速搭位居 2023 年 IDC 低代码/无代码领导者象限

Baidu AICLOUD

低代码平台 大模型 爱速搭 AIGC 企业级开发

怎样实现一款「视频录制」应用?_移动_七牛云_InfoQ精选文章