简单易懂!用JavaCV将多张图片合成为视频的教程
最编程
2024-08-03 18:30:19
...
用JavaCV把图片合成视频
这是我最近在做的一个小需求 就是后台把多张照片生成一个视频 并且展示到前端。
一般处理图片视频有两种方式 第一种使用OpenCV 底层c开发的,效率非常快,c和python都会使用这款插件。但是Java中使用也可以 只不过要去官网下载jar 并且依赖dll文件 才可以正常使用。在Linux中更难受 所以在Java中不推荐使用OpenCV。
我们这次主要说第二种 使用JavaCV来处理这个需求,其实他也是封装了opencv ,只不过加了java中的一些接口…废话不过说。
首先我们得导入Javacv的依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.2</version>
</dependency>
首先把要生成视频的图片地址放到一个map中 因为我图片存在本地所以 做了一些逻辑
//将一个gis中的一个文件夹 转map集合
public static Map<Integer,File> gisFileToMap(String filePath, GisCondition gisCondition){
long startTime = System.currentTimeMillis();
//根据类型选择文件路径
String path = filePath+File.separator+typeNames[gisCondition.getTypeId()];
Map<Integer, File> imgMap = new HashMap<Integer, File>();
Integer index = 0;
try {
File file = new File(path);
for (File listFile : file.listFiles()) {
log.info("子文件路径==>"+listFile);
Gis gis = appendGis(listFile);
//提前跳出筛选
log.info("start1===>"+gis.getRecordTime().getTime());
log.info("start2===>"+gisCondition.getStartDate().getTime());
if (gis.getRecordTime().getTime()>gisCondition.getEndDate().getTime()) break;
if (gis.getRecordTime().getTime() < gisCondition.getStartDate().getTime()) continue;
//根据开始日期和结束日期选择图片
if (gis.getRecordTime().getTime() >=
gisCondition.getStartDate().getTime() &&
gis.getRecordTime().getTime() <=
gisCondition.getEndDate().getTime())
{
imgMap.put(index,listFile);
index++;
}
}
}catch (Exception e){
log.info("解析gis图片失败:{}",e.getMessage());
}
System.out.println("筛选图片耗时===》"+(System.currentTimeMillis() - startTime));
return imgMap;
}
然后通过tomcat 映射本地路径 返回最终的一个展示路径
@Override
public String getGisListByLocalFile2(GisCondition gisCondition) {
//把原有的视频删除
File file = new File(localPath);
if (file.exists()){
for (File listFile : file.listFiles()) {
listFile.delete();
}
}
//根据条件筛选出图片
Map<Integer, File> imgMap = CommonUtil.gisFileToMap(filePath, gisCondition);
log.info("==》照片总数:{}",imgMap.size());
String uuid = UUID.randomUUID().toString();
localPath = localPath+uuid+".mp4";
tomcatPath = tomcatPath+uuid+".mp4";
try {
PicToAviUtil.createMp4(localPath,imgMap,width,height);
} catch (FrameRecorder.Exception e) {
log.info("生成视频出错:{}",e.getMessage());
}
return tomcatPath;
}
然后使用的该工具类
package com.gis.util;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FrameRecorder;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Map;
/**
* 图片与视频转换工具类
*/
public class PicToAviUtil {
//设置每秒的帧数
private static final Integer FRAME = 3;
//设置一秒钟几幅图像
private static final Integer SECOND_IMG = 2;
/**
* @param localPath 保存到本地的路径
* @param imgMap 需要转视频的 图片
* @param width 宽度
* @param height 高度
* @throws FrameRecorder.Exception
*/
public static void createMp4(String localPath, Map<Integer, File> imgMap,
int width, int height) throws FrameRecorder.Exception {
long startTime = System.currentTimeMillis();
//视频宽高最好是按照常见的视频的宽高 16:9 或者 9:16
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(localPath, width, height);
//设置视频编码层模式
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
//设置视频多少帧每秒
recorder.setFrameRate(FRAME);
//设置视频图像数据格式
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
//视频格式 可以自己选
recorder.setFormat("mp4");
try {
recorder.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
//录制一个自定义视频
Integer index = 0;
for (; index < imgMap.size(); index++) {
BufferedImage read = ImageIO.read(imgMap.get(index));
//根据帧数 记录每一帧都是一样的
for (int j = 0; j < FRAME; j++) {
recorder.record(converter.getFrame(read));
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//最后一定要结束并释放资源
recorder.stop();
recorder.release();
}
System.out.println("生成视频结束==>"+(System.currentTimeMillis()-startTime));
}
}
最后到页面上可以展示视频
然后可以根据自己的需求去改变工具类中的方法。
最后到页面上可以展示视频
然后可以根据自己的需求去改变工具类中的方法。
JavaCV 不仅可以图片合成视频 还可以对视频进行抽帧 做人脸识别 身份认证等等…
上一篇: Java: 如何获取视频链接的大小和时长
下一篇: 用JavaCV提取视频每一帧的方法