Java播放海康的RTSP视频

视频流

视频流,一种流媒体传输方式,市面上常用的流媒体传输协议分别有RTSP、FLV、M3U8、HLS和HDS以及WebRTC。像更早一点的通过falsh插件播放的协议就是RTMP。

RTSP(Real-Time Streaming Protocol)是一种实时流媒体传输协议,适用于点对点传输,可以支持高质量的视频流传输,但是需要较高的带宽支持。

FLV(Flash Video)是一种常见的流媒体格式。它可以通过HTTP传输,在不需要特殊服务器配置的情况下即可播放。FLV支持流式传输和P2P传输,是一种较为稳定和可靠的流媒体协议。

M3U8是苹果公司推出的一种流媒体协议,在移动设备上广泛使用。M3U8协议基于HTTP协议传输,可以实现自适应码率和实时转换等功能,可以在不同的网络环境下提供更好的用户体验。

总的来说就是:RTSP适用于高带宽网络,FLV是能够在不需要特殊服务器配置的情况下即可播放,M3U8协议支持自适应码率和实时转换等功能。不同的协议可以根据具体的需求进行选择。

代码

这边笔者是用的是通过Java调取命令行的形式,首先需要下载ffmpeg,ffmpeg提供了各种平台的下载,下载完成之后通过执行ffmpeg命令来判断是否下载成功(注:下载完成之后还需要把ffmpeg加入到系统加环境变量中)。下面是我的代码部分:

 public String start(HkVideoDto hkVideoDto) {
        String name = hkVideoDto.getName().replace("#", "");
        String pinYinHeadChar = StringUtils.getPinYinHeadChar(name);
        String rtsp = getRtspStream(hkVideoDto);
        log.info("开始获取rtsp流地址:{}", rtsp);
        // 视频存储路径
        String resultUrl = "D:\\syps\\video\\" + pinYinHeadChar + ".m3u8";
        log.info("当前视频存储路径:{}", resultUrl);
        // 清空旧视频
        File videoFolder = new File("D:\\syps\\video");
        if (videoFolder.isDirectory()) {
            File[] files = videoFolder.listFiles();
            // 匹配以pinYinHeadChar字符串为前缀,.ts为后缀的文件
            Pattern pattern = Pattern.compile("^" + pinYinHeadChar + ".*\\.ts$");
            for (File file : files) {
                if (file.isFile()) {
                    String fileName = file.getName();
                    Matcher matcher = pattern.matcher(fileName);
                    if (matcher.matches()) {
                        System.out.println("删除文件:" + fileName);
                        file.delete();
                    }
                }
            }
        }
        File file = new File("D:\\syps\\video\\daemonTmp");
        log.info("当前daemonTmp文件存储路径:{}", file.getAbsolutePath());
        if (!file.exists()) {
            file.mkdirs();
            log.info("创建daemonTmp文件夹成功!");
        }
        File tmpFile = new File("D:\\syps\\video\\temp.tmp");
        log.info("当前temp缓存文件存储路径:{}", tmpFile.getAbsolutePath());
        List<String> commandList = Arrays.asList("ffmpeg", "-i", rtsp, "-vcodec", "libx264",
                        "-map", "0:v", "-c:a", "copy",
                        "-f", "hls", "-threads", "0", "-preset", "ultrafast", "-movflags", "faststart",
                        "-hls_flags", "split_by_time+delete_segments", "-hls_time", "6", "-hls_list_size", "10", resultUrl);
        // 将命令参数列表转换为单个字符串
        String commandString = String.join(" ", commandList);
        // 将命令行字符串记录到日志
        log.info("执行的ffmpeg命令: {}", commandString);
        // 使用命令参数列表创建ProcessBuilder
        ProcessBuilder pb = new ProcessBuilder()
                .command(commandList)
                .redirectErrorStream(true)
                .redirectOutput(tmpFile);
        try {
            log.info("命令行的命令为:", pb.command());
            Process process = pb.start();
            log.info("开始执行ffmpeg命令");
            // 读取命令输出结果
            try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            }
            System.out.println("执行完成");
        } catch (Exception e) {
            log.error("执行ffmpeg命令出错:{}", e.getMessage());
            e.printStackTrace();
        }
        return pinYinHeadChar;
    }

我这里是通过Java提供的 ProcessBuilder类来调用命令提示符来完成的。在写命令之前可以先进入在服务器中查看命令是否可以被执行。然后在通过这个代码来完成转流。

ProcessBuilder类在Java中可以跨平台使用,它会自动处理操作系统之间的差异。

但是,请确保在Linux服务器上安装了ffmpeg工具,因为这是你要执行的命令。如果ffmpeg不在默认的PATH环境变量中,你可能需要提供ffmpeg的完整路径。例如,你可以将ffmpeg替换为/usr/local/bin/ffmpeg(或者在你的系统中ffmpeg的实际路径)。

在Linux上安装ffmpeg的方法可能因发行版而异。在CentOS上,你可以使用以下命令安装ffmpeg

sudo yum install epel-release -y
sudo yum install ffmpeg ffmpeg-devel -y
安装完成后,你可以使用ffmpeg命令。你的Java代码应该可以在Linux服务器上正常运行,只要确保所有相关的工具和库都已经安装。

大致流程可以理解成

