背景
前几天做一个需求,社区文章如果是视频类型,需要在文章列表播放视频预览动图。
这里我们使用了视频部门的服务,生成视频预览,对方给出的可选格式为 webp、mp4、flv、hls,后面三个都是视频格式,肯定不能作为预览图,而且考虑到 webp 有用较小的体积,我们使用的 fresco 也支持 WebP 的动图,因此果断选择了 WebP 格式。
fresco 加载动图的方法
val uri = Uri.parse("http://voddafz06jj.vod.126.net/voddafz06jj/videoPreview_1821338293_IQAB9DSR.webp")
val controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setAutoPlayAnimations(true)
.build()
drawee_view.controller = controller
看起来好像没什么问题,可是等开发完成拿给产品看的时候,产品不乐意了,这个动图怎么只能播放一次呢,我需要循环播放。
赶紧去补了下课,原来 WebP 动图是可以设置循环次数的,询问了视频部门的同事,原来是他们生成的预览图没有设置循环播放属性,坑爹。。
而视频部门也需要排期来支持预览图循环属性,只能这样告诉产品了,产品果然还是不满意,“我不管,我就要无限循环播放!”
只能硬着头皮搞了
社区寻找帮助
果然找到了一个类似的问题
https://github.com/facebook/fresco/issues/401
emm..不过这位仁兄遇到的问题是图片的循环次数是1,可是使用 fresco 却无限循环播放,而且这位仁兄使用的是 gif 动图,这就尴尬了,不过这些都不重要,根本问题是一致的,就是要强行设置动图的播放次数,继续往下看,找到一条点赞数比较多的回答
赶紧试一下,纳尼,怎么还是只放一遍?
仔细看了一下,这位仁兄的版本是 0.10.0
,而我们用的版本是 1.2.0
,看起来应该是 fresco 改了代码
于是看了下源码,果然不叫 mTotalLoops
,改为 mLoopCount
了
赶快修改代码,再试一次,这次果然可以了
上代码
val uri = Uri.parse("http://voddafz06jj.vod.126.net/voddafz06jj/videoPreview_1821338293_IQAB9DSR.webp")
val controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setAutoPlayAnimations(true)
.setControllerListener(object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
try {
if (imageInfo is CloseableAnimatedImage) {
val animatedImage = imageInfo.image
if (animatedImage is WebPImage) {
if (animatable != null) {
val field = AbstractAnimatedDrawable::class.java.getDeclaredField("mLoopCount")
field.isAccessible = true
field.set(animatable, Integer.MAX_VALUE)
}
}
}
} catch (e: Throwable) {
e.printStackTrace()
}
}
})
.build()
drawee_view.controller = controller
这里只针对 webp 图片设置无限循环,以免影响 gif 图片。
总结
我们遇到了 fresco 加载 webp 动图无法控制播放次数的问题,在社区的帮助下,通过反射修改循环次数,由于版本差异,查看源码改动,并最终解决问题。
不过这仅仅是一个临时方案,而且只针对特定版本有效,说不定 facebook 哪天不爽又改了代码,我们的方案就失效了。还是要按照规范,生成支持循环播放的 webp 动图。
其实今天这篇文章更想表达的是一种解决问题的思路,希望对大家有用。
网友评论