Java实现抓取通道(RTSP或MP4)图片
描述:需要去抓取监控流的一张图片作为监控区域分析图片。
使用技术:ffmpeg
代码实现
方式一
- 引入依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.9</version>
</dependency>
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>4.5.1-2</version>
</dependency>
- 代码实现
/**
* 抓取通道图片
*
* @param channelUrl 通道地址
* @param type 通道类型
*
* @return 结果
*/
private static String captureChannelPicture(String channelUrl, String type) {
try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(channelUrl);
Java2DFrameConverter converter = new Java2DFrameConverter();){
if("RTSP".equals(type)) {
grabber.setOption("rtsp_transport", "tcp"); // 使用TCP传输协议
}
grabber.setTimeout(5000); // 设置超时时间(毫秒)
grabber.start(); // 启动抓取器
// 抓取第一帧(可能需要多试几次才能获取有效帧)
for (int i = 0; i < 5; i++) {
Frame frame = grabber.grabImage();
if (frame != null) {
BufferedImage bufferedImage = converter.getBufferedImage(frame);
String uuid = UUID.randomUUID().toString().replace("-", "");
String filePath = "/data/app/images/base64/" + uuid + ".jpg";
javax.imageio.ImageIO.write(bufferedImage, "jpg", new File(filePath));
return filePath;
}
}
} catch (Exception e) {
log.error("抓取RTSP图片失败:{}", e.toString());
}
return null;
}
缺点:javacv-platform自带ffmpeg,导致所需jar包非常大,大概有1G多
方式二
- 部署环境安装ffmpeg
- 代码实现
/**
* 抓取通道图片
* 使用框架执行导致jar包太大,lib大小有1G
*
* @param channelUrl 通道地址
* @param type 通道类型
*
* @return 结果
*/
private static String captureChannelPictureForCmd(String channelUrl, String type) {
String uuid = UUID.randomUUID().toString().replace("-", "");
String filePath = "/data/app/images/base64/" + uuid + ".jpg";
int maxRetries = 3; // 最大重试次数
int retryCount = 0;
while (retryCount < maxRetries) {
try {
// 构建FFmpeg命令
String[] command;
if ("RTSP".equals(type)) {
command = new String[]{
"ffmpeg",
"-i", channelUrl,
"-vframes", "1",
"-update", "1",
"-rtsp_transport", "tcp",
"-timeout", "5000", // 超时时间(毫秒)
filePath
};
} else {
command = new String[]{
"ffmpeg",
"-i", channelUrl,
"-vframes", "1",
"-update", "1",
"-timeout", "5000",
filePath
};
}
// 执行FFmpeg命令
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
int exitCode = process.waitFor();
if (exitCode == 0) {
return filePath;
} else {
log.warn("抓取RTSP图片失败,退出码: {}, 尝试重试 {}/{}", exitCode, retryCount + 1, maxRetries);
}
} catch (IOException | InterruptedException e) {
log.warn("抓取RTSP图片失败:{}, 尝试重试 {}/{}", e.toString(), retryCount + 1, maxRetries);
}
retryCount++;
}
log.error("抓取RTSP图片失败,重试次数已达上限");
return null;
}

浙公网安备 33010602011771号