android获取mp4视频文件总时长和视频宽高,MediaMetadataRetriever类、方法以及使用详解

2019-12-19 00:35:10

android使用 MediaMetadataRetriever 获取视频文件的 总时长 和视频的分辨率。

根据该方式获取视频信息可以看出不仅仅可以获取时长和分辨率,还能获取到其他的一些视频信息,不错还是很强大的,不用自己去解析mp4文件了。此demo只是获取的mp4文件,其他的多媒体文件也可以获取到相应信息,比如mp3;

private void  getPlayTime(String mUri)
    {
        android.media.MediaMetadataRetriever mmr = new android.media.MediaMetadataRetriever();
        try {
            if (mUri != null) 
            {
                HashMap<String, String> headers = null;
                if (headers == null) 
                {
                    headers = new HashMap<String, String>();
                    headers.put("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.4.2; zh-CN; MW-KW-001 Build/JRO03C) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/1.0.0.001 U4/0.8.0 Mobile Safari/533.1");
                }
                mmr.setDataSource(mUri, headers);
            } else 
            {
                //mmr.setDataSource(mFD, mOffset, mLength);
            }

            String duration = mmr.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_DURATION);//时长(毫秒)
            String width = mmr.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);//宽
            String height = mmr.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);//高
            
            Toast.makeText(MainActivity.this, "playtime:"+ duration+"w="+width+"h="+height, Toast.LENGTH_SHORT).show();

        } catch (Exception ex) 
        {
            Log.e("TAG", "MediaMetadataRetriever exception " + ex);
        } finally {
            mmr.release();
        }

    }


MediaMetadataRetriever类简单介绍

(1)属于在android api的那个包下:`android.media.MediaMetadataRetriever`

(2)类简单介绍:

 MediaMetadataRetriever类提供了用于从输入媒体文件检索帧和元数据的统一接口。

(3)这个是android提供的类,用来获取本地和网络media相关文件的信息

1

2

3

4

MediaMetadataRetriever常量以及属性进行简单介绍

(1)METADATA_KEY_ALBUM :检索数据源的专辑标题信息的元数据键。

(2)METADATA_KEY_ALBUMARTIST: 检索与数据源相关的表演者或艺术家的信息的元数据键。

(3)METADATA_KEY_ARTIST:检索有关数据源的艺术家的信息的元数据键。

(4)METADATA_KEY_AUTHOR:检索有关数据源作者的信息的元数据键

(5)METADATA_KEY_BITRATE:此键检索平均比特率(以比特/秒),如果可用的话。

(6)METADATA_KEY_CD_TRACK_NUMBER:元数据关键字,用于检索描述原始数据记录中音频数据源的顺序的数字字符串。

(7)METADATA_KEY_COMPILATION:检索音乐专辑编辑状态的元数据键

(8)METADATA_KEY_COMPOSER:检索有关数据源的作曲家的信息的元数据键

(9)METADATA_KEY_DATE:检索或创建数据源时的日期的元数据键

(10)METADATA_KEY_DISC_NUMBER:用于检索描述音频数据源的集合的哪一部分的数字字符串的元数据键

(11)METADATA_KEY_DURATION:检索数据源回放持续时间的元数据键

 (12) METADATA_KEY_GENRE:检索数据源的内容类型或类型的元数据键

(13) METADATA_KEY_HAS_AUDIO:如果存在此密钥,则媒体包含音频内容

(14)METADATA_KEY_HAS_VIDEO:如果存在此密钥,则媒体包含视频内容

(15)METADATA_KEY_LOCATION:此键检索位置信息,如果可用的话。该位置应根据ISO-6709标准,在MP4/3GP框“@ XYZ”下指定。例如,经度为90度和纬度为180度的位置将被检索为“-90+180”。

(16)METADATA_KEY_MIMETYPE:检索数据源MIME类型的元数据键。一些示例MIME类型包括:"video/mp4", "audio/mp4", "audio/amr-wb"

(17)METADATA_KEY_NUM_TRACKS:元数据键,用于检索数据源(如MP4或3GPP文件)中的音轨的数目,如音频、视频、文本。

(18)METADATA_KEY_TITLE:检索数据源标题的元数据键

(19) METADATA_KEY_VIDEO_HEIGHT:如果媒体包含视频,则该键检索其高度

