Android音视频开发之三种方式获取视频某一帧封面
前言:在Android开发中获取视频的某一帧很常见,比如直播或者播放视频时暂停时显示当前一帧的封面,或者视频暂停时从视频列表进入详情然后再返回时显示之前暂停的界面,今天来=先说下三种方式实现获取视频某一帧显示封面,然后说遇到的问题.1.使用Glide获取视频某一帧:/*** 使用Glide方式获取视频某一帧* @param context 上下文* @param uri 视频地址* @param
·
目录
2.使用MediaMetadataRetriever方式获取视频某一帧:
4.1 使用glide和MediaMetadataRetriever方式时由于时间是微妙所以需要换算成毫秒*1000
4.3 使用MediaMetadataRetriever方式会出现卡顿现象,由于是网络在线查询,所以网络不好时查询很慢,一般会用rxjava异步去查询,列表不建议用这个。
5.从上面5-1、5-2、5-3的截图可以看出封面是实时显示的,很符合需求视频暂停到那一秒就显示当前某一帧的封面,而且不会出现卡顿.
前言:
在Android开发中获取视频的某一帧很常见,相信大家都用过腾讯视频、爱奇艺、优酷等,里面会有直播或者播放视频时暂停时显示当前一帧的封面,或者视频暂停时从视频列表进入详情然后再返回时显示之前暂停的界面。今天先说下三种方式实现获取视频某一帧显示封面,然后说遇到的问题.
1.使用Glide获取视频某一帧:
/** * 使用Glide方式获取视频某一帧 * @param context 上下文 * @param uri 视频地址 * @param imageView 设置image * @param frameTimeMicros 获取某一时间帧. */ public static void loadVideoScreenshot(final Context context, String uri, ImageView imageView, long frameTimeMicros) { RequestOptions requestOptions = RequestOptions.frameOf(frameTimeMicros); requestOptions.set(FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST); requestOptions.transform(new BitmapTransformation() { @Override protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { Log.d("--使用glide方式--", "高度为" + toTransform.getHeight() + "寛度为" + toTransform.getWidth()); return toTransform; } @Override public void updateDiskCacheKey(MessageDigest messageDigest) { try { messageDigest.update((context.getPackageName() + "RotateTransform").getBytes("utf-8")); } catch (Exception e) { e.printStackTrace(); } } }); Glide.with(context).load(uri).apply(requestOptions).into(imageView); }
1.1打断点可以看到bitmap图片信息如下:
1.2 glide输出图片宽高:
1.3 输出的日志如下:
2.使用MediaMetadataRetriever方式获取视频某一帧:
/** * 使用MediaMetadataRetriever获取视频指定微秒处的帧图片 * url 网络url *timeUs 微秒 */ @SuppressLint("LongLogTag") public static Bitmap GetFramePictures(String url, long timeUs){ Bitmap videoShortCut = null; String width; String height; MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever(); try { if (url != null) { HashMap<String, String> headers; headers = new HashMap<>(); 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"); mediaMetadataRetriever.setDataSource(url, headers); } else { //mmr.setDataSource(mFD, mOffset, mLength); } videoShortCut = mediaMetadataRetriever.getFrameAtTime(timeUs, MediaMetadataRetriever.OPTION_CLOSEST); width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); Log.d("--使用MediaMetadata方式--","图片高度为:" + width + "图片宽度为:" + height); } catch (IllegalArgumentException e) { Log.e("setFrameAtTimeWithView ERROR:" , e.toString(), e); } mediaMetadataRetriever.release(); return videoShortCut; }
2.1 断点截图如下:
图2-1
图2-2
2.2 日志打印如下:
3.使用TextureView方式获取视频某一帧:
public Bitmap getFrontCoverBitmap() { Bitmap bitmap = null; if (textureView != null) { bitmap = textureView.getBitmap(); } return bitmap; }
3.1 调试输出图片bitmap信息:
图5-1
图5-2
图5-3
3.2 日志打印图片宽高为:
4.遇到的问题如下:
4.1 使用glide和MediaMetadataRetriever方式时由于时间是微妙所以需要换算成毫秒*1000
4.2 使用glide方式会有延迟获取到的封面可能不准确
4.3 使用MediaMetadataRetriever方式会出现卡顿现象,由于是网络在线查询,所以网络不好时查询很慢,一般会用rxjava异步去查询,列表不建议用这个。
5.从上面5-1、5-2、5-3的截图可以看出封面是实时显示的,很符合需求视频暂停到那一秒就显示当前某一帧的封面,而且不会出现卡顿.
6.工具类源码如下:
videotimedemo: 视频播放时间 (gitee.com)
7.总结:以上就是今天的内容,使用三种方式实现获取视频的某一帧,最后选择的是第三种,大家可以根据需要自行选择,如果小伙伴们有更好的方法欢迎留言,后面有时间会整理出来一个列表播放暂停进入详情页再次返回的demo,谢谢大家!
更多推荐
已为社区贡献1条内容
所有评论(0)