赞
踩
具体实现步骤:
准备工作:
OpenCVFrameConverter.ToIplImage
对象 converter
,它用于将 JavaCV 帧转换为 OpenCV 的 IplImage
对象。设置视频抓取器:
FFmpegFrameGrabber
对象,分别用于原始视频文件和待合并的视频文件。设置视频参数:
设置临时文件和输出文件:
设置录制器参数:
FFmpegFrameRecorder
对象,用于录制合并后的视频。抓取和处理视频帧:
释放资源:
- 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 < 500) {
-
- // 抓取当前视频的一帧
- frame = frameGrabber1.grabFrame();
- if (frame == null) {
- break;
- }
-
-
- // 如果当前帧是图像,则进行叠加
- if (frame.image != null) {
- // 将JavaCV帧转换为OpenCV的Mat对象,方便后续处理颜色通道
- Mat mat = converter.convertToMat(frame);
- // 进行图像边界处理,例如裁剪掉边界黑线条
- // 将JavaCV帧转换为BufferedImage,并创建Graphics2D对象
- BufferedImage buffImg = Java2DFrameUtils.toBufferedImage(frame);
- Graphics2D graphics = buffImg.createGraphics();
- // 抓取另一个视频的一帧
- mergeFrame1 = frameGrabber2.grabFrame();
- if(mergeFrame1!=null){
- Mat mat1 = converter.convertToMat(mergeFrame1);
- int borderSize = 1;
- mat1 = mat1.apply(new Rect(borderSize, borderSize, mat1.cols() - 2 * borderSize, mat1.rows() - 2 * borderSize));
- // 将处理后的 Mat 对象转换回帧对象
- mergeFrame = converter.convert(mat1);
- }
- frameGrabber2.setImageMode(FrameGrabber.ImageMode.COLOR);
-
- if (mergeFrame != null) {
- // 如果当前帧是空帧,则一直循环直到抓取到带图像的帧
- while (mergeFrame.image == null) {
- mergeFrame = frameGrabber2.grabFrame();
- frameGrabber2.setImageMode(FrameGrabber.ImageMode.COLOR);
- }
-
- // 进行颜色空间转换(例如,将图像从BGR转换为RGB)
- // cvtColor(mat, mat, COLOR_BGR2RGB);
- // 判断颜色空间是否需要转换
- // if (mat.channels() > 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();
- }
-
- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>javacv</artifactId>
- <version>1.5.2</version>
- </dependency>
- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>javacpp</artifactId>
- <version>1.5.2</version>
- </dependency>
-
- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>opencv</artifactId>
- <version>4.1.2-1.5.2</version>
- <classifier>windows-x86_64</classifier>
- </dependency>
- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>openblas</artifactId>
- <version>0.3.7-1.5.2</version>
- <classifier>windows-x86_64</classifier>
- </dependency>
- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>ffmpeg</artifactId>
- <version>4.2.1-1.5.2</version>
- <classifier>windows-x86_64</classifier>
- </dependency>
-
- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>opencv</artifactId>
- <version>4.1.2-1.5.2</version>
- <classifier>linux-x86_64</classifier>
- </dependency>
- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>openblas</artifactId>
- <version>0.3.7-1.5.2</version>
- <classifier>linux-x86_64</classifier>
- </dependency>
- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>ffmpeg</artifactId>
- <version>4.2.1-1.5.2</version>
- <classifier>linux-x86_64</classifier>
- </dependency>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。