Android 获取视频(本地、网络)的第一帧

转载:https://blog.csdn.net/w690333243/article/details/78593654

可以获取网络视频,本地视频第一帧

使用:

imageView.setImageBitmap(ImageUtil.createVideoThumbnail(urlPath,MediaStore.Images.Thumbnails.MINI_KIND));
public static Bitmap createVideoThumbnail(String filePath, int kind)
    {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try
        {
            if (filePath.startsWith("http://")
                    || filePath.startsWith("https://")
                    || filePath.startsWith("widevine://"))
            {
                retriever.setDataSource(filePath, new Hashtable<String, String>());
            }
            else
            {
                retriever.setDataSource(filePath);
            }
            bitmap = retriever.getFrameAtTime(0, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); //retriever.getFrameAtTime(-1);
        }
        catch (IllegalArgumentException ex)
        {
            // Assume this is a corrupt video file
            ex.printStackTrace();
        }
        catch (RuntimeException ex)
        {
            // Assume this is a corrupt video file.
            ex.printStackTrace();
        }
        finally
        {
            try
            {
                retriever.release();
            }
            catch (RuntimeException ex)
            {
                // Ignore failures while cleaning up.
                ex.printStackTrace();
            }
        }

        if (bitmap == null)
        {
            return null;
        }

        if (kind == MediaStore.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 == MediaStore.Images.Thumbnails.MICRO_KIND)
        {
            bitmap = ThumbnailUtils.extractThumbnail(bitmap,
                    96,
                    96,
                    ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
        }
        return bitmap;
    }

其中压缩图片处的代码可以换成这个 bitmap = compressImage(bitmap); 在网上搜索到的质量压缩

/**
     * 质量压缩方法
     *
     * @param image
     * @return
     */
    public static Bitmap compressImage(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        int options = 90;

        while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset(); // 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
            options -= 10;// 每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

查看源码可以发现

//查看源码可以看到,retriever.setDataSource(filePath, new Hashtable<String, String>());如果setDataSource方法传递了Hashtable,会调用
 _setDataSource(
                MediaHTTPService.createHttpServiceBinderIfNecessary(uri),
                uri,
                keys,
                values);
                既然用到了MediHTTPService,http中的东西,肯定和网络有关了。所以可以获取到网络视频的第一帧

如果是本地视频,直接使用

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            retriever.setDataSource(videoFilePath);
            Bitmap bmp = retriever.getFrameAtTime(0, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
            imageView.setImageBitmap(bmp);

即可。
对于本地视频,如下方式只能获取到最大关键帧

Bitmap bmp = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Images.Thumbnails.MINI_KIND);
imageView.setImageBitmap(bmp);

另外网上很多说 使用MediaMetadataRetriever的拓展类:FFmepgMediaMetadataRetriever来取更多格式的视频文件缩略图,还没有尝试,大家可以尝试下。

我在录制视频后,显示视频第一帧的过程中报错(这里介绍处理问题的方法)

java.lang.RuntimeException: setDataSource failed: status = 0xFFFFFFEA and I'd like to know what this status is. I'm using the function MediaMetaDataRetriever.setDataSource(String filePath)

当我看到这个异常后,第一反应就是网上搜索这个异常,但是一直没找到合适的答案。
其实看到这个异常后的第一步应该是看自己录制的视频是否正常,因为显示视频第一帧的方法是没有问题的,如果录制的视频就不正常,肯定显示不出来第一帧,而且会报异常,但是如果你去分析这个异常的话,是很难分析出来的(如果视频录制的正常),但是恰好是录制的视频不正常引起的。
录制视频时使用1280 * 720的分辨率后,录制视频正常。之前使用的是640*480 结果视频没录制成功

startInput(472) failed: other input 468 already started 在使用audioRecord.startRecording()方法时,提示此错误(不是抛出的异常),是因为上次录音没有很好的释放资源引起的

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值