视频的关键帧和非关键帧

Android 91es.com@站长2021年3月25日 pm10:22发布1年前 (2023)更新
0
导航号,我的单页导航
目录

前言

项目中有时候需要获取视频封面(缩略图,类似于图片列表),并展示给用户观看。

下面是整理一下自己测试用的。

总结

目前我知道的就有如下两种方式,但对我来说不是太理想,不知道是否还有其他的更有效的方式获取视频封面,如果有知道的请留言,谢谢。

  1. 使用ThumbnailUtils的createVideoThumbnail 这种方式获取存在一定的缺陷,因为很多前面都是黑色的。
  2. 使用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。

  1. MINI_KIND 宽是512,但高没有固定的缩略图
  2. FULL_SCREEN_KIND 完整大小的图片
  3. 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) 
  1. 第一个参数 :

是传入截取时间,只能是us(微秒)

  1. 第二个参数

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;
    }
小结一下

使用这种方式,可以满足客户,但缺点也比较明显:效率低和耗时。

参考文章

  1. Android获取视频的关键帧和非关键帧,提取视频封面
  2. ThumbnailUtils工具类整理
  3. Android 获取视频关键帧代码

版权声明 1、 本站名称 91易搜
2、 本站网址 https://www.91es.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权请留言
4、 本站禁止发布或转载任何违法的相关信息,如有发现请向站长举报
导航号,我的单页导航

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

暂无评论...