Springboot接入海康摄像头

具体实现参考:

https://blog.csdn.net/weixin_46093962/article/details/123912817

  1. 前端是无法直接播放rstp推流来的视频,所以需要用ffmpeg进行转码。

  1. ffmpeg只能推送TCP或者HTTP协议还不支持ws协议。

  1. 后端的实现暂时只试了ws模式,http没有试过

大致流程图。

ffmpeg.exe -i "rtsp地址" -q 0 -f mpegts -codec:v mpeg1video -s 800x600 推送地址

需要注意的点:

1.Runtime.getRuntime.exec的陷阱

参考:

https://blog.csdn.net/gybshen/article/details/103815379?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-103815379-blog-125668719.pc_relevant_3mothn_strategy_and_data_recovery&spm=1001.2101.3001.4242.1&utm_relevant_index=3

解决方案:

a.定义StreamGobbler类来多开线程处理process.getErrorStream()的信息 ,只要循环输出即可

public class StreamGobbler extends Thread {

    InputStream is;
    String type;

    String videoUrl;


    public StreamGobbler(InputStream is, String type,String videoUrl) {
        this.is = is;
        this.type = type;
        this.videoUrl = videoUrl;
    }

    @Override
    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null) {
                if (type.equals("Error")) {
                    System.out.println(line);
                } else {
//                    System.out.println("Debug:" + line);
                }
            }
            //防止windows进程意外关闭
            ShowWebSocket.conversionVideo.destroy(videoUrl);
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

b.在调用ffmpeg时使用

/**
 * 转换视频流
 */
@Component
@Slf4j
public class ConversionVideo{

    public ConcurrentHashMap<String, Process> processMap = new ConcurrentHashMap<>();


    public void destroy(String videoUrl){
        Process process = processMap.get(videoUrl);
        if (process !=null){
            process.destroy();
            processMap.remove(videoUrl);
            log.info("------------------------推流结束-------------------------");
        }
    }

    public Integer pushVideoAsRTSP(String videoUrl, String controllerUrl){

        Process process = processMap.get(videoUrl);
        // 已经在推送了不需要进行操作
        if(process != null){
            return 0;
        }
        // 获取ffmpeg位置
        String ffmpegPath = System.getProperty("ffmpeg");
        try {
            // cmd命令拼接,注意命令中存在空格
            String command = ffmpegPath;
            // ffmpeg开头,-re代表按照帧率发送,在推流时必须有
            // 指定要推送的视频
            command += " -i \"" + videoUrl + "\"";
            // 指定推送服务器,-f:指定格式
            command += " -q 0 -f mpegts -codec:v mpeg1video -s 800x600 " + controllerUrl;
            log.info("ffmpeg推流命令:" + command);
            // 运行cmd命令,获取其进程
            process = Runtime.getRuntime().exec(command);
            //这里处理process的信息
            StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "Error",videoUrl);
            errorGobbler.start();
            log.info("开始推流");
            processMap.put(videoUrl,process);
        }catch (Exception e){
            e.printStackTrace();
        }
        return 1;
    }

}

2023-04-25

在对接IPCamera 摄像头的时候:

ffmpeg 报错 MPEG-1/2 does not support 15/1 fps

在命令行加上 -r 30 参数即可

原本命令:

 ffmpeg -i “rtsp://admin:foa123456@192.168.1.135:554/h264/ch1/main/av_stream” -q 0 -f mpegts -codec:v mpeg1video -s 1366x768 http://127.0.0.1:8081/123456

改为:

ffmpeg -i "rtsp://admin:foa123456@192.168.1.135:554/h264/ch1/main/av_stream" -r 30 -q 0 -f mpegts -codec:v mpeg1video -s 1366x768 http://127.0.0.1:8081/foa123456

参考地址:https://blog.csdn.net/lclfans1983/article/details/105390071/

20230607 项目切换播放库mpegts(因为要使用video标签做3D视频融合)

前端播放库:

mpegts 和 jsmpeg

自行网上下载文件或者npm下载

mpegts (要求视频流是flv格式)

ffmpeg -i  "视频地址" -q 0 -f flv -vcodec h264 -an -s 1674x942 http://127.0.0.1:8081/foa123456
      var video = document.getElementById('video'+sxtIndex);
      var url = this.app.wsUrl +'/live/' + UtilTools.getDataByObjectFields(sxtData, "unit","");
      var player = mpegts.createPlayer({
          type: 'flv',
          isLive: true,
          url
      });
      player.attachMediaElement(video);
      player.load();
      player.play();

jsmpeg (vue项目需要将jsmpeg.min.js 文件开头的var JSMpeg换成 window.JSMpeg)

      // let canvas = document.getElementById('video')
      let url = 'ws://127.0.0.1:8866/live?porthole=' + this.porthole
      let player = new JSMpeg.Player(url, {canvas: this.$refs.video})

项目初始化ffmpeg

    @PostConstruct
    public void loadFFmpeg() {
        log.info("正在初始化资源,请稍等...");
        String path = System.getProperty("user.dir");
        path = path + "\\ffmpeg\\bin\\ffmpeg.exe ";
        System.setProperty("ffmpeg",path);
        log.info(System.getProperty("ffmpeg"));
        log.info("初始化成功");
    }

2023-07-24 记录

发现使用websocket有一些新问题,比如第二个ws连接和第一个连接使用同一个视频时,第二个连接前端不会播放

使用postman测试

发现第一次请求的时候会返回一个头部video信息,postman看不到具体数据内容,在网页端查看

经过查阅资料,这是flv视频固定开头,使用播放库的时候需要保证第一个发送的信息是这个(不知道是不是所有播放库都需要,待查证,有知道的大神麻烦讲一下)

这个头部信息似乎是固定的(因为我这边要播放的视频流是经过统一转码).因此把这一段的信息直接copy下来,在建立ws连接后发送即可(取中间的16进制数据)

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值