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) + "毫秒");
    }
}

参考

相关推荐
CoderCodingNo5 分钟前
【GESP】C++五级真题(贪心和剪枝思想) luogu-B3930 [GESP202312 五级] 烹饪问题
开发语言·c++·剪枝
Coder_Boy_12 分钟前
SpringAI与LangChain4j的智能应用-(理论篇3)
java·人工智能·spring boot·langchain
kylezhao201922 分钟前
第1章:第一节 开发环境搭建(工控场景最优配置)
开发语言·c#
啃火龙果的兔子24 分钟前
JavaScript 中的 Symbol 特性详解
开发语言·javascript·ecmascript
Coder_Boy_33 分钟前
基于SpringAI的智能平台基座开发-(六)
java·数据库·人工智能·spring·langchain·langchain4j
热爱专研AI的学妹1 小时前
数眼搜索API与博查技术特性深度对比:实时性与数据完整性的核心差异
大数据·开发语言·数据库·人工智能·python
Mr_Chenph1 小时前
Miniconda3在Windows11上和本地Python共生
开发语言·python·miniconda3
阿狸远翔1 小时前
Protobuf 和 protoc-gen-go 详解
开发语言·后端·golang
永远前进不waiting1 小时前
C复习——1
c语言·开发语言
伯明翰java1 小时前
Java数据类型与变量
java·开发语言