如何将安防摄像头接入互联网直播服务器

转载请注明出处:https://blog.csdn.net/impingo
项目地址:https://github.com/im-pingo/pingos
项目官网:http://pingos.io

背景描述

在远古时代,互联网刚开始发展的时候,世界上出现了一种叫做IPC的东西,它可以通过TCP或者UDP将视频数据传送给播放器。开始的时候人们惊叹这种技术带来的便利,因为人们终于可以在自己电脑上安装播放器然后观看IPC捕获的画面。
随着互联网的普及和智能手机的普及,人们的欲望也在野蛮生长,终于他们不再满足于在固定的一台电脑前观看IPC监控的视频。而是希望随时随地可以看到想看的IPC直播内容。
有些厂商意识到了这一点,前些年各大安防厂商开始支持输出rtmp协议,这就很方便的能够与互联网对接。
更有一些互联网公司针对家用和商用场景直接就出了一些互联网安防设备,在他们平台申请个账号,购买设备直接联网。如360水滴摄像头、海康萤石等等。
但是由于世界上遗留的IPC设备实在太多,无法做到给每一台设备都实现rtmp协议,这种情况下就需要我们将IPC支持的rtsp协议转换成rtmp协议了。

接入流媒体服务器

支持rtmp协议的安防监控设备是这样接入流媒体服务器的:

rtmp
rtmp/http-flv/hls
rtmp/http-flv/hls
安防摄像头
公网rtmp服务器
浏览器
手机

不支持rtmp协议的安防设备是这样接入流媒体服务器的:

rtsp
rtmp
rtmp/http-flv/hls
rtmp/http-flv/hls
安防摄像头
ffmpeg
公网rtmp服务器
浏览器
手机

需要注意的是,图二中使用ffmpeg将rtsp协议转换成rtmp协议
为了方便实施,可以利用ffmpeg命令行工具直接做协议转换。
如下命令:

ffmpeg -i rtsp://xxxxxx -vcodec copy -acodec aac -f flv rtmp://ip/app/stream-name

这样做的问题在于,如果你的安防设备过多,你需要手动开启很多个ffmpeg任务。而且如果你新增或者减少一些设备,还要去修改你的ffmepg 任务,除非你去开发一套自动伸缩的系统来管理这些任务。
有没有一种比较简单,不需要开发工作又自动化的方式呢?有!!!

实现原理

rtsp拉流
rtmp拉流
rtmp/http-flv/hls
rtmp/http-flv/hls
安防设备
内外双网卡rtmp服务器
公网rtmp服务器
浏览器
手机

触发流程是这样的:

播放器 公网rtmp服务器 双网卡rtmp服务器 安防设备 播放请求(rtmp/http-flv/hls) 判断 如果播放器请求的流 不在本机器上 则向双网卡rtmp服务器 回源拉流 拉流请求(rtmp) rtmp拉流 返回流媒体数据(rtsp) 返回流媒体数据(rtmp) 返回流媒体数据 播放器 公网rtmp服务器 双网卡rtmp服务器 安防设备

解释:
关键之处在于“双网卡rtmp服务器”,这台服务器的功能是能够拉取rtsp流,同时能够将rtsp协议转换成rtmp协议。

rtsp转rtmp服务器实现原理

首先,搭建nginx-rtmp-module服务器,搭建流程参考我以前的博文分布式直播系统(二)【搭建单点rtmp\http-flv\hls流媒体服务器】

exec_pull bash -c "ffmepg -i rtsp://$parg_ip/$parg_uri -vcodec copy -acodec aac -f flv rtmp://127.0.0.1/live/$name";

使用这个配置可以在有观众请求进来时,nginx-rtmp服务器向目IPC设备发起rtsp拉流,并且将rtsp协议转换成rtmp协议回推给本机。等待公网服务器过来拉流。

如果IPC设备rtsp地址为:rtsp://192.168.1.2/stream/1
双网卡rtmp服务器的公网地址为:34.2.1.2
公网rtmp服务器地址为:34.2.1.3

双网卡rtmp服务器配置模板如下:

user  root;
daemon on;
master_process on;
worker_processes  1;
#worker_rlimit 4g;
#working_directory /usr/local/openresty/nginx/logs;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  logs/error.log  info;

worker_rlimit_nofile 102400;
worker_rlimit_core   2G;
working_directory    /tmp;

#pid        logs/nginx.pid;

events {
    use epoll;
    worker_connections  1024;
    multi_listen unix:/tmp/http 80;
    multi_listen unix:/tmp/rtmp 1935;
}

stream_zone buckets=1024 streams=4096;