(20)METADATA_KEY_VIDEO_ROTATION:此键检索视频旋转角度的程度,如果可用的话。视频旋转角度可以是0, 90, 180度,也可以是270度

(21)METADATA_KEY_VIDEO_WIDTH:如果媒体包含视频,则该密钥检索其宽度

(22)METADATA_KEY_WRITER:检索数据源的作者(如歌词作者)信息的元数据键

(23) METADATA_KEY_YEAR:检索创建或修改数据源的一年的元数据密钥

(24) OPTION_CLOSEST:此选项与GETFrimeTimeTime(long,int)一起使用,以检索与最接近或给定时间的数据源相关联的帧(不一定是关键帧)

(25)OPTION_CLOSEST_SYNC:(时间)或给定时间的数据源相关联的同步(或密钥)帧。

(26)OPTION_NEXT_SYNC:此选项与GETFrimeTimeTime(long,int)一起使用,以检索与数据源相关联的同步(或密钥)帧,该数据源位于或在给定的时间之后。

(27)OPTION_PREVIOUS_SYNC:此选项与GETFrimeTimeTime(long,int)一起使用,以检索与数据源相关联的同步(或密钥)帧,该数据源正好位于给定时间之前或给定时间

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

MediaMetadataRetriever 获取这个对象的方法

public MediaMetadataRetriever ()

1

MediaMetadataRetriever中的使用方法进行详细介绍

(1)public String extractMetadata (int keyCode)


方法描述:在 setDataSource()之后调用此方法。此方法检索与键值相关联的元数据值。当前支持的键代码被列为Meta DATAXXXX常量。使用任何其他值,它返回空指针



(2)public byte[] getEmbeddedPicture ()

方法描述:在 setDataSource()之后调用此方法。此方法找到与数据源相关联的可选图形或相册/封面艺术。如果有超过一张照片,(任何)其中一个被退还


(3)public Bitmap getFrameAtTime (long timeUs, int option)

方法介绍:在SETDATABORCEL()之后调用此方法。该方法通过考虑给定的选项,在给定的时间位置找到具有代表性的帧,并将其作为位图返回。这对于生成输入数据源的缩略图或在给定的时间位置获得和显示帧是有用的。

timeUs :帧将被检索的时间位置。当在给定的时间位置检索帧时,不能保证数据源具有位于该位置的帧。当这种情况发生时,附近的一个框架将被返回。如果TimeSo为负,则将忽略时间位置和选项,并且可以将实现视为代表的任何帧返回

option:关于如何找到框架的提示。如果希望检索一个具有比TimeS更早或相同的时间戳的同步帧,请使用opthyPyviousSyc。如果希望检索一个比TimeS晚于或相同的时间戳的同步帧,请使用opthyNXTySyc。如果想检索一个同步帧,它的时间戳与TimeS最接近或相同,则使用opthyLoestStSyc。如果希望检索一个可能是或可能不是同步帧但与TimeS最接近或相同的帧,则使用OpthOffice最接近。如果没有时间同步帧,OpTestIm最常用的性能开销与其他选项相比更大


(4)public Bitmap getFrameAtTime (long timeUs)

方法介绍:在SETDATABORCEL()之后调用此方法。如果可能的话,该方法找到一个接近给定时间位置的有代表性的帧,并将其作为位图返回。这对于生成输入数据源的缩略图是有用的。如果不关心帧是如何找到的,只要它接近给定的时间,调用这个方法;否则,请调用GETFrimeTimeTime

timeUs :帧将被检索的时间位置。当在给定的时间位置检索帧时,不能保证数据源具有位于该位置的帧。当这种情况发生时,附近的一个框架将被返回。如果TimeSo为负,则将忽略时间位置和选项,并且可以将实现视为代表的任何帧返回


(5)public Bitmap getFrameAtTime ()

方法介绍:在SETDATABORCEL()之后调用此方法。如果可能的话,该方法在任何时间位置找到一个有代表性的帧,并将其作为位图返回。这对于生成输入数据源的缩略图是有用的。如果不关心框架的位置,请调用此方法;否则,请调用GETFrimeTimeTime:(long)或GETFrimeTimeTime(long,int)


(6)public void release ()

方法介绍:当一个对象完成时调用它。此方法释放内存内部分配的内存


(7)public void setDataSource (FileDescriptor fd, long offset, long length)

