视频的关键帧和非关键帧

Android  音视频  2021年3月25日 pm10:22发布4年前 (2021)更新 城堡大人
115 0 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. 2024: Android Studio工程中.idea没有*.iml文件(0条评论)
  2. 2023: Android截图和保存图片到指定目录(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

[摘]Android 系统重启原因分析

重启原因分类1.上层造成重启system_server被杀watchdog重启重要线程阻塞2.kernel造成重启空指针非法地址3.kernel watchdog造成重启,原因不确定内存原因nand驱动log查看步骤及关键字1. 重启后的kernel.log或...

Android存储单位转换

G M K B 单位之间转换,直接上代码 // storage, G M K B public static String convertStorage(long size) { long kb = 1024; long mb = kb <...

[代码片段]MediaCode 播放Video中的音频

前言这就只做使用MediaCodec+AudioTrack播放Video中的音频正文原理通过MediaExtractor获取媒体的编码信息[Track索引,MediaMime,MediaFormat]根据编码信息进行创建MediaCodec在子线程循环dequeueInputBuff...

MediaPlayer java层介绍

前言Android中经常用MediaPlayer控制音频/视频文件和流的播放。虽然经常用,但没怎么看其源码,今天有空记录一下,方便自己查阅。正文本篇涉及的源码目录frameworks\base\media\java\android\media\MediaPlayer.javaPS:只是...

windows下FFmpeg使用以及ffmpeg抽取视频的关键帧

FFmpeg 简介FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它包括了目前领先的音/视频编码库libavcodec。FFmpeg是在 Linux 下开发出来的,但它可以在包括 Windows 在内的大多数操作系统中编译。这个项目是由 Fabrice ...

Android includeFontPadding属性的介绍

前言Android开发中,我们知道TextView显示文本时是存在留白的,如图一的第一行[读书导航],明显比第二行“高大威猛”些。虽然TextView默认存在留白,正常情况下的影响可以忽略不计,但如果换了个别字体后,如图二的第一行[读书导航],加上字体设计也存在留白,导致TextView占用的位...