rtmp {
    log_format log_bandwidth '{"app":"$app","name":"$name","bitrate":$bitrate,"args":"$args","timestamp":$ntp,"ts":"$time_local","type":"$command","remote_addr":"$remote_addr","domain":"$domain"}';
    access_log logs/bandwidth.log log_bandwidth trunc=60s;

    server {
        listen 1935;
        serverid 000;
        out_queue 2048;
   
        application live {
            rtmp_auto_pull on;
            rtmp_auto_pull_port unix:/tmp/rtmp;

#           live_record on;
#live_record_path /tmp/record;

#            recorder r1{
#                record all;
#                record_path /tmp/record;
#            }

            exec_pull bash -c "ffmepg -i rtsp://$parg_ip/$parg_uri -vcodec copy -acodec aac -f flv rtmp://127.0.0.1/live/$name";

            live on;
            hls on;
            hls_path /tmp/hls;
            hls_fragment 4000ms;
            hls_max_fragment 6000ms;
            hls_playlist_length 12000ms;
            hls_type event;

            hls2memory on;
            mpegts_cache_time 20s;

            hls2_fragment 1300ms;
            hls2_max_fragment 1600ms;
            hls2_playlist_length 3900ms;

            wait_key on;
            wait_video on;
            cache_time 3s;
            low_latency off;
            fix_timestamp 0s;
# h265 codecid, default 12
            hevc_codecid  12;
        }
    }
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_X-Forwarded-For" "$http_X-Real-IP" "$host"';


    access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #reset_server_name www.test1.com www.test2.com;
    #gzip  on;
    server {
         listen 80;
        location /rtmp_stat {
            rtmp_stat all;
            rtmp_stat_stylesheet /stat.xsl;
        }

        location /xstat {
            rtmp_stat all;
        }

        location /sys_stat {
            sys_stat;
        }

        location /control {
            rtmp_control all;
        }
         location /live {
            flv_live 1935;
         }
         location /ts {
            ts_live 1935 app=live;
         }
         location /hls {
            # Serve HLS fragments
             types {
                 application/vnd.apple.mpegurl m3u8;
                 video/mp2t ts;
             }
             root /tmp;
             expires -1;
             add_header Cache-Control no-cache;
             add_header 'Access-Control-Allow-Origin' '*';
         }

        location /hls2 {
             hls2_live 1935 app=live;
             add_header 'Access-Control-Allow-Origin' '*';
             add_header Cache-Control no-cache;
         }
         location / {
             chunked_transfer_encoding on;
             root html/;
         }
    }
}

公网服务器配置模板:

user  root;
daemon on;
master_process on;
worker_processes  1;
#worker_rlimit 4g;
#working_directory /usr/local/openresty/nginx/logs;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  logs/error.log  info;

worker_rlimit_nofile 102400;
worker_rlimit_core   2G;
working_directory    /tmp;

#pid        logs/nginx.pid;

events {
    use epoll;
    worker_connections  1024;
    multi_listen unix:/tmp/http 80;
    multi_listen unix:/tmp/rtmp 1935;
}

stream_zone buckets=1024 streams=4096;

rtmp {
    log_format log_bandwidth '{"app":"$app","name":"$name","bitrate":$bitrate,"args":"$args","timestamp":$ntp,"ts":"$time_local","type":"$command","remote_addr":"$remote_addr","domain":"$domain"}';
    access_log logs/bandwidth.log log_bandwidth trunc=60s;

    server {
        listen 1935;
        serverid 000;
        out_queue 2048;
   
        application live {
            rtmp_auto_pull on;
            rtmp_auto_pull_port unix:/tmp/rtmp;

#           live_record on;
#live_record_path /tmp/record;

#            recorder r1{
#                record all;
#                record_path /tmp/record;
#            }

#            exec_publish bash -c "ffmepg -i rtmp://127.0.0.1/live/$name -c copy /tmp/mp4/$name-$starttime.mp4";
            pull rtmp://34.2.1.2/live app=live; # 双网卡rtmp服务器地址
            live on;
            hls on;
            hls_path /tmp/hls;
            hls_fragment 4000ms;
            hls_max_fragment 6000ms;
            hls_playlist_length 12000ms;
            hls_type event;

            hls2memory on;
            mpegts_cache_time 20s;

            hls2_fragment 1300ms;
            hls2_max_fragment 1600ms;
            hls2_playlist_length 3900ms;

            wait_key on;
            wait_video on;
            cache_time 3s;
            low_latency off;
            fix_timestamp 0s;
# h265 codecid, default 12
            hevc_codecid  12;
        }
    }
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_X-Forwarded-For" "$http_X-Real-IP" "$host"';


    access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #reset_server_name www.test1.com www.test2.com;
    #gzip  on;
    server {
         listen 80;
        location /rtmp_stat {
            rtmp_stat all;
            rtmp_stat_stylesheet /stat.xsl;
        }

        location /xstat {
            rtmp_stat all;
        }

        location /sys_stat {
            sys_stat;
        }

        location /control {
            rtmp_control all;
        }
         location /live {
            flv_live 1935;
         }
         location /ts {
            ts_live 1935 app=live;
         }
         location /hls {
            # Serve HLS fragments
             types {
                 application/vnd.apple.mpegurl m3u8;
                 video/mp2t ts;
             }
             root /tmp;
             expires -1;
             add_header Cache-Control no-cache;
             add_header 'Access-Control-Allow-Origin' '*';
         }

        location /hls2 {
             hls2_live 1935 app=live;
             add_header 'Access-Control-Allow-Origin' '*';
             add_header Cache-Control no-cache;
         }
         location / {
             chunked_transfer_encoding on;
             root html/;
         }
    }
}

测试方法

配置模板里和下面出现的ip地址和ipc的rtsp地址都是为了方便描述虚构的,你要根据自己的实际情况配置真实地址

从公网rtmp服务器播放视频:
rtmp://34.2.1.3/live/s0?ip=192.168.1.2&uri=/strea/0
http://34.2.1.3/live/s0?ip=192.168.1.2&uri=/strea/0

QQ交流群:697773082

QQ交流群:697773082

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值