关于阿里云开发者:如何实现-iOS-短视频跨页面的无痕续播

41次阅读

共计 3298 个字符,预计需要花费 9 分钟才能阅读完成。

简介: 在所有皆可视频化的明天,短视频内容作为挪动端产品新的促活点,受到了越来越多的器重与投入。盒马在秒播、卡顿率、播放成功率等根底优化之外,在用户应用体验上引入了无痕续播能力,晋升用户观看视频内容的延续性。本篇将分享盒马在 iOS 短视频方面的实际干货。

作者|神捕

审校|泰一

跨页面续播是除秒播外另一个能够从体感上减少用户体验的能力。因为一些业务场景须要在不同页面上播放同一个视频内容的场景,而这些场景页面切换往往是间断的,这就要求短视频的播放也是间断。这样能力使得体验上会有连贯性,让用户在进入沉迷式页面时,能流畅的适度,且无感知的持续播放,从而产生间断不间断的感触。上面咱们开始介绍盒马短视频的跨页面续播能力和晦涩的动画切换成果的流畅性。

如上视频所示,视频在列表页预览观看后,用户很可能持续点击跳到下一个全屏页面,进入沉迷式体验。在这过程中,视频窗口平滑变大至全屏,视频进度是连续的,两头没有感觉到视频或音频的进展感。在页面返回后,视频窗口也有相应的还原成果。

指标

  • 接入简略,只须要关怀并加一个参数,其它逻辑内聚。
  • 适配性好,反对裁剪模式的切换。
  • 视频、音频无缝连接,不能有任何进展感。
  • 页面间播放状态隔离,互不烦扰。

实现计划

在计划抉择上,次要思考了以下三种:

目前盒马采纳的是第 3 种 ——playerView 的复用形式,具体来说,无痕续播的实现,至多须要以下几个步骤:

1. 用户点击,从 A 页面跳转到 B 页面,如:domain/path?reusedPlayerView=0xyyyyyy, 在原有业务参数的根底上,增加一个 reusedPlayerView 参数,把 playerView 传给下个页面。
2. B 页面 HMTBPlayerView 的实例化:外部实例化一个或复用 A 页面的 reusedPlayerView。
3. playerView 的大小地位换算,实现切换动画。
4. 从 B 页面返回 A 时,实现退出动画并返还 playerView。

以上步骤不多,但具体实现起来是比较复杂的,上面咱们将围绕 4 个次要问题的解决过程,来阐明具体实现形式。

尺寸变动的动画

失常来说,只有计算好 playerView 的原始 Rect,以及最终 Rect,基于 UIView 做 frame 动画就能够简略实现窗口变大成果。但实现时发现,手淘播放器外部重写了 setFrame 办法,只有批改了 frame,playerView 将间接显示为终态,动画没有成果。

于是,这里采纳了 CGAffineTransform 的 scale 实现:先把 playerView 的 frame 设置为终态,计算好变动前后的尺寸比例 ratio,设置 playerView.transform = CGAffineTransformMakeScale (ratio, ratio),将其尺寸等比放大为初始地位大小,而后就能够执行 transform 的动画实现从终点到起点的变换。

须要留神的是,此处 ratio 的计算形式,是以 playerView 内实在渲染的视频尺寸计算,而不是 playerView 自身大小。

渲染 mode 的切换

视频渲染自身能够设置为 ScaleAspectFit 或 ScaleAspectFill,目前在盒马的场景中,存在一种 A 页面的播放器为 fill mode,且 playerView 固定正方形,但跳转到 B 页面时,变成 fit mode,这样就呈现了一个在尺寸变动动画进行时的 mode 切换的问题。

上述通过 setFrame 并批改 transform 的形式,能够实现把 playerView 大小变换成与动画前的初始大小统一,然而,如果此时存在 mode 切换需要就有可能呈现计算后的大小不统一,比方从一个 9:16 长方形的 playerview 变成一个 1 : 1 且 mode 为 fill 的正方形 playerView,此时宽度统一,但高度显著多出了,间接做动画会导致初始状态闪动。

这里的解决形式,咱们应用了 maskView 进行 mode 切换过渡:首先,计算 maskView 别离在宽高上的 scale,而后设置 playerView.maskView.transform。计算形式如下:

CGAffineTransformMakeScale(originalRect.size.width/(destRect.size.width*ratio), originalRect.size.height/(destRect.size.height*ratio))

这样就实现利用 maskView,把 9:16 的长方形显示成 1:1 的可见区域,实现动画的起始地位重合。最初,联合上述 playerView.transform 动画,再增加一个 maskView.transform 动画,二者配合,模拟出带 mode 切换场景下的动画过渡成果。

被动回收与被动偿还策略

在实现了进场动画之后,最重要的是须要思考 playerView 复用逻辑,其中比拟重要的一点就是 playerView 什么时候归还给 A 页面。

目前咱们采纳的是租借思路:

1. 有可借 playerView 时,进行借用;

2. 复用的 playerview 不再应用时,及时被动偿还;

3. 当出租方本人要应用时,发现租方还未返还,此时进行被动回收。

具体场景来说:进场时,判断有 reusePlayerView,则进行复用;当沉迷式视频(B 页面,相似抖音)翻到下一个视频时,上一个视频进行被动偿还操作,如果用户又划回到第 1 个视频,此时是 new 的 playerView 了;另外,当用户点击页面敞开时,被动偿还(如果还未还的话);特地要留神的是,这里还减少了一个被动回收机制,场景比方用户通过一些咱们未知的形式,回到了页面 A,此时 reusePlayerView 是没有被动偿还的,但页面 A 本人又须要 play,此时就触发了被动回收机制,保障以后页面可用。

有一点须要提一下的是,在页面返回时也有动画,实现方面与上述相似,惟一区别是,返回时页面可能 dealloc 了,动画会有问题,所以咱们做法是先把 playerView 从 B 页面,增加到 window, 做好缩放动画,完结后,再被动归还给页面 A。

状态隔离

在应用播放器复用时,须要思考一个重要的问题,就是复用后,播放器状态、设置的隔离。比方,在页面 A 进入页面 B 后,播放器无痕续播,但播放器的状态对 A 来说是暂停,对于 B 来说必须是播放状态,尽管二者应用的是同一个 playerView。

这种隔离是很有必要的,比方业务想要疏导用户进入页面 A 的业务,在这里观看视频能够得积分,那么在他进入页面 B 时,就不应该持续结算积分(业务依赖了播放状态告诉)。还有,A 与 B 页面的播放设置可能不同,A 可能是静音,B 是有声音,设置不同,也须要隔离。咱们是这样做的,如下图(视图层级):

图中,最外层的 view 是盒马本人封装的播放器 HMTBPlayerView,外部有一个手淘的 TBMPBPlayerView,大小一样。咱们拿来做复用的其实是 TBMPBPlayerView 这一层,而把业务层的所有设置放在 HMTBPlayerView,这样的话,在 TBMPBPlayerView 被移走时,从新依据新的 HMTBPlayerView 设置它,做好关联,而旧的 HMTBPlayerView 设置不受影响,包含播放器回调。

总结

综上,咱们实现了一种播放器复用形式,在播放器外部实现了窗口切换、状态隔离等逻辑,对 App 应用方来说是简直无感的。该计划不仅可用在无痕续播场景上,今后也能够用在 App 内全局播放器实例复用优化方向。


「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实际技术文章,在这里与音视频畛域一流工程师交换切磋。公众号后盾回复【技术】可退出阿里云视频云产品技术交换群,和业内大咖一起探讨音视频技术,获取更多行业最新信息。

版权申明: 本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

正文完
 0