android提供了获取视频帧的方法,比如获取第一帧作为视频缩略图,或者获取指定位置的帧快速浏览视频内容。
MediaMetadataRetriever类提供了获取视频各种信息的方法。
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(videoPath);
String rotationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
String width = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
String height = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
...
可获得视频宽高大小、持续时间、比特率等信息。
还可获取帧数据:
public static Bitmap getVideoFrame(String path, long time) {
long timeUs = time * 1000;
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(path);
return mmr.getFrameAtTime(timeUs, MediaMetadataRetriever.OPTION_CLOSEST);
}
获取指定时间附近的帧,返回Bitmap对象。
需要注意:
1.要先设置dataSource,再获取帧数据;
2.getFrameAtTime(long timeUs, int option)方法第一个参数的时间单位为微妙,这个地方很容易误传毫秒时间,导致一直获取第一帧。
getFrameAtTime()方法第二个参数设置帧的获取类型选项,可选择如下四种选项:
/**
* This option is used with {@link #getFrameAtTime(long, int)} to retrieve
* a sync (or key) frame associated with a data source that is located
* right before or at the given time.
*/
public static final int OPTION_PREVIOUS_SYNC = 0x00; //获取当前时间或之前的关键帧
/**
* This option is used with {@link #getFrameAtTime(long, int)} to retrieve
* a sync (or key) frame associated with a data source that is located
* right after or at the given time.
*/
public static final int OPTION_NEXT_SYNC = 0x01; //获取当前时间或之后的关键帧
/**
* This option is used with {@link #getFrameAtTime(long, int)} to retrieve
* a sync (or key) frame associated with a data source that is located
* closest to (in time) or at the given time.
*/
public static final int OPTION_CLOSEST_SYNC = 0x02; //获取当前时间最近的关键帧
/**
* This option is used with {@link #getFrameAtTime(long, int)} to retrieve
* a frame (not necessarily a key frame) associated with a data source that
* is located closest to or at the given time.
*/
public static final int OPTION_CLOSEST = 0x03; //获取当前时间最近的帧,不一定是关键帧
getFrameAtTime()方法获取的帧图片大小是和视频大小一样的,那么如果想获取不同宽高大小的图片怎么办呢?我们可以选择自己缩放图片。
其实,MediaMetadataRetriever类也提供了可以获取指定宽高大小的帧数据方法:
public Bitmap getScaledFrameAtTime(long timeUs, @Option int option, int dstWidth, int dstHeight) {
...
}
它可以指定要获取帧的宽高。
--------------------------------------------------------------------
上述方法返回的是Bitmap对象数据,怎么保存成一张图片呢?下面直接给出方法,不再赘述。
public static boolean saveBitmap(Bitmap bitmap, File file) {
if (bitmap == null)
return false;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
============================================
另外,要想获取视频帧图片,也可通过ffmpeg来获取,ffmpeg是一款强大的音视频处理工具。