pom.xml
<properties>
<java.version>8</java.version>
<javacv.version>1.5.8</javacv.version>
</properties>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profile.active>dev</profile.active>
<dev.environment>dev</dev.environment>
</properties>
<dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.21-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>5.1.2-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.6.0-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture</artifactId>
<version>2.13.3.31-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
</dependencies>
</profile>
<profile>
<id>pro</id>
<properties>
<profile.active>pro</profile.active>
<dev.environment>pro</dev.environment>
</properties>
<dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.21-1.5.8</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>5.1.2-1.5.8</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.6.0-1.5.8</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture</artifactId>
<version>2.13.3.31-1.5.8</version>
<classifier>linux-x86_64</classifier>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencies>
<!-- javacv:封装对opencv、ffmpeg的api -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>${javacv.version}</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
<version>${javacv.version}</version>
</dependency>
</dependencies>
OpencvUtil
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.Collection;
/**
* @author 954L
* @create 2023/5/5 22:57
*/
@Slf4j
public class OpencvUtil {
/** 图片转视频 */
@SneakyThrows
public static boolean img2Video(Collection<InputStream> imageInputStreams,
String outFilePath, int videoWidth, int videoHeight) {
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outFilePath, videoWidth, videoHeight);
try {
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.setFormat("mp4"); recorder.setFrameRate(25); recorder.start();
// 加入图片
Java2DFrameConverter converter = new Java2DFrameConverter();
for (InputStream imageInputStream: imageInputStreams) {
BufferedImage read = ImageIO.read(imageInputStream);
for (int i = 0; i < 25; i++)
recorder.record(converter.getFrame(read));
}
return true;
} catch (Exception e) {
log.error("javacv:img2Video error", e); return false;
} finally {
recorder.stop(); recorder.release(); recorder.close();
}
}
/** 视频添加音频 */
@SneakyThrows
public static boolean videoAddAudio(InputStream videoInputStream, InputStream audioInputStream,
String outFilePath) {
FrameGrabber videoGrabber = new FFmpegFrameGrabber(videoInputStream);
FrameGrabber audioGrabber = new FFmpegFrameGrabber(audioInputStream);
try {
videoGrabber.start(); audioGrabber.start();
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outFilePath,
videoGrabber.getImageWidth(), videoGrabber.getImageHeight(),
audioGrabber.getAudioChannels());
try {
recorder.setFormat("mp4"); recorder.setFrameRate(videoGrabber.getFrameRate());
recorder.setSampleRate(audioGrabber.getSampleRate()); recorder.start();
Frame videoFrame, mp3Frame ;
while ((videoFrame = videoGrabber.grabFrame()) != null ) recorder.record(videoFrame);
while ((mp3Frame = audioGrabber.grabFrame()) != null) recorder.record(mp3Frame);
return true;
} catch (Exception e) {
log.error("javacv:videoAddAudio error", e); return false;
} finally {
recorder.stop(); recorder.release(); recorder.close();
}
} catch (Exception e) {
log.error("javacv:videoAddAudio error", e); return false;
} finally {
videoGrabber.stop(); audioGrabber.stop(); videoGrabber.release();
audioGrabber.release(); videoGrabber.close(); audioGrabber.close();
}
}
}
调用示例
// 图片 转 视频
avutil.av_log_set_level(avutil.AV_LOG_ERROR); FFmpegLogCallback.set();
File videoFile = new File(uploadProperties.getTempPath() + File.separator + StrUtils.generateUuid32() + ".mp4");
boolean handlerStatus = OpencvUtil.img2Video(Collections.singleton(new FileInputStream("/logo.jpg")),
videoFile.getAbsolutePath(), 263, 263);
if (!handlerStatus) {
videoFile.delete(); return ResponseEnum.UNKONW_ERROR; }
// 视频 添加 音频
File outFile = new File(uploadProperties.getTempPath() + File.separator + StrUtils.generateUuid32() + ".mp4");
handlerStatus = OpencvUtil.videoAddAudio(new FileInputStream(videoFile),
new FileInputStream(audioFilePath), outFile.getAbsolutePath());
if (!handlerStatus) {
outFile.delete(); return ResponseEnum.UNKONW_ERROR; }