当前位置: 首页 > 编程笔记 >

android提取视频多张图片和视频信息实例

公西宏毅
2023-03-14
本文向大家介绍android提取视频多张图片和视频信息实例,包括了android提取视频多张图片和视频信息实例的使用技巧和注意事项,需要的朋友参考一下

话说2016年的直播比较火,2017年短视频又火了。但对于开发者来说隐藏在这背后的技术才是我们所关心的,毕竟我们是靠技术吃饭的。

现在在安卓中多媒体服务比较强大,而与视频有关的视频基本处理技术有必要学习一下。我前段时间也在做有关视频的一些需求,当然也涉及本文的标题内容。

经测试和研究发现在android中提取视频图片的方法只有MediaMetadataRetriever这个类比较靠谱简单实用。当然OpenGL-也可以做到哈!(后者不展开介绍),

最后会把完整的demo献上。

效果图

技术需求

  1. 需求一:给你一个视频提取第一个关键帧图片作为视频的封面,好处呢!?就是当没有播放的时候显示视频的首帧图片,当点击播放按钮时(或者自动播放)视频和首帧图片能连惯起来,是个很不错的体验。
  2. 需求二:提取多张图片,用户可以滑动这些缩略图来查看视频的大体内容,然后截取指定的视频区域进行编辑,这个需求类似:微信的小视频编辑界面。这个会在第二篇文章中实现。实现高速度提取视频图片。
  3. 需求三:提取视频的基本信息,比如宽高,视频的时长。这个主要用于上传视频文件时的参数提交,然后展示的时候用视频宽高做UI特效,比如不规则之美-瀑布流

调研

先看第3个问题,这个比较简单。主要是MediaMetadataRetriever这个系统API类。

大体意思就是:给定一个媒体文件,它能检索/输出一些元数据和帧。有点意思哈,它加载了动态库media_jni,可见它是一个十分接近底层的一个类。

技术实现-视频基本信息的获取

看一下类结构,有一些常量,作为一线码农,我懂你哦。


//1.初始化
   mMetadataRetriever = new MediaMetadataRetriever();

//2.设置视频源文件mMetadataRetriever.setDataSource(file.getAbsolutePath());
//3.获取视频的宽
String w = mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
 //获取视频的高
String h = mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
 //获取视频的时长,ms
mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);

// 等等...一些其它属性,比如媒体类型(3gp,mp4) ,视频旋转角度
//4.释放资源,防止内存泄漏,养成好习惯
 mMetadataRetrieve.release();

我自己简单了写了一个util类,最后会献上。

技术实现-获取视频关键帧

