一、准备工作
下载图集放到文件夹中,图集宽高改成一致的比例,然后编号;
二、原理
FFmpegFrameRecorder
是 OpenCV 库中的一个类,它是用于将视频帧序列编码为视频文件的工具。这个类是 OpenCV 与 FFmpeg 库结合使用的一部分,允许开发者在 Java 应用程序中进行视频编码。FFmpeg 是一个非常流行的开源多媒体框架,它支持多种音视频编解码器。
以下是 FFmpegFrameRecorder
的一些关键特性和用法:
关键特性:
- 多种格式支持:支持多种视频格式,如 MP4、AVI、MOV 等。
- 多种编码器支持:支持多种视频编码器,例如 H.264、MPEG-4、VP8 等。
- 帧率控制:可以设置视频的帧率。
- 比特率控制:可以设置视频的比特率,影响视频质量和文件大小。
- 音频支持:可以同时录制视频和音频。
- 像素格式:支持不同的像素格式,如 YUV420P 等。
基本用法:
- 初始化:创建
FFmpegFrameRecorder
对象,并指定输出文件路径和视频参数(宽度、高度)。 - 设置参数:设置视频编码器、帧率、比特率、像素格式等。
- 开始录制:调用
start()
方法开始录制。 - 录制帧:通过
record()
方法传递帧到编码器。 - 结束录制:调用
stop()
或release()
方法结束录制并释放资源。
示例代码:
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class VideoRecorderExample {
public static void main(String[] args) throws IOException {
String outputFile = "output.mp4";
int width = 640;
int height = 480;
double fps = 30.0;
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, width, height);
recorder.setFrameRate(fps);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 使用 H.264 编码器
recorder.setFormat("mp4"); // 设置视频格式
recorder.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage image = ImageIO.read(new File("path_to_image.jpg"));
for (int i = 0; i < 100; i++) { // 录制 100 帧
recorder.record(converter.getFrame(image));
}
recorder.stop();
}
}
三、实现方法
我们主要使用了OpenCV的FFmpegFrameRecorder ,这个是
-
异常处理:添加适当的异常处理逻辑,以便在发生错误时能够优雅地处理。
-
资源管理:使用
try-with-resources
语句确保FFmpegFrameRecorder
和ImageIO
正确关闭,避免资源泄漏。
package com.bitar.javavideo.test;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Test01 {
private static final String OUTPUT_DIR = "D:\\desktop\\test\\test01\\";
private static final String OUTPUT_FILE = OUTPUT_DIR + "01-result.mp4";
private static final int IMG_WIDTH = 512;
private static final int IMG_HEIGHT = 512;
private static final int FRAME_RATE = 25;
private static final int MOTION_FACTOR = 1;
private static final String IMAGE_FORMAT = "png";
public static void main(String[] args) {
try (FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(OUTPUT_FILE, IMG_WIDTH, IMG_HEIGHT)) {
recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4);
recorder.setFrameRate(FRAME_RATE);
recorder.setVideoBitrate(calculateVideoBitrate());
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.setFormat("mp4");
recorder.setAudioChannels(2);
recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
recorder.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
for (int i = 1; i <= 3; i++) {
recordImages(recorder, converter, i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static int calculateVideoBitrate() {
return (int) (IMG_WIDTH * IMG_HEIGHT * FRAME_RATE * MOTION_FACTOR * 0.07);
}
private static void recordImages(FFmpegFrameRecorder recorder, Java2DFrameConverter converter, int imageNumber) throws IOException {
String imagePath = OUTPUT_DIR + "512x512-" + imageNumber + "." + IMAGE_FORMAT;
BufferedImage image = ImageIO.read(new File(imagePath));
for (int i = 0; i < FRAME_RATE; i++) {
recorder.record(converter.getFrame(image));
}
}
}