引入依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.7</version>
</dependency>
或者单独引入
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>5.0-1.5.7</version>
<exclusions>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.7</version>
</dependency>
代码块
截取某一帧成图
/**
* 获取rtsp的某帧图片
*
* @param response
* @return
*/
public String getMonitorImage(String url) throws IOException {
FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(url);
grabber.setOption("rtsp_transport", "tcp");
grabber.setImageWidth(960);
grabber.setImageHeight(540);
grabber.start();
String currentDir = System.getProperty("user.dir");
File outPut = new File(currentDir + "\\temp.jpg");
while (true) {
Frame frame = grabber.grabImage();
if (frame != null) {
ImageIO.write(FrameToBufferedImage(frame), "jpg", outPut);
grabber.stop();
grabber.release();
break;
}
}
String result = TransformPhotoToBase64Data(currentDir, "\\temp.jpg");
outPut.delete();
return result;
}
/**
* 图片 转 base64
*
* @param LoadPath
* @param DataName
* @return
*/
public String TransformPhotoToBase64Data(String LoadPath, String DataName) {
//获取Base64编码器
Base64.Encoder encoder = Base64.getEncoder();
//数据集缓存器
byte[] ImgContainer = null;
//文件输入流
FileInputStream fileInputStream = null;
try {
//到指定路径寻找文件
fileInputStream = new FileInputStream(LoadPath + DataName);
//设置图片字节数据缓冲区大小
ImgContainer = new byte[fileInputStream.available()];
//将数据流中的图片数据读进缓冲区
fileInputStream.read(ImgContainer);
//将图片编码转换成Base64格式的数据集
String Base64ImgData = encoder.encodeToString(ImgContainer);
//关闭数据流
fileInputStream.close();
//将缓冲区数据转换成字符数据返回
return Base64ImgData;
} catch (FileNotFoundException e) {
return "找不到指定文件!";
} catch (IOException e) {
e.printStackTrace();
}
return "null";
}
录制MP4的方法,最好使用异步方法访问,可以返回uuid到前端,前端拿到uuid可以自己操作录制时长,同时也有最大时长的控制
public static ConcurrentHashMap<String, Object> mp = new ConcurrentHashMap<>();
public void getMp4FromMonitor(String monitorUrl,String uuid) throws FrameGrabber.Exception, InterruptedException {
mp.put(uuid, ***);//唯一标识或是摄像头信息
FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(monitorUrl);
grabber.setOption("rtsp_transport", "tcp");
grabber.setImageWidth(2560);
grabber.setImageHeight(1440);
String fileUrl = System.getProperty("user.dir") + "\\" + uuid + ".mp4";
//流媒体输出地址,分辨率(长,高),是否录制音频(0:不录制/1:录制)
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(fileUrl, 2560, 1440, 1);
recorder.setFrameRate(15);
CountDownLatch count = new CountDownLatch(1);
//最大录制时长控制
new Thread(() -> {
try {
Thread.sleep(40000);
mp.remove(uuid);
count.countDown();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, "setMp4Time").start();
Thread t = new Thread(() -> {
try {
grabber.start();
recorder.start();
Frame frame = null;
while (mp.containsKey(uuid) && (frame = grabber.grabFrame()) != null) {
recorder.record(frame);
}
recorder.stop();
grabber.stop();
count.countDown();
} catch (FrameRecorder.Exception | FrameGrabber.Exception e) {
System.out.println(uuid);
throw new RuntimeException(e);
}
}, "getMp4");
t.start();
//主线程等待
count.await();
//防止最大时限后,主线程比录制线程更快执行保存逻辑
while (!t.getState().equals(Thread.State.TERMINATED)) {
}
//调用接口保存mp4
...
}
/**
* 停止录制视频
*
* @param uuid
*/
public void stopRecordMp4(String uuid) throws InterruptedException {
mp.remove(uuid);
}