视频抽帧实现
/**
* 抽帧
* @param frameRate 帧率
* @param storePath 截图图片要存放的路径
* @param filePath 要截图的视频存放路径
*/
public static List<String> grabFrameByFilePath(double frameRate, String storePath, String filePath) throws Exception {
File folder = new File(storePath);
boolean success = true;
if (!folder.exists() && !folder.isDirectory()) {
success = folder.mkdirs();
}
if (!success){
throw new FileNotFoundException("文件夹创建异常");
}
List<String> sourceFiles = new ArrayList<>();
FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(filePath);
fFmpegFrameGrabber.start();
grabFrames(fFmpegFrameGrabber,frameRate,storePath,sourceFiles);
fFmpegFrameGrabber.close();
return sourceFiles;
}
private static void grabFrames(FFmpegFrameGrabber fFmpegFrameGrabber, double frameRate, String storePath, List<String> sourceFiles) throws Exception {
double videoRate = fFmpegFrameGrabber.getFrameRate();
if (frameRate >= videoRate){
//每一帧都获取
doGrabPerFrame(fFmpegFrameGrabber,storePath,sourceFiles);
}else if (frameRate >= ApolloConfig.VIDEO_RATE){
//逐帧遍历,只获取需要的
doGrabFramesByTraverseFrames(fFmpegFrameGrabber,frameRate,storePath,sourceFiles,videoRate);
}else {
//稍后会说明
doGrabFramesBySetTimestamp(fFmpegFrameGrabber,frameRate,storePath,sourceFiles,videoRate);
}
}
/**
* 产生的所有文件都暂时以本地存储为主
* fFmpegFrameGrabber ffmpeg抽帧工具
* videoRate 视频帧率
* storePath 为统一放置抽帧图片使用
* sourceFiles 抽帧之后图片存放本地位置
*
*/
void doGrabFramesByTraverseFrames(FFmpegFrameGrabber fFmpegFrameGrabber, double frameRate, String storePath, List<String> sourceFiles, double videoRate) throws FFmpegFrameGrabber.Exception {
Java2DFrameConverter converter = new Java2DFrameConverter();
int lengthInVideoFrames = fFmpegFrameGrabber.getLengthInFrames();
int frameGapCount = (int) Math.ceil(lengthInVideoFrames * frameRate / videoRate);
int frameGap = lengthInVideoFrames / frameGapCount;
Frame f;
String path;
boolean flag;
for (int i = 1; i <= frameGapCount; i++){
flag = false;
// 每frameGap取1帧
for (int j = 1; j <= frameGap; j++) {
f = fFmpegFrameGrabber.grabImage();
path = String.format("%s/%s", storePath, i + ".jpg");
doExecuteFrame(f,path,converter);
if (PicDetectionUtil.checkPicAvailableBySourcePath(path) && !flag){//图片检测,看你实际使用,并不必须
sourceFiles.add(path);
flag = true;
}
}
}
//考虑总帧数不能整除情况
if (lengthInVideoFrames > frameGap * frameGapCount){
int diff = lengthInVideoFrames - frameGap * frameGapCount;
while (diff > 0){
f = fFmpegFrameGrabber.grabImage();
path = String.format("%s/%s", storePath, frameGapCount + 1 + ".jpg");
doExecuteFrame(f,path,converter);
if (PicDetectionUtil.checkPicAvailableBySourcePath(path)){
sourceFiles.add(path);
break;
}
diff--;
}
}
converter.close();
}