Java处理视频文件,生成打标视频

java 复制代码
import org.apache.commons.lang3.StringUtils;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @author Mr.superbeyone
 * @project 
 * @className FfmpegUtil2
 * @description
 * @date 2023-10-20 15:15
 **/

public class FfmpegUtil2 {


    private static Logger logger = LoggerFactory.getLogger(FfmpegUtil2.class);


    /**
     * 生成标注后的视频文件
     *
     * @param srcVideoPath 源视频文件路径
     * @param frameRate    跳帧请求RPC的步数
     * @param extName      生成的文件扩展名 如: mp4  flv
     * @return 标注后的视频文件路径
     */
    public static String generateTagVideo(String srcVideoPath, int frameRate, String extName) {
        return generateTagVideo(srcVideoPath, null, frameRate, extName);
    }

    public static String generateTagVideo(String srcVideoPath, String targetVideoPath, int frameRate, String extName) {
        long start = System.currentTimeMillis();
        //视频文件路径
        File srcVideoFile = new File(srcVideoPath);
        if (!srcVideoFile.exists() || !srcVideoFile.isFile()) {
            logger.info("generateTagVideo srcVideoPath is not video file {}", srcVideoPath);
            return "";
        }
        if (StringUtils.isBlank(targetVideoPath)) {
            targetVideoPath = srcVideoFile.getParentFile() + File.separator + StringUtils.substringBeforeLast(srcVideoFile.getName(), ".") + "_tag." + extName;
        }
        String targetVideo = doGenerateTagVideo(srcVideoPath, targetVideoPath, frameRate, extName);
        logger.info("generateTagVideo 耗时 {}", (System.currentTimeMillis() - start));
        logger.info("generateTagVideo srcVideo {} targetVideo {}", srcVideoPath, targetVideo);
        return targetVideo;
    }

    public static String doGenerateTagVideo(String srcVideoPath, String targetVideoPath, int frameRate, String extName) {
        FFmpegFrameGrabber grabber = null;
        FFmpegFrameRecorder recorder = null;
        try {
            grabber = FFmpegFrameGrabber.createDefault(new File(srcVideoPath));
            grabber.setFormat(StringUtils.substringAfterLast(srcVideoPath, ".").toLowerCase());
            grabber.start();

            int imageHeight = grabber.getImageHeight();
            int imageWidth = grabber.getImageWidth();
            recorder = FFmpegFrameRecorder.createDefault(new File(targetVideoPath), imageWidth, imageHeight);

            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
            recorder.setFormat(extName);

            recorder.setVideoBitrate(10000);//数值越大,存储空间越大
            recorder.setVideoOption("preset", "ultrafast");//究极快
            recorder.start();

            Java2DFrameConverter converter = new Java2DFrameConverter();

            int index = 0, x = 0, y = 0, width = 0, height = 0;
            Frame frame;
            while ((frame = grabber.grabImage()) != null) {
                if (null == frame.image) {
                    continue;
                }
                index++;
                
                BufferedImage image = converter.getBufferedImage(frame);
                if (frameRate > 0 && index % frameRate == 0) {
                    Map<String, Integer> location = rpcFindLocation(image);
                    x = location.get("x");
                    y = location.get("y");
                    width = location.get("w");
                    height = location.get("h");
                }
                
                Graphics graphics = image.getGraphics();
                graphics.setColor(Color.RED);
                graphics.drawRect(x, y, width, height);
                Frame drawFrame = converter.convert(image);
                recorder.record(drawFrame);
            }
            recorder.close();
            grabber.close();
        } catch (Exception e) {
            logger.error("doGenerateTagVideo exception ", e);
        } finally {
            if (grabber != null) {
                try {
                    grabber.close();
                } catch (Exception ex) {
                    logger.error("close grabber error", ex);
                }
            }
            if (recorder != null) {
                try {
                    recorder.close();
                } catch (Exception ex) {
                    logger.error("close recorder error", ex);
                }
            }
        }

        return targetVideoPath;
    }

    /**
     * 对图片文件RPC调用
     *
     * @param image 图片文件
     * @return x, y, w, h
     */
    private static Map<String, Integer> rpcFindLocation(BufferedImage image) {
        Map<String, Integer> location = new HashMap<>(8);
        Random random = new Random();
        location.put("x", 800 + random.nextInt(100));
        location.put("y", 750 + random.nextInt(50));
        location.put("w", 50 + random.nextInt(10));
        location.put("h", 50 + random.nextInt(10));
        return location;
    }


    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        String srcPath = "D:\\WorkSpace\\video\\src\\b.mp4";
        String destPath = "D:\\WorkSpace\\video\\src\\test\\" + System.currentTimeMillis() + ".flv";
        generateTagVideo(srcPath, destPath, 10, "flv");
        System.out.println(destPath + "耗时\t" + (System.currentTimeMillis() - start) + "毫秒");
    }
}

参考

相关推荐
躺平大鹅2 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者3 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺3 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart4 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP5 小时前
MyBatis-mybatis入门与增删改查
java
孟陬8 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
想用offer打牌8 小时前
一站式了解四种限流算法
java·后端·go
华仔啊9 小时前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java
也些宝10 小时前
Java单例模式:饿汉、懒汉、DCL三种实现及最佳实践
java