MediaMetadataRetriever小试牛刀

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/submit66/article/details/53537073

           最近项目有用到音视频的录制,那么自然也是有获取录制的音视频信息的需求,同时也会有获取网络视频信息的需求了。

           其实说来获取录制时长的话,完全可以不从文件本身入手了。可以放个计时器。不过这样子也是大动干戈,也太不灵活了。然后就遇到了今天的主角了:MediaMetadataRetriever。看google对于这个类的描述MediaMetadataRetriever class provides a unified interface for retrieving frame and meta data from an input media file.大意为MediaMetadataRetriever提供了一个统一的接口用于获取输入的媒体文件的框架和元数据(英文不好,多多包涵)。可能大意就是这个类可以用于获取输入媒体文件的一些信息吧。

           其实我主要是用到了该类的两个功能了,一个是获取音视频的时长,另外一个就是获取视频某一帧的缩略图。具体看下如下代码:

     以下的NETWORK和LOCAL只是我自己定义的常量而已啦。
//根据url获取音视频时长,返回毫秒
    public long getDurationLong(String url,int type){
        String duration = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            //如果是网络路径
            if(type == NETWORK){
                retriever.setDataSource(url,new HashMap<String, String>());
            }else if(type == LOCAL){//如果是本地路径
                retriever.setDataSource(url);
            }
            duration = retriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_DURATION);
        } catch (Exception ex) {
            LogUtils.e(ex);
            LogUtils.d("nihao", "获取音频时长失败");
        } finally {
            try {
                retriever.release();
            } catch (RuntimeException ex) {
                LogUtils.e(ex);
                LogUtils.d("nihao", "释放MediaMetadataRetriever资源失败");
            }
        }
        if(!TextUtils.isEmpty(duration)){
            return Long.parseLong(duration);
        }else{
            return 0;
        }
    }
    
    //获取视频缩略图
    private Bitmap createVideoThumbnail(String url, int type) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            //将网络文件以及本地文件区分开来设置
            if (type == NETWORK) {
                retriever.setDataSource(url, new HashMap<String, String>());
            } else if(type == LOCAL){
                retriever.setDataSource(url);
            }
            bitmap = retriever.getFrameAtTime(0, MediaMetadataRetriever.OPTION_NEXT_SYNC);
        } catch (IllegalArgumentException ex) {
            LogUtils.e(ex);
            LogUtils.d("nihao", "获取视频缩略图失败");
        } finally {
            try {
                retriever.release();
            } catch (RuntimeException ex) {
                LogUtils.e(ex);
                LogUtils.d("nihao", "释放MediaMetadataRetriever资源失败");
            }
        }
        return bitmap;
    }

其实他俩基本一致只是获取音频用的是extractMetadata,而获取视频缩略图用的是getFrameAtTime;其实重点在于两个方法都对于传入的url进行了是否是网络的判断,那么接下来我们看看传入不同参数的setDataSource有什么不同吧,官方解释如下:


这个是我用于获取本地文件信息的方法,可以看下我标红的地方,path的定义是你传入的媒体问题的路径,所以就应该是对应的本地文件路径了。但是如果路径无效是会抛出异常的。


这个是我用于获取网络视频信息的方法,也可以看下我标红的部分,这个方法是从android 4.0才开始有的。另外那个第二个参数是请求数据时候携带的头信息。但是我这里没有做特殊的设置了。就传递了一个map对象;

上面是我最终的方法。但是一开始其实不是这个样子的,一开始我是没有区分网络路径和本地路径的。我只是加了sdk版本的区分而已,就是如果是4.0及其以上我用了第二个方法。在很多手机上面也没有事儿,包括本地以及网络的。可是后来用了小米4的6.0系统,以及华为mate7的6.0系统后,发现用两个参数的方法是无法获取到本地视频的信息的,会抛出illegalState的异常。因为我的apk的最低安装版本就是4.0所以其实我的判断就永远会走进两个参数的方法里面的。

        总结一下就是两个参数的方法大多数情况下既可以获取网络音视频信息,也可以获取本地音视频信息。但是在有的手机上无法获取本地视频信息。所以就要用到一个参数的方法获取本地音视频信息,且一个参数是不支持获取网络音视频信息的。所以最终就有了上面的代码。

        以上如有不对之处,欢迎批评指正。

没有更多推荐了,返回首页