使用 FFmpegMediaMetadataRetriever 以及 MediaMetadataRetriever 获取关键帧失败(返回null)问题

       大家知道 一个较长的视频中可能存在多个关键帧,而往往第一帧是黑色的,因此我们会采用1/4时间点处的关键帧用于生成视频的缩略图。

       但是后来发现某些视频采用 MediaMetadataRetriever 会出现

MediaMetadataRetrieverJNI: getFrameAtTime: videoFrame is a NULL pointer 

     同时使用 FFmpegMediaMetadataRetriever获取1/4处关键帧始终返回 null

   

     后来尝试通过linux中的工具 ffmpeg 来生产 缩略图。终于找到了重要线索,开心~~

     当使用以下命令仍然不能生成缩略图:

ffmpeg -i video.mp4 -y -f image2 -ss 8 -t 0.001 -s 350x240 thumbnail.jpg

 但将命令修改为下面的状态竟然能生成缩略图:

ffmpeg -i video.mp4 -y -f image2  -t 0.001 -s 350x240 thumbnail.jpg

其实这两段命令唯一的差别是 “-ss 8” ,这个属性的意思是生产缩略图的时间点。(其他关于ffmpeg的使用可以参考ffmpeg 常用命令汇总

于是我将之前android 代码中FFmpegMediaMetadataRetriever获取缩略图的结果由

retriever.getScaledFrameAtTime(80, (int) destWidth, destHeight);

改为 

retriever.getScaledFrameAtTime(-1, (int) destWidth, destHeight);

果然能够生产缩略图啦啦,哈哈。

至于MediaMetadataRetriever 的问题仍然存在,这应该确实设个bug。

********************************************************************************************************

但为啥那个视频设置时间点就会失败呢???

后来通过以下命令可以获取视频中所有的缩略图发现:

ffmpeg -i video.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -s 1920*1080 -f image2 core-%02d.jpeg

那个视频竟然只有一帧关键帧!!!所以如果设置时间点不正确的话,是只能返回null,满脸黑线……

********************************************************************************************************

因此建议在生成缩略图时,如果设置了时间点,返回null;那么再重新创建一个 FFmpegMediaMetadataRetriever ,不设置时间点去获取。

注意:一定要重新去创建一个 FFmpegMediaMetadataRetriever 而不是 在 上一个FFmpegMediaMetadataRetriever 中直接获取,否则仍然获取不到!

一点经验,希望能帮到大家~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果使用`MediaMetadataRetriever`获取视频帧画面被放大,可能是因为视频的分辨率与显示的视图大小不匹配导致的。你可以尝试对获取到的视频帧进行缩放以适应目标视图。 下面是一个示例代码,展示了如何使用`MediaMetadataRetriever`获取视频帧并进行缩放: ```java import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.MediaMetadataRetriever; import android.os.Bundle; import android.widget.ImageView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.imageView); String videoPath = "your_video_path"; // 替换成你的视频文件路径 Bitmap videoFrame = extractVideoFrame(videoPath); if (videoFrame != null) { Bitmap scaledFrame = scaleBitmap(videoFrame, imageView.getWidth(), imageView.getHeight()); imageView.setImageBitmap(scaledFrame); } } private Bitmap extractVideoFrame(String videoPath) { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(videoPath); return retriever.getFrameAtTime(); } catch (Exception e) { e.printStackTrace(); } finally { retriever.release(); } return null; } private Bitmap scaleBitmap(Bitmap bitmap, int targetWidth, int targetHeight) { return Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, false); } } ``` 在上述代码中,`extractVideoFrame()`方法使用`MediaMetadataRetriever`获取视频的帧画面。然后,使用`scaleBitmap()`方法将视频帧画面缩放为目标视图的大小。最后,将缩放后的位图设置给`ImageView`来显示。 请注意,这段代码假设目标视图的大小已经确定。如果目标视图的大小在运行时才能确定,你可以在适当的时机调用`scaleBitmap()`方法来进行缩放。另外,如果视频的分辨率与目标视图的宽高比不匹配,可能会导致画面被拉伸或裁剪。你可以根据需求调整缩放逻辑,以保持画面的正确比例。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值