视频抽帧实现

时间:2025-02-16 09:23:16
/** * 抽帧 * @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(); }