Android视频技术探索之旅:美团外卖商家端的实践( 二 )

整体架构
我们整体的架构设计 , 用以满足业务扩展和平台化需要 , 可复用、可扩展 , 且可快速接入 。架构采用分层设计 , 基础能力和组件进行下沉 , 业务和视频能力做分离 , 最大化降低业务方的接入成本 , 三方业务只需要接入视频基础SDK , 直接使用相关能力组件或者工具即可 。
整体架构分为四层 , 分别为平台层、核心能力层、基础组件层、业务层 。

  • 平台层:依赖系统提供的平台能力 , 比如Camera、OpenGL、MediaCodec和MediaMuxer等 , 也包括引入的平台能力 , 比如ijkplayer播放器、mp4parser 。
  • 核心能力层:该层提供了视频服务的核心能力 , 包括音视频编解码、音视频的转码引擎、滤镜渲染能力等 。
  • 基础能力层:暴露了基础组件和能力 , 提供了播放、裁剪、录屏等基础组件和对应的基础工具类 , 并提供了可定制的播放面板 , 可定制的缓存接口等 。
  • 业务层:包括段落拍摄、自由拍摄、视频空间、拍摄模版预览及加载等 。
我们的视频能力层对业务层是透明的 , 业务层与能力层隔离 , 并对业务层提供了部分定制化的接口支持 , 这样的设计降低了业务方的接入成本 , 并方便业务方的扩展 , 比如支持蜜蜂App的播放面板定制 , 还支持缓存策略、编解码策略的可定制 。整体设计如下图所示:
 
Android视频技术探索之旅:美团外卖商家端的实践

文章插图
 
 
实践经验
在视频开发实践中 , 因业务场景的复杂性 , 我们遇到了多种问题和挑战 。下面以核心功能为基点 , 围绕各功能遇到的问题做详细介绍 。
视频播放
播放器是视频播放基础 。针对播放器 , 我们进行了一系列的方案调研和选择 。在此环节 , 遇到的挑战如下:
1. 兼容性问题
2. 缓存问题
针对兼容性问题 , Android有原生的MediaPlayer , 但其版本兼容问题偏多且支持格式有限 , 而我们需要支持播放本地视频 , 本地视频格式又无法控制 , 故该方案被舍弃 。ijkplayer基于FFmpeg , 与MediaPlayer相比 , 优点比较突出:具备跨平台能力 , 支持Android与IOS;提供了类似MediaPlayer的API , 可兼容不同版本;可实现软硬解码自由切换 , 拥有FFmpeg的能力 , 支持多种流媒体协议 。基于上述原因 , 我们最终决定选用ijkplayer 。
但紧接着又发现ijkplayer本身不支持边缓存边播放 , 频繁的加载视频导致耗费大量的流量 , 且在弱网或者3G网络下很容易导致播放卡顿 , 所以这里就衍生出了缓存的问题 。
针对缓存问题 , 引入AndroidVideoCache的技术方案 , 利用本地的代理去请求数据 , 先本地保存文件缓存 , 客户端通过Socket读取本地的文件缓存进行视频播放 , 这样就做到了边播放边缓存的策略 , 流程如下图:
 
Android视频技术探索之旅:美团外卖商家端的实践

文章插图
 
 
此外 , 我们还对AndroidVideoCache做了一些技术改造:
  • 优化缓存策略 。针对缓存策略的单一性 , 支持有限的最大文件数和文件大小问题 , 调整为由业务方可以动态定制缓存策略;
  • 解决内存泄露隐患 。对其页面退出时请求不关闭会导致的内存泄露 , 为其添加了完整的生命周期监控 , 解决了内存泄露问题 。
视频录制
在视频拍摄的时候 , 最为常用的方式是采用MediaRecorder+Camera技术 , 采集摄像头可见区域 。但因我们的业务场景要求视频采集的时候 , 只录制采集区域的部分区域且比例保持宽高比16:9 , 在保证预览图像不拉伸的情况下 , 只能对完整的采集区域做裁剪 , 这无形增加了开发难度和挑战 。通过大量的资料分析 , 重点调研了有两种方案:
  1. Camera+AudioRecord+MediaCodec+Surface
  2. MediaRecorder+MediaCodec
方案1需要Camera采集YUV帧 , 进行截取采集 , 最后再将YUV帧和PCM帧进行编码生成mp4文件 , 虽然其效率高 , 但存在不可把控的风险 。


推荐阅读