如何实现 Android 短视频跨页面的流畅续播?
在一切皆可视频化的今天,短视频内容作为移动端产品新的促活点,受到了越来越多的重视与投入,同时短视频也是增加用户粘性、增加用户停留时长的一把利器。那么如何快速实现移动端短视频功能呢?前两篇我们介绍了盒马短视频秒播优化(iOS 篇 / Android 篇),本篇我们聊聊秒播之外,另一个从体感上增加短视频用户体验的能力 - 续播。
作者|少阳
审校|泰一
短视频作为内容重要的承载方式,是吸引用户的重点,短视频的内容与体验直接关系到用户是否愿意长时停留。因此,体验的优化就显得尤为重要。
跨页面续播
跨页面续播是除秒播外另一个可以从体感上增加用户体验的能力。由于一些业务场景需要在不同页面上播放同一个视频内容的场景,而这些场景页面切换往往是连续的,这就要求短视频的播放也是连续。这样才能使得体验上会有连贯性,让用户在进入沉浸式页面时,能流畅的过度,并无感知的继续播放,从而产生连续不间断的感受。
在优化前,盒马沉浸式短视频播放页面的体验与主流短视频 App 有明显差距。从卡片列表页面跳转视频沉浸式页面时,相同视频无法续播,影响用户观赏和体验。下面主要介绍盒马短视频从普通展示页进入沉浸式页面时跨页面续播能力和流畅的动画切换效果的实现过程。
环境
- 手机:Pixel 4
- os:Android 10
- 播放器:淘宝播放器
效果对比
首先我们来看一下盒马优化前后与主流短视频 App 的效果对比
问题分析
从对比可以看出,续播的关键在于视频流的复用以及页面转场动画。
视频流的复用
要解决流的复用,同时又要保证进入新的页面时可以立即播放,不产生声音和画面的顿挫,这里根据上一篇《揭秘盒马鲜生 APP Android 短视频秒播优化方案》的分析,必须要解决视频下载,加载解码的耗时。
- 根据《揭秘盒马鲜生 APP Android 短视频秒播优化方案》里讲到缓存原理,这里可以利用播放器播放同一个视频(注意统一 URL,盒马全部转为 H.265)来避免多次下载。
- 加载解码的耗时则需要播放器复用来解决。这里涉及到实现方案,可参照下一章的续播方案选型。
转场动画
转场动画能显著提高体感流畅度,但实现过程中需要考虑各种兼容问题。
续播方案选型
在优化前期,我们考虑了三种续播方案。
播放器 View 跨页面传递
优点:思路简单,体验效果好。
缺点:业务侵入严重,不具通用性,播放器业务回调无法隔离,不利于续播放器管控。基于 Surface (View) 级别的全局播放器管理
优点:体验效果好,能扩展内存管控,侵入性低。
缺点:实现复杂,需要改写底层 HMVideoView 的封装逻辑;改造中易出现内存泄漏,较难排查。基于 MediaPlayer 级别的全局播放器管理
优点:无侵入,能扩展内存管控,实现快(可复用和扩展淘宝播放器底层 token 机制)
缺点:需要一定的改造,体验比方案 1、2 略差(声音有一瞬间的顿挫,不明显)
盒马最终选择方案 3,这里方案 2 和 3 原理是相同的,没有明显的优劣之分,最终选择方案 3 是因为这是目前稳定性最高,成本最低的方法。后续的播放器续播、复用、管理的分析同样适用于方案 2。
播放器续播、复用和管理
业务上,我们需要实现续播,通过问题分析,我们已经知道,通过视频流的复用即可实现,而视频流的复用这里选择通过复用 MediaPlayer 实现(也可以复用 Surface+MediaPlayer)。
解耦播放器 View 与 MediaPlayer 层
将 MediaPlayer 从 TaobaoPlayerView 中拆解出来,通过 MediaPlayerManager 进行全局管理。全局管理后,所有的播放器的 MediaPlayer 都由 MediaPlayerManager 分配和控制。
各组建间关系
业务流程
确保业务流程中,只需要关心业务与 VideoView 之间的交互,底层播放器复用由 MediaPlayerManager 实现。
播放器复用(管理)原理
播放器复用是管理的一个子集,所以这里一起介绍。主要原来有以下几个原则:
- 全局播放器(MediaPlayer)控制最多创建 4 个。
- 超过 4 个播放器,创建第 5 个时,先销毁最少使用的播放器的 MediaPlayer。
- 每个播放器随机分配一个 token(时间戳 + 随机数),也可以开发者指定。
- 相同 token 的播放器,共享 MediaPlayer。
- 一个 MediaPlayer 同时只能被 1 个播放器 Surface 所绑定和持有。
- 存在相同 token 的播放器,当前播放器在销毁时,保留 MediaPlayer 实例。
- 已创建的播放器恢复播放,但 MediaPlayer 被其他后创建的播放器占用时,解绑 MediaPlayer 并重新绑定当前播放器。
场景模拟
场景一:APP 共创建 4 个及以内播放器。
场景二:创建超过 4 个播放器时。
场景三:新创建的播放器 token 已存在时,复用 MediaPlayer。
场景四:存在 token 与当前即将被销毁的播放器 token 一致时(或已被解除 MediaPlayer 的播放器播放时)。
逻辑流程图
从场景总结,MediaPlayer 主要提供 复用、恢复、销毁、驱逐(创建) 四个能力。
转场动画
目前转场动画有两个方案可选:
Android 自带的元素动画
优点:动画流畅顺滑,无需实现动画逻辑,由系统自己实现。
缺点:侵入严重,需要改写 Nav 层,在 View 复用的方案下有白屏和黑屏。自定义实现属性动画
优点:侵入小,只需要前置页极少的坐标信息,如果是 View 复用方案,甚至不需要前置页提供坐标信息;兼容性好,适用于各种播放器复用场景。
缺点:需要自己实现动画,有一定的闪烁感。
动画原理
- 前置页跳转到沉浸式,传递播放器坐标 Rect 信息。
- 沉浸式默认透明,并根据 Rect 坐标信息创建播放器(复用)。
- 开始动画,将播放器 View 放大至正确位置,同时背景不透明度增加。
(注意:这里最后要将沉浸式页的主题设为不透明,否则前置页不会执行 onStop () 具体参考下一节,生命周期填坑。)
ps:返回动画同理,过程相反即可。
生命周期填坑
属性动画原理存在一个坑。
问题描述:
假设页面为 A->B,方案 3 要求 B 页面在动画过程中是全透明的。当 B 的 theme 中 windowIsTranslucent 为 true 时,A->B 过程 A 的生命周期无法走向 stop(即便 B 页面动画结束,完全遮盖 A 页面)。因此,A 的生命周期没有按照预期执行,一些需要 onStop 执行的场景下,业务就无法正常执行
B Ativity 的样式(注:示例代码):
<style name="MyTransparent" parent="xxxx">
<item name="android:windowFullscreen">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@style/noAnimation</item>
</style>
解决方案:
- 进入动画结束时,通过反射调用 Activity 的 convertFromTranslucent 方法, 使 activity 不透明。
- 返回动画开始时,通过反射调用 Activity 的 convertToTranslucent 方法,使 activity 透明。
后续优化展望
关于多媒体的优化工作还有很多可以做。除了续播和沉浸式秒播等场景外,我们还可以:
1. 对播放器的一般性场景进行秒播优化,如首页列表的卡片视频。
2. 对播放器的全局实例管控,控制播放器创建数量,从而优化内存。
未优化:
操作:连续开启 30~50 个页面及播放器。
现象:内存飙升,手机发烫,影响手机正常使用。
优化后:
操作:每秒开启 1 个页面和播放器,连续开启 100 个。
现象:内存呈锯齿状正常上升,无明显飙升现象,软件运行正常。
下一期我们将继续分享盒马 iOS 端短视频续播的体验优化实践。
「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。公众号后台回复【技术】可加入阿里云视频云产品技术交流群,和业内大咖一起探讨音视频技术,获取更多行业最新信息。
如何实现 Android 短视频跨页面的流畅续播?的更多相关文章
- 如何实现 iOS 短视频跨页面的无痕续播?
在一切皆可视频化的今天,短视频内容作为移动端产品新的促活点,受到了越来越多的重视与投入.盒马在秒播.卡顿率.播放成功率等基础优化之外,在用户使用体验上引入了无痕续播能力,提升用户观看视频内容的延续性. ...
- Android短视频滑动播放(一)
本文主要介绍采用RecyclerView配合PagerSnapHelper实现短视频滑动播放内容. 1. 主页内容构建 主页布局文件定义RecyclerView,为RecyclerView建立对应适配 ...
- Android短视频中如何实现720P磨皮美颜录制?
视频中磨皮.美颜功能已成为刚需,那么如何在Android短视频中实现720P磨皮美颜录制?本篇文章中,网易云信资深开发工程师将向大家介绍具体的操作方法. 相关阅读推荐 <短视频技术详解:Andr ...
- 揭秘盒马鲜生 Android 短视频秒播优化方案
短视频作为内容重要的承载方式,是吸引用户的重点,短视频的内容与体验直接关系到用户是否愿意长时停留.因此,体验的优化就显得尤为重要.上一篇我们分享了 iOS 短视频秒播优化,这篇我们来聊聊 Androi ...
- Android短视频SDK转码实践
一. 前言 一些涉及的基本概念: 转码:一般指多媒体文件格式的转换,比如分辨率.码率.封装格式等: 解复用(demux):从某种封装中分离出视频track和音频track,然后交给后续模块进行处理: ...
- Android 用视频做页面背景
不知道怎么开头,直接代码. xml:RelativeLayout布局,MyVideoView放在第一位,其他的放到之下就可以. <MyVideoView android:id="@+i ...
- 如何快速打造一款高清又极速的短视频APP?
整个短视频的市场规模一直在增长,网络数据显示2018年已经突破100亿大关,在2019年预测将超过200亿.纵观行业,在生活资讯.美食.搞笑.游戏.美妆等领域,短视频流量巨大但竞争激烈,但是在教育.财 ...
- 短视频 SDK 架构设计实践
作者简介 孔维乐,七牛云客户端团队 Android 平台高级开发工程师,专注音视频,图形图像领域.OpenGL 专家,先后参与直播推流及连麦 SDK 的开发,主导短视频 SDK 的架构设计与实现, 对 ...
- android多框架实现短视频应用、3D手势旋转、banner控件、指南针、智能管家等应用源码
Android精选源码 android智能管家app源码 Android高仿拼多多分类列表 Android百度地图实例详解之仿摩拜单车APP RecyclerView的LayoutManager搭建流 ...
随机推荐
- linux系统下操作mysql数据库常见命令
一. 备份数据库(如: test): ①可直接进入后台即可.(MySQL的默认目录:/var/lib/mysql ) ②输入命令: [root@obj mysql]# mysqldump -u roo ...
- 【源码】“@Value 注入不成功”引发的一系列骚操作
目录 背景 模拟@Value成功的场景 模拟注入不成功的场景 看看为什么没有注入成功 为什么加static和不加static的加载顺序是不一样的呢 我们不加static,能不能也让它注入成功呢? 总结 ...
- JSON数据的HTTP Header应该怎么标记?
第一种 header('Content-type: application/json'); 另一种 header('Content-type: text/json');
- 移植TensorFlow到Windows平台
2015年11月,Google宣布开源旗下机器学习工具TensorFlow,引发业界热潮.TensorFlow原生支持*unix系和安卓平台,但并不提供对Windows平台的支持.如果想在Window ...
- H5页面自动烟花特效
代码如下: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> ...
- 小程序中多个echarts折线图在同一个页面的使用
最近做小程序的业务中遇到一个页面要同时显示几个echarts图,刚开始遇到各种冲突,死数据可以,动态数据就报错的问题,折磨了一天,仔细看了官网和查在各种资料之后,终于解决了. 直接上代码: commi ...
- 腾讯云TDSQL监控库密码忘记问题解决实战
首先,给大家介绍一下TDSQL.TDSQL MySQL 版(TDSQL for MySQL)是腾讯打造的一款分布式数据库产品,具备强一致高可用.全球部署架构.分布式水平扩展.高性能.企业级安全等特性, ...
- ubuntu安装qemu
ubuntu安装qemu ubtuntu编译安装qemu 5.2.0,apt-get安装的版本过于老旧. 环境:ubuntu 18.04. wget https://download.qemu.org ...
- 并发编程——synchronized关键字的使用
前言 我们一般对共享数据操作的时候,为了达到线程安全我们会使用synchronized关键字去修饰方法或者代码块.那么今天我们就来讲一讲synchronized关键字的使用. 专栏推荐: 并发编程专栏 ...
- React脚手架配置代理
react脚手架配置代理 方法一 在package.json中追加如下配置 "proxy":"http://localhost:5000" 说明: 优点:配置简 ...