fd 要播放的文件的文件描述符

offset 开始位置

length 结束位置


(8)public void setDataSource (String path)

 方法介绍:这个方法主要是设置media类型文件的路径,包括音视频等


(9)public void setDataSource (FileDescriptor fd)

 方法介绍:这个是是设置文件的描述符


(10)public void setDataSource (String uri, Map<String, String> headers)

方法介绍:设置网络音视频url地址,第二个参数是设置参数的请求头


(11)public void setDataSource (Context context, Uri uri)

方法介绍:设置网络media文件的url路径

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

MediaMetadataRetriever简单使用

(1)第一个案例:获取网络视频的第一帧图片


  public static Bitmap getBitmap(Context context,String url, boolean isSD) {

    Bitmap bitmap = null;

    //MediaMetadataRetriever 是android中定义好的一个类,提供了统一

    //的接口,用于从输入的媒体文件中取得帧和元数据;

    MediaMetadataRetriever retriever = new MediaMetadataRetriever();

    try {

        if (isSD){

            //()根据文件路径获取缩略图

            retriever.setDataSource(context, Uri.fromFile(new File(url)));

        }else {

            //根据网络路径获取缩略图

            retriever.setDataSource(url, new HashMap());

        }

        //获得第一帧图片

        bitmap = retriever.getFrameAtTime();

    } catch (IllegalArgumentException e) {

        e.printStackTrace();

    } finally {

        retriever.release();

    }

    return bitmap;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

(2)第二个案例:获取音频文件的时间:


` public static String getRingDuring(String mUri) {

    String duration = null;

    android.media.MediaMetadataRetriever mmr = new android.media.MediaMetadataRetriever();


    try {

        if (mUri != null) {

            HashMap<String, String> headers = null;

            if (headers == null) {

                headers = new HashMap<String, String>();

            }

            mmr.setDataSource(mUri, headers);

        }


        duration = mmr.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_DURATION);

    } catch (Exception ex) {

    } finally {

        mmr.release();

    }

    return duration;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

`

以上的这两个案例是获取网络url的信息,本地的获取方法在这里我就不做阐述了,是和上面的用法几乎一样


注意:获取网络url现在不支持https协议的获取


  • 2017-09-14 10:18:25

    15分钟成为Git专家

    不管是以前使用过 Git 还是刚开始使用这个神奇的版本控制工具的开发者,阅读了本文以后都会收获颇丰。如果你是应一名有经验的 GIT 使用者,你会更好的理解 checkout -> modify -> commit 这个过程。如果你刚开始使用 Git,本文将给你一个很好的开端。

  • 2017-09-28 16:42:57

    Linux vmstat命令实战详解

    vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令,一个是Linux/Unix都支持,二是相比top,我可以看到整个机器的CPU,内存,IO的使用情况,而不是单单看到各个进程的CPU使用率和内存使用率(使用场景不一样)。

  • 2017-10-13 16:21:29

    Activity的四种launchMode

    launchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个task里。这里简单介绍一下task的概念,task是一个具有栈结构的对象,一个task可以管理多个Activity,启动一个应用,也就创建一个与之对应的task。

  • 2017-10-16 16:45:45

    Android开发技巧:Application和Instance

    在开发过程中,我们经常会需要用到一些全局的变量或者全局的“管理者”,例如QQ,需要有一个“全局的管理者“保存好友信息,各个activity即可直接通过该”管理者“来获取和修改某个好友信息,显然,这样的一个好友信息,保存到某一个具体的activity里面,然后依靠activity的intent来传递参数是不合适。我们有两种方法来实现这样一个全局的管理者,一种是使用C++/Java中常用的单例模式,另一种是利用Android的Application类,下面一一阐述。

  • 2017-11-01 01:30:45

    解决第三方包内jar包冲突

    这个问题就是因为引入jar包的冲突,这时我们可以在build.gradle中添加如下代码,下方单独的是添加的代码

  • 2017-11-06 01:00:17

    撤销git add

    如何撤销git add,不小心执行了git add . 操作,但是又不能提交所有的文件,因为对应不同的分支,现在怎么样可以将git add 撤销回来

  • 2017-11-10 00:06:15

    CORS: credentials mode is 'include'

    XMLHttpRequest cannot load http://localhost/Foo.API/token. The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:5000' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.