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协议的获取


  • 2020-01-04 08:19:28

    flex 布局子内容p元素被撑开

    父元素 flex 布局,子元素有一行文字,将其设置为不换行隐藏后显示省略号,但实际并不是想象的那样,而导致布局变形。改怎么办?

  • 2020-01-04 18:44:26

    vue中computed源码,工作原理

    (Obeject.defineProperty是Object的一个方法,第一个参数是对象名称,第二个参数是要设置的属性名,第三个参数是一个对象,它可以设置这个属性是否可修改、可写等,而这篇文章主要使用的是Obeject.defineProperty的访问器属性,感兴趣的朋友可以自行google或者查看Js高及程序设计)

  • 2020-01-06 23:02:42

    Updating Homebrew... 更新了镜像依然卡死

    使用brew install [软件包]安装软件包时,卡在Updating Homebrew... 或输入`brew update`更新brew,半天没反应.产生原因一般是在国内访问官方 更新源获取资源太慢,解决方案可以采用更换国内镜像更新源.

  • 2020-01-07 10:06:00

    vue重定向beforeRouterEnter与replace的使用

    一个登录页面,只有第一次才会出现,一旦出现过,以后再也不会出现,即使是输入该页面的url也不会跳转到该页面,只会跳转到指定的其他页面;

  • 2020-01-07 10:14:07

    vue强制刷新组件 销毁和重建

    很多时候,通过重置数据将页面重置时,子组件可以提供重置的方法,或者提供props重置自己的状态。但是相对麻烦,那可以使用强制刷新来实现刷新组件。

  • 2020-01-07 10:17:42

    vue钩子函数beforeRouteUpdate没有反应

    由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 可以访问组件实例 `this`