Java+ffmpeg+rstp实现视频监控截图功能

1.开发准备

Maven依赖

  <properties>
        <java.version>1.8</java.version>
        <mybatisplus.version>3.2.0</mybatisplus.version>
        <druid.version>1.1.20</druid.version>
        <shiro.version>1.4.0</shiro.version>
        <log4j.version>1.2.17</log4j.version>
        <hutool.version>4.6.8</hutool.version>
        <pinyin4j.version>2.5.1</pinyin4j.version>
        <fastjson.version>1.2.62</fastjson.version>
        <javacv.version>1.5.3</javacv.version>
        <javacv.windows-x86_64>windows-x86_64</javacv.windows-x86_64>
    </properties>
 <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>${javacv.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>flycapture</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>libdc1394</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>libfreenect</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>libfreenect2</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>librealsense</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>librealsense2</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>videoinput</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>artoolkitplus</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>flandmark</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>leptonica</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bytedeco</groupId>
                    <artifactId>tesseract</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>4.2.2-${javacv.version}</version>
            <classifier>${javacv.windows-x86_64}</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacpp</artifactId>
            <version>${javacv.version}</version>
            <classifier>${javacv.windows-x86_64}</classifier>
        </dependency>

        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>openblas</artifactId>
            <version>0.3.9-${javacv.version}</version>
            <classifier>${javacv.windows-x86_64}</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>opencv</artifactId>
            <version>4.3.0-${javacv.version}</version>
            <classifier>${javacv.windows-x86_64}</classifier>
        </dependency>

2.定时任务

从数据库中查询视频监控参数
设置文件路径和截图文件名称
开始通过ffmpeg推流,截取其中一帧保存

    /***
     * 定时获取video数据
     */
    @Scheduled(fixedRate = 10800000)//一小时执行一次    
    @Async
    public void getVideoPic() {
        log.info("定时任务开始:获取VIDEO数据");
        Date now=new Date();
        try {
            //获取可用VIDEO
            List<VideoExt> videoList = videoService.getStationNameByDeptId(19, null);
            if (videoList.size() > 0) {
                //遍历VIDEO
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String dayStr = sdf.format(now);
                int hour = now.getHours();
                int minute = now.getMinutes();

                for (VideoExt video : videoList) {
                    String ip = video.getCameraIp();
                    if (StringUtils.isNotBlank(ip)){
                        //存储图片目录路径
                        String path = "D:\\download\\" + video.getLineName() + "\\" + video.getStationName() + "\\" + dayStr + "\\";
                        File file=new File(path);
                        if (!file.exists()) {
                            file.mkdirs();
                        }
                        //视频配置
                        VideoConfig config = JSONObject.parseObject(video.getConfig(), VideoConfig.class);
                        //绝对路径
                       String targetName =path+ip + "-1-" + hour+minute + ".jpg";
                       //推流rtsp命令
                        String url=VideoUtil.replaceRtspUrl(video.getCameraType(),video.getCameraMode(),video.getCameraUserName(),video.getCameraPassword(),
                       video.getCameraIp(),String.valueOf(config.getPic1()+1));
                        //开始推流和截图
                        VideoUtil.getVideoImagePathByRSTP(url,targetName);


                    }
                }
            }
        } catch (Exception e) {

           log.error(":获取VIDEO数据错误"+e.getMessage());

        }
        log.info("定时任务结束:获取video数据");
    }

推流url

private static String HK_NVR_RTSP_URL="rtsp://{username}:{password}@{ip}:554/Streaming/Channels/{channel}01";
    private static String HK_CAMERA_RTSP_URL="rtsp://{username}:{password}@{ip}:554/Streaming/Channels/{channel}01";
    private static String DH_RTSP_URL="rtsp://{username}:{password}@{ip}:554/cam/realmonitor?channel={channel}&subtype=0";
   

推流url替换参数

public static String replaceRtspUrl(String cj,String mode,String userName,String password,String ip,String channel){
        if(cj.equals("海康")){
            if(mode.equals("NVR")){
                return HK_NVR_RTSP_URL.replace("{username}",userName)
                        .replace("{password}",password)
                        .replace("{ip}",ip).replace("{channel}",channel);
            }else {
                return HK_CAMERA_RTSP_URL.replace("{username}",userName)
                        .replace("{password}",password)
                        .replace("{ip}",ip).replace("{channel}",channel);
            }

        }else if(cj.equals("大华")){
            return DH_RTSP_URL.replace("{username}",userName)
                    .replace("{password}",password)
                    .replace("{ip}",ip).replace("{channel}",channel);
        }
        return "";
}

核心方法
FFmpegFrameGrabber rstp流对象
原理

 /**
     * 解析视频地址并截图
     * @param path rstp 流地址
     * @param picPath 图片存放地址
     * @throws Exception
     */
    public static String getVideoImagePathByRSTP(String path, String picPath) throws Exception {
        log.info("开始拉流"+path+picPath);
        System.setProperty("org.bytedeco.javacpp.maxphysicalbytes", "0");
        System.setProperty("org.bytedeco.javacpp.maxbytes", "0");
        String ret=picPath;
        //创建rstp流对象
        FFmpegFrameGrabber grabber = createGrabber(path);
        try {
            //开启流获取
            grabber.startUnsafe();
            //由于视频第一帧的流可能为黑屏 为了确保实时能截取到准确图像
            // 故此做了个for循环用于覆盖生成图片
            for (int i=0;i<count;i++){
                //获取流视频框内的图像
                Frame frame = grabber.grabFrame();
                //转换图像
                Java2DFrameConverter converter = new Java2DFrameConverter();
                BufferedImage srcImage = converter.getBufferedImage(frame);
                //自定义画图
            if (srcImage!=null) {
                    //创建文件
                    File file = new File(picPath);
                    //输出文件
                    ImageIO.write(srcImage, "jpg", file);
                }
            }
            log.info("结束拉流");
            return ret.replaceAll("\\\\","//");
        }catch (Exception e){
            ret="异常";
           log.error(e.getMessage());
        }finally {
            if(grabber!=null) {
                grabber.stop();
                grabber.close();
                grabber.release();
            }
        }
     return ret;

    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以通过以下步骤来实现JavaRTSPFFmpeg、HTML和Nginx的结合来实现视频实时播放的监控系统: 1. 首先,你需要使用Java来创建一个监控系统的后端服务。你可以使用Java的网络编程库来监听RTSP流并将其解码。可以使用开源的库,例如JRTSP或者Xuggler来处理RTSP流,并将其转换为可供播放的视频流。 2. 接下来,你需要使用FFmpeg来处理视频流。FFmpeg是一个强大的多媒体处理工具,可以用于转码、解码、编码等操作。你可以使用FFmpeg来解码RTSP流,并将其转换为HTML5支持的视频格式,例如HLS(HTTP Live Streaming)或者MPEG-DASH(Dynamic Adaptive Streaming over HTTP)。 3. 在前端方面,你可以使用HTML和JavaScript来创建一个简单的视频播放器。你可以使用HTML5的<video>标签来嵌入视频,并使用JavaScript来控制视频的播放、暂停等操作。你可以使用一些开源的视频播放器库,例如video.js或者plyr来简化开发过程。 4. 最后,你可以使用Nginx作为反向代理服务器来提供视频流的分发和缓存功能。Nginx可以将视频流从后端服务器转发给前端浏览器,并且可以缓存视频文件以提高性能和可靠性。你可以配置Nginx来支持HLS或者MPEG-DASH协议,并且可以使用Nginx的HTTP模块来进行性能优化和安全加固。 综上所述,通过将JavaRTSPFFmpeg、HTML和Nginx结合起来,你可以实现一个监控视频的实时播放系统。这个系统可以从RTSP流中提取视频数据,经过FFmpeg处理后,通过HTML和JavaScript在浏览器中进行播放,并且可以使用Nginx提供性能优化和缓存支持。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值