FFmpegFrameGrabber读取的MP4帧如何转换为Google ML Kit的InputImage
解决方案
方案1:跳过BufferedImage,直接转换Frame为InputImage(实现简单)
Android平台确实不支持Java AWT的BufferedImage类,你可以直接通过JavaCV自带的AndroidFrameConverter把FFmpegFrameGrabber读取到的Frame直接转成Android原生Bitmap,再生成ML Kit要求的InputImage,步骤如下:
- 初始化帧抓取器时指定像素格式,降低转码开销
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(path); // 指定输出RGBA格式,方便后续转Bitmap frameGrabber.setPixelFormat(AV_PIX_FMT_RGBA); frameGrabber.start(); Frame frame; try { // 仅抓取图像帧,跳过音频帧提升效率 frame = frameGrabber.grabImage(); } catch (Exception e) { e.printStackTrace(); }
- 转换Frame为Bitmap
// 转换器全局复用即可,不要每次处理帧都创建,减少GC AndroidFrameConverter converter = new AndroidFrameConverter(); Bitmap bitmap = converter.convert(frame);
- 生成InputImage
// 第二个参数为视频帧的旋转角度,根据视频元数据的旋转信息填写,无旋转默认传0 InputImage inputImage = InputImage.fromBitmap(bitmap, 0);
注意:处理完成后及时调用
bitmap.recycle()回收内存,避免OOM。
方案2:更优实现(性能更高,适合高帧率/长视频处理)
ML Kit对YUV格式的处理效率远高于RGB格式,你可以直接输出NV21格式的帧数据,跳过Bitmap创建环节,整体处理速度可提升30%以上:
- 初始化帧抓取器时指定输出NV21格式
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(path); frameGrabber.setPixelFormat(AV_PIX_FMT_NV21); frameGrabber.start();
- 直接读取帧字节数组生成InputImage
Frame frame = frameGrabber.grabImage(); byte[] nv21Data = new byte[frame.image[0].limit()]; frame.image[0].get(nv21Data); InputImage inputImage = InputImage.fromByteArray( nv21Data, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), 0, // 旋转角度 InputImage.IMAGE_FORMAT_NV21 );
内容的提问来源于stack exchange,提问作者Arun
相关产品推荐
相关产品推荐

