Java实现批量视频抽帧2.0

继上个版本 对其进行略微升级 🤓

上个版本仅对一个视频进行抽帧处理

此版本可对一个文件夹内的全部视频进行抽帧并对应的文件夹进行帧图片的保存

1️⃣配置pom.xml (保持上次不变)

复制代码
    <dependencies>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.7</version>
        </dependency>

    </dependencies>

2️⃣创建Util工具类 (本次所有方法都在次类中)

复制代码
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class Util {
    //读取文件夹的内容并执行1️⃣创建文件夹2️⃣抽帧
    public static String ReadFolderFiles(String address) {
        //存放读取到的路径
        ArrayList<String> strings = new ArrayList<>();
        // 文件夹路径
        String folderPath = address;
        // 创建File对象
        File folder = new File(folderPath);
        // 检查文件夹是否存在
        if (folder.exists() && folder.isDirectory()) {
            int num;
            String strCreate = "";
            String strFrame = "";
            // 获取文件夹中的所有文件名
            File[] files = folder.listFiles();
            // 将子文件夹的名称添加到ArrayList中并过滤掉当前文件夹名
            for (File file : files) {
                if (!file.getName().equals(".DS_Store")) {
                    strings.add(file.getName());
                }
            }
            num = strings.size();
            // 输出文件名数组
            for (String fileName : strings) {
                String oldfileName = address+"/"+fileName;
                String str = fileName.substring(0,fileName.indexOf('.'));
                String newFileName = address+"/"+str;
                strCreate = CreateFolder(newFileName);
                strFrame = FrameExtractor(oldfileName);
            }
            return String.format(strCreate+"\n已对%d个视频进行抽帧\n"+strFrame+"至对应文件夹",num);
        } else {
            return "指定的文件夹不存在或不是一个文件夹";
        }
    }
    //1️⃣根据视频名称创建对应文件夹
    private static String CreateFolder(String fileName){
        String str;
        // 文件夹名
        String folderName = fileName;
        // 创建一个File对象,表示文件夹路径
        File folder = new File(folderName);
        // 使用mkdir()方法创建文件夹
        if (!folder.exists()) {
            if (folder.mkdir()) {
                str = "文件夹创建成功!";
            } else {
                str = "文件夹创建失败!";
            }
        } else {
            str = "文件夹已存在!";
        }
        return str;
    }
    //2️⃣将视频转为帧图片
    public static String FrameExtractor(String address){
        String str;
        // 视频文件路径
        String videoFilePath = address;
        // 创建FFmpegFrameGrabber对象
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoFilePath);
        try {
            // 打开视频文件
            grabber.start();
            // 逐帧抓取视频
            Frame frame;
            int frameNumber = 1;
            //保存路径
            String createaddress = address.substring(0,address.indexOf("."));
            while ((frame = grabber.grabImage()) != null) {
                BufferedImage bufferedImage = frameToBufferedImage(frame);
                // 生成保存帧图像的文件路径
                String outputFilePath = String.format("%s/frame_%05d.jpg", createaddress, frameNumber);
                // 保存帧图像到文件
                try {
                    ImageIO.write(bufferedImage, "jpg", new File(outputFilePath));
                } catch (IOException e) {
                    e.printStackTrace();
                    str = "保存失败";
                }
                frameNumber++;
            }
            // 关闭视频文件
            grabber.stop();
            str = "保存成功";
        } catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
            e.printStackTrace();
            str = "保存失败";
        }
        return str;
    }
    //将Frame转换为BufferedImage
    private static BufferedImage frameToBufferedImage(Frame frame) {
        Java2DFrameConverter converter = new Java2DFrameConverter();
        return converter.getBufferedImage(frame);
    }
}

3️⃣运行结果

相关推荐
学长毕业设计2 小时前
基于SpringBoot的公益基金管理系统(源码+文档+讲解视频)
java·spring boot·后端
东小西2 小时前
【SAA实战】第 3 篇 · 工具调用全攻略:把业务能力交给 Agent 自己调度
java·后端·spring
东小西2 小时前
【SAA实战】第 4 篇 · Agent 短期记忆:saver 让 Agent 跨轮记得住(threadId 隔离)
java·后端·spring
许彰午2 小时前
22-DataCenter报文序列化
java·低代码·架构·状态模式
2601_962065253 小时前
[MySQL] SQL优化之性能分析
java·sql·mysql
小范同学_3 小时前
JDK1.7 与 JDK1.8 HashMap 底层原理对比 + 数组并发扩容死循环详解
java·开发语言
予昊4 小时前
从零实现“在线五子棋对战“:WebSocket 实时通信 + 段位匹配
java·开发语言·网络·websocket
2601_962203514 小时前
【SpringAI入门】初识SpringAI
java
weixin_461408584 小时前
Mybatis-flex小记
java·开发语言·mybatis
2601_962177135 小时前
【MySQL篇】聚合查询,联合查询
android·java·mysql