首先拉取rtsp流,然后转为hls的分段数据片,最后通过m3u8的格式来播放这些数据片成一个完整的实时流视频。最后返回的是一个视频的播放地址。播放地址需要配合前端同时也需要在nginx中配置视频的播放地址。

问题:大部分视频播放404导致无法播放视频

1:首先想到可能是代码层面的问题,但是经过排查发现代码层面没有问题

2:对代码进行增加更多的日志来获取更多的信息,发现都顺利执行完成了

3:由于是通过代码调用命令行的形式来完成视频的转流以及播放,故通过添加命令行的执行文件观察ß执行流程

4:并且尝试通过vlc直接播放rtsp流发现可以正常播放,然后通过直接在windows窗口调用命令行直接代码中的指令,发现可以正常生成ts文件

5:当你使用 Executor 框架并异步执行 FFmpeg 命令时,命令的执行可能还没有完成,对应的文件可能还没有完整生成,而你的请求却已经过来了,因此会返回 404 错误。因此,在异步执行 FFmpeg 命令时,你需要等待命令执行完成并确认文件完整生成后,才能返回生成的文件路径。

这种方式能够找到文件而不报 404 错误,是因为你没有使用 Executor 框架来异步执行 FFmpeg 命令,而是直接在当前线程中执行了。因此,当命令执行完成后,文件已经被完整地生成了。而且没有使用 Executor 时,你也不需要等待异步执行完成,直接返回生成的文件路径即可。

6:出现播放同一个时间段的原因可能是视频流的切片时间长度(hls_time参数)设置过短,而直接卡住播放不动可能是由于转流过程出错,导致hls切片文件不完整或者损坏。

建议检查以下几个方面:

hls_time参数配置是否合理。hls_time参数是指hls切片的时间长度,如果设置过短,会导致切片频繁,播放过程中容易卡顿。可以将hls_time参数调整为较大的值,比如10s或者15s。

检查转流命令是否正确。在执行转流命令时,需要注意各个参数的含义和格式是否正确,以及输入和输出文件的路径是否正确。

检查转流过程中是否有错误发生。可以查看命令的输出信息,检查是否有异常信息提示,比如网络连接错误、数据传输错误等。同时,还可以检查生成的切片文件是否完整和正常,可使用播放器进行验证。

综上所述,可以通过调整hls_time参数、检查命令和检查转流过程中的错误信息来解决播放同一个时间段和卡顿的问题。如果问题仍然存在,可以详细查看日志信息,定位具体问题。

7:ProcessBuilder pb = new ProcessBuilder() .command("ffmpeg", "-i", rtsp, "-vcodec", "libx264", "-map", "0", "-f", "hls", "-threads", "6", "-preset", "ultrafast", "-hls_flags", "6", "-hls_list_size", "6", "-hls_time", "5", resultUrl)命令参数如下

ffmpeg:命令名称,表示要运行的程序。 -i:输入文件,这里代表输入的视频流地址。 rtsp:视频流地址,指定要转换的源视频流地址。 -vcodec:指定视频的编码器。 libx264:使用x264编码器。 -map:指定要复制的流。 0:表示从第一个输入(输入文件)中复制所有流。 -f:输出的封装格式。 hls:HTTP Live Streaming,Apple的流媒体传输协议。 -threads:使用的线程数,加快编码速度。 6:指定使用6个线程。 -preset:预设编码速度和质量。 ultrafast:尽可能快的编码速度,但会影响视频质量。 -hls_flags:设置hls标志,控制hls行为。 ``:设置为6,表示只保留最新的6个切片文件。 -hls_list_size:设置hls列表文件长度。 6:表示列表文件长度为6。 -hls_time:设置hls分片时长。 5:表示每个分片的时长为5秒。 resultUrl:转换的结果输出路径,存储输出文件的路径。有关更多的参数可以自行去了解,然后根据自己系统的需要来选择最合适的参数来播放。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
海康是一家全球领先的视频监控设备供应商,其实时流传输协议(RTSP)是一种用于在网络上传输音频和视频流的协议。在Java中,我们可以通过使用编程原理来实现与海康设备的RTSP对接。 首先,需要在Java中使用相关的网络编程库,例如Netty或Apache HttpClient来发送和接收RTSP请求和响应。可以通过创建RTSP客户端来建立与海康设备的连接,并发送RTSP请求以获取视频流。 在与海康设备建立连接后,需要发送DESCRIBE请求来获取视频流的详细信息和参数。根据响应,可以解析获取到的视频流信息,例如URL、码率、编码格式等。 接下来,我们可以使用Java中的图像处理库,如OpenCV或JavaFX,来处理和显示视频流。可以使用视频编解码器来解码视频帧,然后使用图像处理算法和技术来处理帧图像,如人脸识别、移动检测等。 此外,还可以使用Java的多线程机制来处理接收和处理视频流的并发性。可以使用线程池来管理并发请求,并使用合适的同步和通信机制来协调线程之间的操作。 最后,需要注意在与海康设备进行RTSP对接时,应该遵循设备提供的RTSP协议规范,并确保网络稳定和设备可靠性。 通过以上步骤和技术,我们可以在Java中实现与海康设备的RTSP对接。通过获取视频流、处理视频图像和保障网络稳定,我们可以实现各种视频监控应用和功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值