Android使用Exoplayer捕获指定位置视频帧,解决仅捕获首帧问题
ExoPlayer 捕获指定时间帧异常修复方案
问题根因
- 单位不匹配:ExoPlayer
getCurrentPosition()返回的是毫秒时间戳,但MediaMetadataRetriever.getFrameAtTime()要求传入的参数是微秒时间戳,两者相差1000倍,你传入的数值远小于实际对应时间的微秒值,会被定位到视频0时刻附近,所以返回第一帧。 - 默认取帧规则限制:
getFrameAtTime()不传第二个参数时默认用OPTION_PREVIOUS_SYNC规则,只会提取目标时间之前最近的关键帧,如果目标时间点前的第一个关键帧是视频开头的I帧,也会返回第一帧。
修复后代码
MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(yourPath); // 把ExoPlayer返回的毫秒时间戳转成微秒 long targetTimeUs = simpleExoPlayer.getCurrentPosition() * 1000; // 指定取帧规则为取最接近目标时间的帧,支持非关键帧,精度更高 Bitmap bitmap = retriever.getFrameAtTime(targetTimeUs, MediaMetadataRetriever.OPTION_CLOSEST); // 此处处理获取到的bitmap } catch (Exception e) { // 处理异常:比如路径无效、视频格式不支持等场景 } finally { // 用完必须释放资源,避免内存泄漏 retriever.release(); }
可选取帧规则说明
MediaMetadataRetriever.OPTION_PREVIOUS_SYNC:默认值,仅取目标时间之前最近的关键帧,速度最快但精度最低MediaMetadataRetriever.OPTION_NEXT_SYNC:仅取目标时间之后最近的关键帧,速度较快MediaMetadataRetriever.OPTION_CLOSEST:取和目标时间最接近的帧,允许取非关键帧,精度最高但处理速度稍慢
注意事项
- 如果操作的是网络视频流,
MediaMetadataRetriever支持度有限,建议先缓存到本地再执行抓帧操作 - 确保App已经获取到对应视频文件的读取权限,否则会触发操作异常
- 仅支持未加密的普通视频格式,DRM加密视频无法通过该方法获取帧
内容的提问来源于stack exchange,提问作者ahmadu suleiman
相关产品推荐
相关产品推荐

