• android 获取视频缩略图终极解决方案(ffmpeg)


    http://blog.csdn.net/u010499721/article/details/50338623

    前些天有个师弟(在做一个仿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();
        }
        });
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    要求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;
        }
    • 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
    • 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

    该方法在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;
    }
    • 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
    • 40
    • 41
    • 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
    • 40
    • 41

    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

    http://i.imgur.com/cP4WhLn.gif

    下载测试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

  • 相关阅读:
    gdb段错误
    gdb断点
    init.d详解
    asp.net中的服务器端控件 textbox 设为只读属性后无法获取 javascript给其赋的值
    关于“金点子”征集通知
    Notepad++ SQL Assistant
    IoC Container Benchmark Unity, Windsor, StructureMap and Spring.NET
    如何判断个人电脑是多少位(32位?还是64位系统)
    批量执行SQL文件
    SQL Server 2005 dev 开发板 版本说明
  • 原文地址:https://www.cnblogs.com/jukan/p/6482895.html
Copyright © 2020-2023  润新知