Java实现抓取通道(RTSP或MP4)图片

描述:需要去抓取监控流的一张图片作为监控区域分析图片。
使用技术:ffmpeg

代码实现#

方式一#

  1. 引入依赖
<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>
  1. 代码实现
/**
 * 抓取通道图片
 *
 * @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多

方式二#

  1. 部署环境安装ffmpeg
  2. 代码实现
/**
 * 抓取通道图片
 * 使用框架执行导致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;
}
posted @   IamHzc  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示
主题色彩