小工具知识网

当前位置: 首页 > 行业知识 > JAVACV+ffmpeg+OpenCV实现视频叠加合成(AR效果视频生成)

行业知识

JAVACV+ffmpeg+OpenCV实现视频叠加合成(AR效果视频生成)

2026-10-25 19:34:43 来源:互联网转载

同时抓取两个视频的帧,在叠加合并时进行一些图像处理,并将合并后的帧写入输出文件,最后释放资源。

具体实现步骤:

  1. 准备工作:

    • 导入所需的库,这里主要是 OpenCV 和 JavaCV 相关的库。
    • 创建一个 OpenCVFrameConverter.ToIplImage 对象 converter,它用于将 JavaCV 帧转换为 OpenCV 的 IplImage 对象。
  2. 设置视频抓取器:

    • 创建两个 FFmpegFrameGrabber 对象,分别用于原始视频文件和待合并的视频文件。
    • 设置连接超时时间和读取数据超时时间。
    • 启动两个抓取器并获取视频的长度(单位:微秒),用于后续的处理。
  3. 设置视频参数:

    • 检查并调整两个视频的帧率,确保它们相同。
    • 设置输出视频的宽度和高度。
    • 计算视频的宽高比例,并计算目标高度。
  4. 设置临时文件和输出文件:

    • 获取系统临时文件目录,创建临时文件对象。
    • 设置输出文件路径,并准备好文件名。
  5. 设置录制器参数:

    • 创建一个 FFmpegFrameRecorder 对象,用于录制合并后的视频。
    • 设置输出编码器、音频采样率、帧率、视频比特率、视频编码器等参数。
  6. 抓取和处理视频帧:

    • 循环抓取原始视频的帧,同时抓取待合并视频的帧。
    • 如果当前帧是图像帧,则进行叠加处理:
      • 将 JavaCV 帧转换为 OpenCV 的 Mat 对象,进行图像边界处理。
      • 将 JavaCV 帧转换为 BufferedImage,并创建 Graphics2D 对象。
      • 抓取待合并视频的帧,进行相应处理。
      • 将待合并视频的帧叠加到当前帧上,并写入输出文件。
    • 如果当前帧包含音频,则也将音频写入输出文件。
  7. 释放资源:

    • 停止并释放所有的抓取器和录制器。
    • 关闭颜色转换过滤器。
                 OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();            System.out.println(mergeFilePath);            FFmpegFrameGrabber frameGrabber1 = new FFmpegFrameGrabber(file);            FFmpegFrameGrabber frameGrabber2 = new FFmpegFrameGrabber(mergeFilePath);            frameGrabber2.setOption("timeout", "5000000"); // 设置连接超时时间            frameGrabber2.setOption("stimeout", "20000000"); // 设置读取数据超时时间            Frame frame = null;            Frame  mergeFrame1= null;            Frame mergeFrame = null;            FFmpegFrameRecorder recorder = null;            String fileName = null;            try {                frameGrabber1.start();                frameGrabber2.start();                int videoLengthInSeconds = (int) (frameGrabber1.getLengthInTime() / 1000000);                int videoLengthInSeconds2 = (int) (frameGrabber2.getLengthInTime() / 1000000);                System.out.println("秒数"+videoLengthInSeconds+"-----------"+videoLengthInSeconds2);                System.out.println(frameGrabber1.getImageWidth()+"11111111111111"+frameGrabber1.getImageHeight());                double frameRate = frameGrabber2.getFrameRate();                if (frameRate != frameGrabber1.getFrameRate()) {                    frameGrabber1.setFrameRate(frameRate);                }                frameGrabber2.setFrameRate(24);                frameGrabber1.setFrameRate(24);// 计算两个视频的长度(单位:秒)                // 设置帧率                frameGrabber1.setImageWidth(1080);                frameGrabber1.setImageHeight(1920);                int outputWidth = 1080; // 合成后视频的宽度                int outputHeight = 1920;                // 根据视频的宽高比例计算目标高度                double videoRatio1 = (double) frameGrabber1.getImageWidth() / frameGrabber1.getImageHeight();                double videoRatio2 = (double) frameGrabber2.getImageWidth() / frameGrabber2.getImageHeight();                // 获取图像宽和高                int imageWidth = outputWidth;                int imageHeight = outputHeight;                int imageWidth1 = frameGrabber2.getImageWidth();;                int imageHeight1 = frameGrabber2.getImageHeight();                long sourceVideoDuration = frameGrabber1.getLengthInTime();                long mergeVideoDuration = frameGrabber2.getLengthInTime();                FFmpegFrameFilter colorConvertFilter = new FFmpegFrameFilter("format=rgb24", imageWidth, imageHeight);                colorConvertFilter.setPixelFormat(avutil.AV_PIX_FMT_RGB24);                colorConvertFilter.start();                FFmpegFrameFilter filter = new FFmpegFrameFilter("colorkey=black", imageWidth1, imageHeight1);                filter.setPixelFormat(avutil.AV_PIX_FMT_RGB24);                filter.start();                // 设置时间戳,确保两个视频的起始点一致                // 随机生成一个新的文件名                Random random = new Random();                long name1 = System.currentTimeMillis() + RandomUtils.nextInt(100, 9999);                // 获取系统默认的临时文件目录                String tempDir = System.getProperty("java.io.tmpdir");                // 创建临时文件对象8                File tempFile = new File(tempDir);                String path =  tempFile.getAbsolutePath();                fileName = path +File.separator+ String.valueOf(name1) + ".mp4";                ajaxResult.put("fileUrl", domainName + String.valueOf(name1) + ".mp4");                ajaxResult.put("filePath",fileName);                System.out.println("--文件名-->>" + fileName);                // 设置输出编码器、音频采样率、帧率、时间戳、视频比特率、视频编码器// 创建临时文件流记录器,将输出流作为参数传入                recorder = new FFmpegFrameRecorder(fileName, imageWidth, imageHeight, frameGrabber1.getAudioChannels());                recorder.setFormat("mp4");                recorder.setSampleRate(frameGrabber1.getSampleRate());                recorder.setVideoBitrate(frameGrabber1.getVideoBitrate());                recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);                recorder.setFrameRate(24);                recorder.setTimestamp(frameGrabber2.getTimestamp());                // 启动录制器和另一个视频的抓取器                frameGrabber2.setVideoCodec(avcodec.AV_CODEC_ID_H264);                frameGrabber2.setPixelFormat(avutil.AV_PIX_FMT_RGB24);                frameGrabber2.setVideoBitrate(frameGrabber1.getVideoCodec());                frameGrabber2.setFrameRate(frameGrabber1.getVideoCodec());                recorder.start();                int index = 0;                // 获取视频的总帧数                int totalFrameCount = frameGrabber2.getLengthInFrames();                System.out.println("视频总帧数:" + totalFrameCount);                int totalFrameCount1 = frameGrabber1.getLengthInFrames();                System.out.println("视频总帧数:" + totalFrameCount1);                int xum =700;                while (index  1) {//                            cvtColor(mat, mat, COLOR_BGR2RGB);//                        }                            // 将另一个视频的帧应用颜色过滤器,并将结果转换为BufferedImage                            filter.push(mergeFrame);                            Frame filteredFrame = filter.pullImage();                            BufferedImage mergeBuffer = Java2DFrameUtils.toBufferedImage(filteredFrame);                            // 进行颜色空间转换(例如,将图像从BGR转换为RGB                            //                       cvtColor(converter.convertToMat(filteredFrame), converter.convertToMat(filteredFrame), COLOR_BGR2RGB);                            // 进行直方图均衡化或颜色映射等处理(根据具体需求进行选择和调整)                            // 将另一个视频的帧叠加到当前帧上                            graphics.drawImage(mergeBuffer, 0, 0, outputWidth, outputHeight, null);//                        graphics.drawImage(mergeBuffer, 0, 0, frameGrabber1.getImageWidth(), frameGrabber1.getImageHeight(), null);                        }else {                            break;                        }                        // 将叠加后的JavaCV帧写入输出文件                        Frame newFrame = Java2DFrameUtils.toFrame(buffImg);                        recorder.record(newFrame);                    }                    // 如果当前帧包含音频,则将其写入输出文件                    if (frame.samples != null) {                        recorder.recordSamples(frame.sampleRate, frame.audioChannels, frame.samples);                    }                    if(mergeFrame1 != null){                        if (mergeFrame1.samples != null) {                            recorder.recordSamples(mergeFrame1.sampleRate, mergeFrame1.audioChannels, mergeFrame1.samples);                        }                    }                    System.out.println("帧值=" + index);                    index++;                }                // 停止并释放资源                recorder.stop();                recorder.release();                filter.stop();                colorConvertFilter.stop();                frameGrabber2.stop();                frameGrabber1.stop();//在业务侧写代码时记得处理掉这个临时文件//            if (file!=null){//                file.deleteOnExit();//            }            } catch (Exception e) {                e.printStackTrace();            }
                          org.bytedeco            javacv            1.5.2                            org.bytedeco            javacpp            1.5.2                            org.bytedeco            opencv            4.1.2-1.5.2            windows-x86_64                            org.bytedeco            openblas            0.3.7-1.5.2            windows-x86_64                            org.bytedeco            ffmpeg            4.2.1-1.5.2            windows-x86_64                                    org.bytedeco                    opencv                    4.1.2-1.5.2                    linux-x86_64                                                    org.bytedeco                    openblas                    0.3.7-1.5.2                    linux-x86_64                                                    org.bytedeco                    ffmpeg                    4.2.1-1.5.2                    linux-x86_64                

上一篇:饥荒怎么打服务器mod?

下一篇:Win10升级新体验,一键操作,轻松升级!