轉載請注明出處:https://blog.csdn.net/impingo
項目位址:https://github.com/im-pingo/pingos
項目官網:http://pingos.io
将安防攝像頭快速接入網際網路直播伺服器
- 背景描述
- 接入流媒體伺服器
- 實作原理
-
- rtsp轉rtmp伺服器實作原理
- 測試方法
- QQ交流群:697773082
背景描述
在遠古時代,網際網路剛開始發展的時候,世界上出現了一種叫做IPC的東西,它可以通過TCP或者UDP将視訊資料傳送給播放器。開始的時候人們驚歎這種技術帶來的便利,因為人們終于可以在自己電腦上安裝播放器然後觀看IPC捕獲的畫面。
随着網際網路的普及和智能手機的普及,人們的欲望也在野蠻生長,終于他們不再滿足于在固定的一台電腦前觀看IPC監控的視訊。而是希望随時随地可以看到想看的IPC直播内容。
有些廠商意識到了這一點,前些年各大安防廠商開始支援輸出rtmp協定,這就很友善的能夠與網際網路對接。
更有一些網際網路公司針對家用和商用場景直接就出了一些網際網路安防裝置,在他們平台申請個賬号,購買裝置直接聯網。如360水滴攝像頭、海康螢石等等。
但是由于世界上遺留的IPC裝置實在太多,無法做到給每一台裝置都實作rtmp協定,這種情況下就需要我們将IPC支援的rtsp協定轉換成rtmp協定了。
接入流媒體伺服器
支援rtmp協定的安防監控裝置是這樣接入流媒體伺服器的:
不支援rtmp協定的安防裝置是這樣接入流媒體伺服器的:
需要注意的是,圖二中使用ffmpeg将rtsp協定轉換成rtmp協定
為了友善實施,可以利用ffmpeg指令行工具直接做協定轉換。
如下指令:
ffmpeg -i rtsp://xxxxxx -vcodec copy -acodec aac -f flv rtmp://ip/app/stream-name
這樣做的問題在于,如果你的安防裝置過多,你需要手動開啟很多個ffmpeg任務。而且如果你新增或者減少一些裝置,還要去修改你的ffmepg 任務,除非你去開發一套自動伸縮的系統來管理這些任務。
有沒有一種比較簡單,不需要開發工作又自動化的方式呢?有!!!
實作原理
觸發流程是這樣的:
解釋:
關鍵之處在于“雙網卡rtmp伺服器”,這台伺服器的功能是能夠拉取rtsp流,同時能夠将rtsp協定轉換成rtmp協定。
rtsp轉rtmp伺服器實作原理
首先,搭建nginx-rtmp-module伺服器,搭建流程參考我以前的博文分布式直播系統(二)【搭建單點rtmp\http-flv\hls流媒體伺服器】。
使用這個配置可以在有觀衆請求進來時,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