直接上代码-我懂你

 public Bitmap extractFrame(long timeMs) {
    //第一个参数是传入时间,只能是us(微秒)
    //OPTION_CLOSEST ,在给定的时间,检索最近一个帧,这个帧不一定是关键帧。
    //OPTION_CLOSEST_SYNC  在给定的时间,检索最近一个同步与数据源相关联的的帧(关键帧)
    //OPTION_NEXT_SYNC 在给定时间之后检索一个同步与数据源相关联的关键帧。
    //OPTION_PREVIOUS_SYNC 在给定时间之前检索一个同步与数据源相关联的关键帧。

// Bitmap bitmap = mMetadataRetriever.getFrameAtTime(timeMs * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
    Bitmap bitmap = null;
    for (long i = timeMs; i < fileLength; i += 1000) {
      bitmap = mMetadataRetriever.getFrameAtTime(i * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
      if (bitmap != null) {
        break;
      }
    }
    return bitmap;
  }

实用的时候直接: Bitmap bitmap = extractFrame(0); fileLength为视频的时长( 毫秒数),返回bitmap ,然后你用可以操作bitmap了,比如保存到sd卡上,看你爱好了。有人问:咿,怎么for循环啊?是这样的,我遇到过有时候你传入的0,它有时候返回的bitmap为null,找不到关键帧,因此你需要多次递增1秒获取。
那么需求一的实现也OK了,但是有一点需要注意就是展示视频的控件的宽和高和盖在上面的图片的控件的宽和高一样才有你播放的时候就连贯了。

技术实现-获取视频多张图片

我相信大家都能想到需求一的for循环一下不就可以了吗,是的,没错。

首先提取图片遇到高清视频可能耗时,我经过测试用vivo-xplay-5a ,1080高清视频,提取一张图片也就是mMetadataRetriever.getFrameAtTime()方法大概90-120ms之间。

  1. 方案:因此你需要一个工作线程+handler,每提取一张保存到sd卡中,然后用handeler发送保存图片的路径展示到UI上。demo中会展示到recycleview上,然后用glide图片加载框架一张一张的显示出来。当然你也可以自己缓存mMetadataRetriever.getFrameAtTime 返回的bitmap,不过不建议这么做。
  2. 怎么循环提取,假设视频文件长度是60s,需要提取10张图片,也就是1张图片代表了6s,60/10,
for (int i = 0; i < thumbnailsCount; i++) {
      if (stop) {
        metadataRetriever.release();
        break;
      }
      long time = startPosition + interval * i;
      if (i == thumbnailsCount - 1) {
        if (interval > 1000) {
          String path = extractFrame(metadataRetriever, endPosition - 800, OutPutFileDirPath);
          sendAPic(path, endPosition - 800);
        } else {
          String path = extractFrame(metadataRetriever, endPosition, OutPutFileDirPath);
          sendAPic(path, endPosition);
        }
      } else {
        String path = extractFrame(metadataRetriever, time, OutPutFileDirPath);
        sendAPic(path, time);
      }
    }

stop是停止提取图片的标志,extractFrame方法就是metadataRetriever.getFrameAtTime()返回bitmap然后 bitmap.compress()返回保存到sd卡上的图片路径,最后sendAPic将提取的图片路径和时间加工为一个对象借助handler更新到UI线程中去,然后展示到recycleview上去,具体代码可以参考demo。这里保存的图片没有进行压缩,第二篇文章会具体讲到。

demo地址:https://github.com/ta893115871/MediaMetadataRetrieverDemo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 读取视频信息 如需获取分P,需要以不同页码多次调用本接口 — @fython 调用地址 http://api.bilibili.cn/view 需要 App Key 参数 字段 必选 类型 说明 id true int AV号 page true int 页码 fav false int 是否读取会员收藏状态 (默认 0) 返回 返回值字段 字段类型 字段说明 play int 播放次数 revi

  • 通过该接口可以获取指定用户的有效视频的信息,目前共六个版本,最新版本为V6: a.当地址为https://spark.bokecc.com/api/video/v6 需要传递以下参数 参数 说明 userid 用户 id,不可为空 videoid 视频 id,不可为空 imagetype 返回封面截图的类型,默认值:0(0:小图;1:大图) format 返回格式,xml 或 json 返回数据v

  • 读取视频排行信息 调用地址 http://api.bilibili.cn/list 需要 App Key 参数 字段 必选 类型 说明 tid true int 分类编号 new排序为必填 其他为可选 exclude_tid false int 排除分类编号 不可与tid同时使用 mid false int 只显示该帐号投稿 begin false date 起始搜索日期 (格式:YYYY-mm-

  • 通过该接口可以获取一个用户一个视频的弹幕信息, 地址为: https://spark.bokecc.com/api/video/barrage 需要传递以下参数: 参数 说明 userid 用户 id,不可为空 videoid 查询的videoid, 不可为空 starttime 开始时间,可选(yyyy-MM-dd HH:mm:ss) endtime 结束时间,可选(yyyy-MM-dd HH:

  • 获取视频打点信息 a. 通过该接口可以获取单个视频打点信息, 地址为: http://spark.bokecc.com/api/mark/video 需要传递以下参数: 参数 说明 userid 用户 id,不可为空 videoid 视频 id,不可为空 返回数据videomark包括如下字段: 字段名 字段名 markList 打点列表 markList包括如下字段: 字段名 字段名 markT

  • 通过该接口可以获取指定用户的一批有效视频(不包括删除、正在处理的视频)的信息,目前共七个版本,最新版本为V7: a.当地址为https://spark.bokecc.com/api/videos/v7 需要传递以下参数: 参数 说明 userid 用户 id,不可为空 mode 查询方式 0:指定要查询的视频的起始位置;1:指定一批视频进行查询(不传默认值为0) videoids 要查询的一批视频