前些天有个师弟(在做一个仿LinkInEyes行车记录仪的app)问我怎么获取视频缩略图,起初以为很简单,就找了个常用的解决方案(用户获取正常的视频文件的缩略图):

  1. 方案1:
private void initView() {    imgPic = (ImageView) findViewById(R.id.img_pic);    seekbar = (SeekBar) findViewById(R.id.seekbar);    mmr = new MediaMetadataRetriever();    mmr.setDataSource("/sdcard/3.mp4");    // 取得视频的长度(单位为毫秒)    String time = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);    seekbar.setMax(Integer.parseInt(time) * 1000);    bt = (Button) findViewById(R.id.bt);    bt.setOnClickListener(new OnClickListener() {        @Override        public void onClick(View v) {        Toast.makeText(MainActivity.this, " " + seekbar.getProgress(), 1).show();        Bitmap bitmap = mmr.getFrameAtTime(seekbar.getProgress(),                        MediaMetadataRetriever.OPTION_CLOSEST_SYNC);        // Bitmap bitmap = mmr.getFrameAtTime(seekbar.getProgress());        imgPic.setImageBitmap(bitmap);    System.out.println(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE)+ "");    System.out.println(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE)+ "");//  mmr.release();    }    });}

要求android api>=10

  1. 方案2:

ThumbnailUtils.createVideoThumbnail(filePath, kind);方法获取

 public static Bitmap createVideoThumbnail(String filePath, int kind) {        Bitmap bitmap = null;        MediaMetadataRetriever retriever = new MediaMetadataRetriever();        try {            retriever.setDataSource(filePath);            bitmap = retriever.getFrameAtTime(-1);        } catch (IllegalArgumentException ex) {            // Assume this is a corrupt video file        } catch (RuntimeException ex) {            // Assume this is a corrupt video file.        } finally {            try {                retriever.release();            } catch (RuntimeException ex) {                // Ignore failures while cleaning up.            }        }        if (bitmap == null) return null;        if (kind == Images.Thumbnails.MINI_KIND) {            // Scale down the bitmap if it's too large.            int width = bitmap.getWidth();            int height = bitmap.getHeight();            int max = Math.max(width, height);            if (max > 512) {                float scale = 512f / max;                int w = Math.round(scale * width);                int h = Math.round(scale * height);                bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);            }        } else if (kind == Images.Thumbnails.MICRO_KIND) {            bitmap = extractThumbnail(bitmap,                    TARGET_SIZE_MICRO_THUMBNAIL,                    TARGET_SIZE_MICRO_THUMBNAIL,                    OPTIONS_RECYCLE_INPUT);        }        return bitmap;    }

该方法在2.x系统下可用,API LEVEL > 14时却只能返回null

http://my.oschina.net/kylinhuang/blog/472757?fromerr=vASTONAf

  1. 方案3

使用开源代码:MediaMetadataRetriever

private Bitmap getBitMap() {    Bitmap b = null;    // Retrieve all metadata.    List<Metadata> metadata = new ArrayList<Metadata>();    if (mUri == null) return null;    FFmpegMediaMetadataRetriever fmmr = new FFmpegMediaMetadataRetriever();    try {        fmmr.setDataSource(mUri);        for (int i = 0; i < Constants.METADATA_KEYS.length; i++) { //注意            String key = Constants.METADATA_KEYS[i];            String value = fmmr.extractMetadata(key);            if (value != null) {                metadata.add(new Metadata(key, value));                Log.i(MetadataLoader.class.getName(), "Key: " + key                        + " Value: " + value);            }        }        b = fmmr.getFrameAtTime();        if (b != null) {            Bitmap b2 = fmmr.getFrameAtTime(seekbar.getProgress(),                    FFmpegMediaMetadataRetriever.OPTION_CLOSEST_SYNC);            if (b2 != null) {                b = b2;            }        }        if (b != null) {            metadata.add(new Metadata("image", b));            Log.i(MetadataLoader.class.getName(), "Extracted frame");        } else {            Log.e(MetadataLoader.class.getName(), "Failed to extract frame");        }    } catch (IllegalArgumentException ex) {        ex.printStackTrace();    } finally {        fmmr.release();    }    return b;}

fmmr.setDataSource(mUri);中uri支持的文件类型 file, http, https, mms and mmsh 支持的编码格式(音频&视频): aac, acc+, avi, flac, mp2, mp3, mp4, ogg, 3gp and more! 扩展支持:
开源地址:https://github.com/wseemann/FFmpegMediaMetadataRetriever
備份地址:https://github.com/qq179157977/FFmpegMediaMetadataRetriever

理论上,进过测试以上三个方案,基本的可以获取网络或本地的map4,avi等视频的缩略图了。
但是师弟说还是获取不了,因为他获取到的是一个thm文件(idr流返回),这种文件不是视频文件,是是MP4或者MPG视频文件的索引文件,用以上三种方法根本获取不到缩略图,我就觉得奇怪,想起强大的ffmpeg也可以获取缩略图,于是下载了一个命令行的ffmpeg开始尝试获取缩略图:
先将文件放到c盘,切换到c盘(ffmpeg也在c盘),运行:
ffmpeg -i C:\fengkai.htm -y -f image2 -t 0.001 -s 352x240 a.jpg
运行完毕,出现了a.jpg,还真的可以获取htm文件的缩略图

但是,ffmpeg命令要在android上运行,需要将ffmpeg(linux版)文件放到一个目录,然后用root权限给予ffmpeg执行权,才可以调用上述获取缩略图命令,原因是系统没有ffmpeg命令~

这是只能继续找到不需要权限又能通过ffmpeg获取缩略图的demo了,找了一段时间,找到一个外国人写的牛逼开源项目:
https://github.com/WritingMinds/ffmpeg-android-java

下载测试app

运行app,输入框输入:-
i /sdcard/test.asf -y -f image2 -t 0.001 -s 352x240 /sdcard/a.jpg
执行完毕,sdcard生成缩略图,棒!成功了!

附录
thm测试文件

参考:
http://my.oschina.net/kylinhuang/blog/472757?fromerr=vASTONAf
http://www.tuicool.com/articles/uqmUFfY
http://helloandroid.iteye.com/blog/1753355

更多相关文章

  1. android 多线程下载 显示进度 速度
  2. Android的SD卡文件读写
  3. 关于Android文件Apk下载的那点事
  4. Android获取LayoutInflater对象的方法总结
  5. Android(安卓)Studio添加assets文件夹
  6. 关于Android(安卓)列表多布局的那些事
  7. 四大组件_Service_AIDL_1
  8. Android(安卓)将assets中的文件复制到外置sdcard卡
  9. 查看 android 现在有什么分支

随机推荐

  1. Android应用如何支持屏幕多尺寸多分辨率
  2. Android系统概述
  3. Android中可以做的两件坏事---破解锁屏密
  4. Tim Bray概括Android生态
  5. Android网络编程之Http通信
  6. [置顶] Android(安卓)Scroll详解(三):Andr
  7. Android开发小记--开发实用工具类--数据
  8. Android中的网络时间同步 !!!!!!!!
  9. Android中的一些重要概念
  10. 2013年3月17日----Android主题(Theme)实