前言
项目中有时候需要获取视频封面(缩略图,类似于图片列表),并展示给用户观看。
下面是整理一下自己测试用的。
总结
目前我知道的就有如下两种方式,但对我来说不是太理想,不知道是否还有其他的更有效的方式获取视频封面,如果有知道的请留言,谢谢。
- 使用ThumbnailUtils的createVideoThumbnail 这种方式获取存在一定的缺陷,因为很多前面都是黑色的。
- 使用MediaMetadataRetriever可以指定某个时间点获取对应的图像帧,这个可以减少获取不到概率。
正文
使用ThumbnailUtils
/** * 获取视频第一帧 * * @param path * @return */ public Bitmap getVideoThumbnail(String path) { if (TextUtils.isEmpty(path)) { return null; } Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MINI_KIND); return bitmap; }
除了Thumbnails.MINI_KIND,还有Thumbnails.FULL_SCREEN_KIND 和Thumbnails.MICRO_KIND。
- MINI_KIND 宽是512,但高没有固定的缩略图
- FULL_SCREEN_KIND 完整大小的图片
- MICRO_KIND 96 *96的缩略图
由于现实的高宽可以固定,同时我们不需要512或者固定高宽,因此需要做一定的转换。
//对获取的图进行一定的转换 if (null != bitmap) { bitmap = ThumbnailUtils.extractThumbnail(bitmap, DEFAULT_WIDTH_125, DEFAULT_HEIGHT_100, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); }
小结一下:
这种方大多数图片是可以解析出来的,但总有一部分无法提取封面,导致用户不满意。
使用MediaMetadataRetriever
由于通过上面方式,不能有效获取封面(反正客户不接受),因此改为使用getFrameAtTime()通过指定时间获取对应的一帧。
getFrameAtTime()方法具体参数如下:
public Bitmap getFrameAtTime(long timeUs, int option)
- 第一个参数 :
是传入截取时间,只能是us(微秒)
- 第二个参数
OPTION_CLOSEST
在给定的时间,检索最近一个帧,这个帧不一定是关键帧。
OPTION_CLOSEST_SYNC
在给定的时间,检索最近一个同步与数据源相关联的的帧(关键帧)。
OPTION_NEXT_SYNC
在给定时间之后检索一个同步与数据源相关联的关键帧。
OPTION_PREVIOUS_SYNC
在给定时间之前检索一个同步与数据源相关的关键帧
这里为了提取我们想要的帧,不使用关键帧,所以用 OPTION_CLOSEST
/** * 获取缩略图,从第四秒获取,可以获取大多数的帧 * 缺点:低效率和耗时 * @param path * @return */ public Bitmap getVideoThumbnail2(String path) { if (TextUtils.isEmpty(path)) { return null; } MediaMetadataRetriever mMediaMetadataRetriever = new MediaMetadataRetriever(); try { if (null != mMediaMetadataRetriever) { Bitmap thumbTempBitmap = null; mMediaMetadataRetriever.setDataSource(path); //跳过前面7秒,这种做法是规律大部分视频前面几秒没有图像的帧,但缺点就是效率低和耗时 for (int i = 8; i < 10; i++) { thumbTempBitmap = mMediaMetadataRetriever.getFrameAtTime(i * 1000 * 1000, MediaMetadataRetriever.OPTION_CLOSEST); if (null != thumbTempBitmap) { break; } } if (null != thumbTempBitmap) { return thumbTempBitmap; } } } catch (Exception e) { e.printStackTrace(); } finally { if (null != mMediaMetadataRetriever) { mMediaMetadataRetriever.release(); } } return null; }
小结一下
使用这种方式,可以满足客户,但缺点也比较明显:效率低和耗时。
参考文章
© 版权声明