diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=
404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index a90e9ae..d07c6be 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: casic203
+ password: 123456
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -76,9 +76,9 @@
alarm: true
#zlm 默认服务器配置
media:
- id: your_server_id
+ id: your_server_id1
# [必须修改] zlm服务器的内网IP
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [必须修改] zlm服务器的http.port
http-port: 8080
# [可选] 返回流地址时的ip,置空使用 media.ip
@@ -86,13 +86,13 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip:
+ hook-ip: 192.168.83.37
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
auto-config: true
# [可选] zlm服务器的hook.admin_params=secret
- secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ secret: qZM6aOlerAs90pXdQAUTU1HSfYeqRvsV
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index a90e9ae..d07c6be 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: casic203
+ password: 123456
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -76,9 +76,9 @@
alarm: true
#zlm 默认服务器配置
media:
- id: your_server_id
+ id: your_server_id1
# [必须修改] zlm服务器的内网IP
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [必须修改] zlm服务器的http.port
http-port: 8080
# [可选] 返回流地址时的ip,置空使用 media.ip
@@ -86,13 +86,13 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip:
+ hook-ip: 192.168.83.37
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
auto-config: true
# [可选] zlm服务器的hook.admin_params=secret
- secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ secret: qZM6aOlerAs90pXdQAUTU1HSfYeqRvsV
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
diff --git a/src/main/resources/application-test42.yml b/src/main/resources/application-test42.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/application-test42.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index a90e9ae..d07c6be 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: casic203
+ password: 123456
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -76,9 +76,9 @@
alarm: true
#zlm 默认服务器配置
media:
- id: your_server_id
+ id: your_server_id1
# [必须修改] zlm服务器的内网IP
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [必须修改] zlm服务器的http.port
http-port: 8080
# [可选] 返回流地址时的ip,置空使用 media.ip
@@ -86,13 +86,13 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip:
+ hook-ip: 192.168.83.37
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
auto-config: true
# [可选] zlm服务器的hook.admin_params=secret
- secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ secret: qZM6aOlerAs90pXdQAUTU1HSfYeqRvsV
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
diff --git a/src/main/resources/application-test42.yml b/src/main/resources/application-test42.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/application-test42.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-wvp.yml b/src/main/resources/application-wvp.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index a90e9ae..d07c6be 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: casic203
+ password: 123456
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -76,9 +76,9 @@
alarm: true
#zlm 默认服务器配置
media:
- id: your_server_id
+ id: your_server_id1
# [必须修改] zlm服务器的内网IP
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [必须修改] zlm服务器的http.port
http-port: 8080
# [可选] 返回流地址时的ip,置空使用 media.ip
@@ -86,13 +86,13 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip:
+ hook-ip: 192.168.83.37
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
auto-config: true
# [可选] zlm服务器的hook.admin_params=secret
- secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ secret: qZM6aOlerAs90pXdQAUTU1HSfYeqRvsV
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
diff --git a/src/main/resources/application-test42.yml b/src/main/resources/application-test42.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/application-test42.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-wvp.yml b/src/main/resources/application-wvp.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvp1.yml b/src/main/resources/application-wvp1.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp1.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index a90e9ae..d07c6be 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: casic203
+ password: 123456
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -76,9 +76,9 @@
alarm: true
#zlm 默认服务器配置
media:
- id: your_server_id
+ id: your_server_id1
# [必须修改] zlm服务器的内网IP
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [必须修改] zlm服务器的http.port
http-port: 8080
# [可选] 返回流地址时的ip,置空使用 media.ip
@@ -86,13 +86,13 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip:
+ hook-ip: 192.168.83.37
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
auto-config: true
# [可选] zlm服务器的hook.admin_params=secret
- secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ secret: qZM6aOlerAs90pXdQAUTU1HSfYeqRvsV
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
diff --git a/src/main/resources/application-test42.yml b/src/main/resources/application-test42.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/application-test42.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-wvp.yml b/src/main/resources/application-wvp.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvp1.yml b/src/main/resources/application-wvp1.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp1.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvpbr.yml b/src/main/resources/application-wvpbr.yml
new file mode 100644
index 0000000..dd456fb
--- /dev/null
+++ b/src/main/resources/application-wvpbr.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: localhost
+ # [必须修改] 端口号
+ port: 30001
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:30000/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203!
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 30007
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 172.27.46.84
+ # [可选] 28181服务监听的端口
+ port: 30008
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 172.27.46.84
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 172.27.46.84
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30030,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 30025,30029 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index a90e9ae..d07c6be 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: casic203
+ password: 123456
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -76,9 +76,9 @@
alarm: true
#zlm 默认服务器配置
media:
- id: your_server_id
+ id: your_server_id1
# [必须修改] zlm服务器的内网IP
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [必须修改] zlm服务器的http.port
http-port: 8080
# [可选] 返回流地址时的ip,置空使用 media.ip
@@ -86,13 +86,13 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip:
+ hook-ip: 192.168.83.37
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
auto-config: true
# [可选] zlm服务器的hook.admin_params=secret
- secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ secret: qZM6aOlerAs90pXdQAUTU1HSfYeqRvsV
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
diff --git a/src/main/resources/application-test42.yml b/src/main/resources/application-test42.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/application-test42.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-wvp.yml b/src/main/resources/application-wvp.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvp1.yml b/src/main/resources/application-wvp1.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp1.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvpbr.yml b/src/main/resources/application-wvpbr.yml
new file mode 100644
index 0000000..dd456fb
--- /dev/null
+++ b/src/main/resources/application-wvpbr.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: localhost
+ # [必须修改] 端口号
+ port: 30001
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:30000/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203!
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 30007
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 172.27.46.84
+ # [可选] 28181服务监听的端口
+ port: 30008
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 172.27.46.84
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 172.27.46.84
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30030,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 30025,30029 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 6d3f4ba..3230090 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -2,4 +2,4 @@
application:
name: wvp
profiles:
- active: shentong
\ No newline at end of file
+ active: test
\ No newline at end of file
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index a90e9ae..d07c6be 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: casic203
+ password: 123456
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -76,9 +76,9 @@
alarm: true
#zlm 默认服务器配置
media:
- id: your_server_id
+ id: your_server_id1
# [必须修改] zlm服务器的内网IP
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [必须修改] zlm服务器的http.port
http-port: 8080
# [可选] 返回流地址时的ip,置空使用 media.ip
@@ -86,13 +86,13 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip:
+ hook-ip: 192.168.83.37
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
auto-config: true
# [可选] zlm服务器的hook.admin_params=secret
- secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ secret: qZM6aOlerAs90pXdQAUTU1HSfYeqRvsV
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
diff --git a/src/main/resources/application-test42.yml b/src/main/resources/application-test42.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/application-test42.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-wvp.yml b/src/main/resources/application-wvp.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvp1.yml b/src/main/resources/application-wvp1.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp1.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvpbr.yml b/src/main/resources/application-wvpbr.yml
new file mode 100644
index 0000000..dd456fb
--- /dev/null
+++ b/src/main/resources/application-wvpbr.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: localhost
+ # [必须修改] 端口号
+ port: 30001
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:30000/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203!
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 30007
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 172.27.46.84
+ # [可选] 28181服务监听的端口
+ port: 30008
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 172.27.46.84
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 172.27.46.84
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30030,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 30025,30029 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 6d3f4ba..3230090 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -2,4 +2,4 @@
application:
name: wvp
profiles:
- active: shentong
\ No newline at end of file
+ active: test
\ No newline at end of file
diff --git a/src/main/resources/bak/application-test.yml b/src/main/resources/bak/application-test.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/bak/application-test.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/doc/conf/config.ini b/doc/conf/config.ini
new file mode 100644
index 0000000..b5e0b6d
--- /dev/null
+++ b/doc/conf/config.ini
@@ -0,0 +1,193 @@
+; auto-generated by mINI class {
+
+[api]
+apiDebug=1
+defaultSnap=./www/logo.png
+downloadRoot=./www
+secret=0EcyrurlYHctuBbgue6zMUrI5aF6J8XO
+snapRoot=./www/snap/
+
+[cluster]
+origin_url=
+retry_count=3
+timeout_sec=15
+
+[ffmpeg]
+bin=/usr/bin/ffmpeg
+cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
+log=./ffmpeg/ffmpeg.log
+restart_sec=0
+snap=%s -i %s -y -f mjpeg -frames:v 1 -an %s
+
+[general]
+broadcast_player_count_changed=0
+check_nvidia_dev=1
+enableVhost=0
+enable_ffmpeg_log=0
+flowThreshold=1024
+maxStreamWaitMS=15000
+mediaServerId=your_server_id
+mergeWriteMS=0
+resetWhenRePlay=1
+streamNoneReaderDelayMS=20000
+unready_frame_cache=100
+wait_add_track_ms=3000
+wait_track_ready_ms=10000
+
+[hls]
+broadcastRecordTs=0
+deleteDelaySec=10
+fastRegister=0
+fileBufSize=65536
+segDelay=0
+segDur=2
+segKeep=0
+segNum=3
+segRetain=5
+
+[hook]
+alive_interval=10.0
+enable=0
+on_flow_report=
+on_http_access=
+on_play=
+on_publish=
+on_record_mp4=
+on_record_ts=
+on_rtp_server_timeout=
+on_rtsp_auth=
+on_rtsp_realm=
+on_send_rtp_stopped=
+on_server_exited=
+on_server_keepalive=
+on_server_started=
+on_shell_login=
+on_stream_changed=
+on_stream_none_reader=
+on_stream_not_found=
+retry=1
+retry_delay=3.0
+stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
+timeoutSec=10
+
+[http]
+allow_cross_domains=1
+allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255
+charSet=utf-8
+dirMenu=1
+forbidCacheSuffix=
+forwarded_ip_header=
+keepAliveSecond=30
+maxReqSize=40960
+notFound=404 Not Found您访问的资源不存在!
ZLMediaKit(git hash:2f2e8c2/2024-06-24T09:28:43+08:00,branch:master,build time:2024-07-05T16:42:51)
+port=8080
+rootPath=./www
+sendBufSize=65536
+sslport=8443
+virtualPath=
+
+[multicast]
+addrMax=239.255.255.255
+addrMin=239.0.0.0
+udpTTL=64
+
+[protocol]
+add_mute_audio=1
+auto_close=0
+continue_push_ms=15000
+enable_audio=1
+enable_fmp4=1
+enable_hls=1
+enable_hls_fmp4=0
+enable_mp4=0
+enable_rtmp=1
+enable_rtsp=1
+enable_ts=1
+fmp4_demand=0
+hls_demand=0
+hls_save_path=./www
+modify_stamp=2
+mp4_as_player=0
+mp4_max_second=3600
+mp4_save_path=./www
+paced_sender_ms=0
+rtmp_demand=0
+rtsp_demand=0
+ts_demand=0
+
+[record]
+appName=record
+enableFmp4=0
+fastStart=0
+fileBufSize=65536
+fileRepeat=0
+sampleMS=500
+
+[rtc]
+externIP=
+maxNackMS=5000
+max_bitrate=0
+min_bitrate=0
+nackIntervalRatio=1.0
+nackMaxCount=15
+nackMaxMS=3000
+nackMaxSize=2048
+nackRtpSize=8
+port=8000
+preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
+preferredCodecV=H264,H265,AV1,VP9,VP8
+rembBitRate=0
+rtpCacheCheckInterval=100
+start_bitrate=0
+tcpPort=8000
+timeoutSec=15
+
+[rtmp]
+directProxy=1
+enhanced=0
+handshakeSecond=15
+keepAliveSecond=15
+port=1935
+sslport=0
+
+[rtp]
+audioMtuSize=600
+h264_stap_a=1
+lowLatency=0
+rtpMaxSize=10
+videoMtuSize=1400
+
+[rtp_proxy]
+dumpDir=
+gop_cache=1
+h264_pt=98
+h265_pt=99
+opus_pt=100
+port=10000
+port_range=30000-35000
+ps_pt=96
+rtp_g711_dur_ms=100
+timeoutSec=15
+udp_recv_socket_buffer=4194304
+
+[rtsp]
+authBasic=0
+directProxy=1
+handshakeSecond=15
+keepAliveSecond=15
+lowLatency=0
+port=8554
+rtpTransportType=-1
+sslport=0
+
+[shell]
+maxReqSize=1024
+port=0
+
+[srt]
+latencyMul=4
+pktBufSize=8192
+port=9000
+timeoutSec=5
+
+; } ---
diff --git a/doc/conf/readme b/doc/conf/readme
new file mode 100644
index 0000000..97eaa88
--- /dev/null
+++ b/doc/conf/readme
@@ -0,0 +1,12 @@
+sudo firewall-cmd --permanent --zone=public --add-port=10000/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=10000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=1935/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8554/tcp
+sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
+
+
+sudo firewall-cmd --permanent --zone=public --add-port=8000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=9000/udp
+sudo firewall-cmd --permanent --zone=public --add-port=30000-30050/udp
+# 重新载入防火墙规则
+sudo firewall-cmd --reload
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
index 9241305..e83287b 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/InviteSessionType.java
@@ -1,9 +1,24 @@
package com.genersoft.iot.vmp.common;
public enum InviteSessionType {
+ /**
+ * 实时点播
+ */
PLAY,
+ /**
+ * 历史回放
+ */
PLAYBACK,
+ /**
+ * 文件下载
+ */
DOWNLOAD,
+ /**
+ * 语音广播通知、语音广播应答命令
+ */
BROADCAST,
+ /**
+ * 语音对讲
+ */
TALK
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
index 6c0c050..1421b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
@@ -32,6 +32,7 @@
private static Map requestProcessorMap = new ConcurrentHashMap<>();
private static Map responseProcessorMap = new ConcurrentHashMap<>();
+ private static Map sessionMap = new ConcurrentHashMap<>();
private static ITimeoutProcessor timeoutProcessor;
@Autowired
@@ -39,7 +40,9 @@
@Autowired
private EventPublisher eventPublisher;
-
+ public void addSession(String ip, ServerTransaction serverTransaction) {
+ sessionMap.put(ip, serverTransaction);
+ }
/**
* 添加 request订阅
* @param method 方法名
@@ -132,8 +135,6 @@
responseEvent.getDialog().delete();
}
}
-
-
}
/**
@@ -178,7 +179,7 @@
// serverTransaction.get
// }
-
+ System.out.println("事务断开------------");
// Transaction transaction = null;
// System.out.println("processTransactionTerminated");
// if (transactionTerminatedEvent.isServerTransaction()) {
@@ -201,5 +202,11 @@
CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
}
+ public static Map getSessionMap() {
+ return sessionMap;
+ }
+ public static void setSessionMap(Map sessionMap) {
+ SIPProcessorObserver.sessionMap = sessionMap;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
index ce1074b..9d3c22b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -87,6 +87,7 @@
}
if (message instanceof Request) {
tcpSipProvider.sendRequest((Request)message);
+
}else if (message instanceof Response) {
tcpSipProvider.sendResponse((Response)message);
}
@@ -98,7 +99,8 @@
return;
}
if (message instanceof Request) {
- sipProvider.sendRequest((Request)message);
+ Request request = (Request)message;
+ sipProvider.sendRequest(request);
}else if (message instanceof Response) {
sipProvider.sendResponse((Response)message);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index f984256..536f221 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -84,6 +84,7 @@
Request request = null;
//请求行
SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
+
//via
ArrayList viaHeaders = new ArrayList();
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 5ed3b4e..28a43bc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -351,6 +351,7 @@
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
+
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
index f3f7431..89912a9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -91,7 +91,8 @@
if (msg != null) {
response.setReasonPhrase(msg);
}
-
+ String dia = response.getDialogId(false);
+ logger.info("DialogId:{}----------------",dia);
if (responseAckExtraParam != null) {
if (responseAckExtraParam.sipURI != null && sipRequest.getMethod().equals(Request.INVITE)) {
logger.debug("responseSdpAck SipURI: {}:{}", responseAckExtraParam.sipURI.getHost(), responseAckExtraParam.sipURI.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 1f0ba53..f6da5e5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -93,6 +93,7 @@
// 注销成功
registerFlag = false;
}
+// evt.getServerTransaction()
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
AddressImpl address = (AddressImpl) fromHeader.getAddress();
SipUri uri = (SipUri) address.getURI();
@@ -216,6 +217,8 @@
device.setRegisterTime(DateUtil.getNow());
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
deviceService.online(device, sipTransactionInfo);
+ //开流通道
+// evt.getServerTransaction().sendResponse();
} else {
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
deviceService.offline(deviceId, "主动注销");
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
index 85f2da7..53e04d3 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -6,6 +6,7 @@
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
+import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
@@ -23,6 +24,7 @@
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
+import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.message.Response;
import java.text.ParseException;
@@ -36,7 +38,7 @@
private final Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive";
-
+ private SIPProcessorObserver sipProcessorObserver;
@Autowired
private NotifyMessageHandler notifyMessageHandler;
@@ -60,6 +62,7 @@
// 未注册的设备不做处理
return;
}
+ System.out.println(evt.getDialog());
SIPRequest request = (SIPRequest) evt.getRequest();
logger.info("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
@@ -76,7 +79,6 @@
logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
return;
}
-
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort() || !request.getRemoteAddress().getHostAddress().equals(device.getLocalIp())) {
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 39c67c2..124fee7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -312,6 +312,7 @@
}
}
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
+ //收流IP
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.getHasAudio(), false, device.getStreamModeForParam());
if (ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 3cf100c..3146464 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: 123456
+ password: casic203
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.37
+ ip: 192.168.83.42
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -86,7 +86,7 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip: 192.168.83.37
+ hook-ip: 192.168.83.42
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
# http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
@@ -166,4 +166,5 @@
# - http://127.0.0.1:8080
# [可选] 日志配置, 一般不需要改
logging:
+ level.com.genersoft: debug
config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index a90e9ae..d07c6be 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -32,7 +32,7 @@
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
- password: casic203
+ password: 123456
hikari:
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
initialSize: 50 # 连接池初始化连接数
@@ -60,7 +60,7 @@
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [可选] 28181服务监听的端口
port: 5060
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -76,9 +76,9 @@
alarm: true
#zlm 默认服务器配置
media:
- id: your_server_id
+ id: your_server_id1
# [必须修改] zlm服务器的内网IP
- ip: 192.168.83.42
+ ip: 192.168.83.37
# [必须修改] zlm服务器的http.port
http-port: 8080
# [可选] 返回流地址时的ip,置空使用 media.ip
@@ -86,13 +86,13 @@
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
sdp-ip:
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
- hook-ip:
+ hook-ip: 192.168.83.37
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
http-ssl-port: 1443
# [可选] zlm服务器的hook.admin_params=secret
auto-config: true
# [可选] zlm服务器的hook.admin_params=secret
- secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ secret: qZM6aOlerAs90pXdQAUTU1HSfYeqRvsV
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
rtp:
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
diff --git a/src/main/resources/application-test42.yml b/src/main/resources/application-test42.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/application-test42.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git a/src/main/resources/application-wvp.yml b/src/main/resources/application-wvp.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvp1.yml b/src/main/resources/application-wvp1.yml
new file mode 100644
index 0000000..85cc0d6
--- /dev/null
+++ b/src/main/resources/application-wvp1.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 111.198.10.15
+ # [必须修改] 端口号
+ port: 11412
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password: ew5T4K3#203lwh
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://111.198.10.15:11336/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 22118
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.1.221
+ # [可选] 28181服务监听的端口
+ port: 22117
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 111.198.10.15
+ # [必须修改] zlm服务器的http.port
+ http-port: 22112
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.1.221
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 22130,22160 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 22120,22125 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application-wvpbr.yml b/src/main/resources/application-wvpbr.yml
new file mode 100644
index 0000000..dd456fb
--- /dev/null
+++ b/src/main/resources/application-wvpbr.yml
@@ -0,0 +1,170 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: localhost
+ # [必须修改] 端口号
+ port: 30001
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:30000/wvp_video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: Casic203!
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 30007
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 172.27.46.84
+ # [可选] 28181服务监听的端口
+ port: 30008
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id
+ # [必须修改] zlm服务器的内网IP
+ ip: 172.27.46.84
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 172.27.46.84
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+# http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30030,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 30025,30029 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 180000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 600000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ level.com.genersoft: debug
+ config: classpath:logback-spring.xml
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 6d3f4ba..3230090 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -2,4 +2,4 @@
application:
name: wvp
profiles:
- active: shentong
\ No newline at end of file
+ active: test
\ No newline at end of file
diff --git a/src/main/resources/bak/application-test.yml b/src/main/resources/bak/application-test.yml
new file mode 100644
index 0000000..4b4841c
--- /dev/null
+++ b/src/main/resources/bak/application-test.yml
@@ -0,0 +1,169 @@
+spring:
+ # 设置接口超时时间
+ mvc:
+ async:
+ request-timeout: 20000
+ thymeleaf:
+ cache: false
+ # [可选]上传文件大小限制
+ servlet:
+ multipart:
+ max-file-size: 10MB
+ max-request-size: 100MB
+ # REDIS数据库配置
+ redis:
+ # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
+ host: 127.0.0.1
+ # [必须修改] 端口号
+ port: 6379
+ # [可选] 数据库 DB
+ database: 7
+ # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
+ password:
+ # [可选] 超时时间
+ timeout: 10000
+ # mysql数据源
+ datasource:
+ dynamic:
+ primary: master
+ datasource:
+ master:
+ type: com.zaxxer.hikari.HikariDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/sys-video?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
+ username: root
+ password: casic203
+ hikari:
+ connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
+ initialSize: 50 # 连接池初始化连接数
+ maximum-pool-size: 200 # 连接池最大连接数
+ minimum-idle: 10 # 连接池最小空闲连接数
+ idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
+ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
+#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
+server:
+ port: 18080
+ # [可选] HTTPS配置, 默认不开启
+ ssl:
+ # [可选] 是否开启HTTPS访问
+ enabled: false
+ # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
+ key-store: classpath:test.monitor.89iot.cn.jks
+ # [可选] 证书密码
+ key-store-password: gpf64qmw
+ # [可选] 证书类型, 默认为jks,根据实际修改
+ key-store-type: JKS
+
+# 作为28181服务器的配置
+sip:
+ # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
+ # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
+ # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
+ # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
+ ip: 192.168.83.42
+ # [可选] 28181服务监听的端口
+ port: 5060
+ # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
+ # 后两位为行业编码,定义参照附录D.3
+ # 3701020049标识山东济南历下区 信息行业接入
+ # [可选]
+ domain: 1101080000
+ # [可选]
+ id: 11010800002000000002
+ # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验1234qwer
+ password:
+ # 是否存储alarm信息
+ alarm: true
+#zlm 默认服务器配置
+media:
+ id: your_server_id1
+ # [必须修改] zlm服务器的内网IP
+ ip: 192.168.83.42
+ # [必须修改] zlm服务器的http.port
+ http-port: 8080
+ # [可选] 返回流地址时的ip,置空使用 media.ip
+ stream-ip:
+ # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
+ sdp-ip:
+ # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
+ hook-ip: 192.168.83.42
+ # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
+ http-ssl-port: 1443
+ # [可选] zlm服务器的hook.admin_params=secret
+ auto-config: true
+ # [可选] zlm服务器的hook.admin_params=secret
+ secret: vcOhVPzPUgfcvDLLWTFjgBgVNrCkvi7P
+ # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
+ rtp:
+ # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
+ enable: true
+ # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
+ port-range: 30000,30050 # 端口范围
+ # [可选] 国标级联在此范围内选择端口发送媒体流,
+ send-port-range: 56502,56506 # 端口范围
+ # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
+ record-assist-port: 0
+# [根据业务需求配置]
+user-settings:
+ # [可选] 服务ID,不写则为000000
+ server-id:
+ # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
+ auto-apply-play: true
+ # [可选] 部分设备需要扩展SDP,需要打开此设置
+ senior-sdp: true
+ # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
+ save-position-history: false
+ # 点播/录像回放 等待超时时间,单位:毫秒
+ play-timeout: 18000
+ # 上级点播等待超时时间,单位:毫秒
+ platform-play-timeout: 60000
+ # 是否开启接口鉴权
+ interface-authentication: false
+ # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
+ interface-authentication-excludes:
+ - /api/v1/**
+ # 推流直播是否录制
+ record-push-live: false
+ # 国标是否录制
+ record-sip: false
+ # 是否将日志存储进数据库
+ logInDatabase: true
+ # 使用推流状态作为推流通道状态
+ use-pushing-as-status: true
+ # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
+ use-source-ip-as-stream-ip: false
+ # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
+ stream-on-demand: true
+ # 推流鉴权, 默认开启
+ push-authority: false
+ # 设备上线时是否自动同步通道
+ sync-channel-on-device-online: true
+ # 是否使用设备来源Ip作为回复IP, 不设置则为 false
+ sip-use-source-ip-as-remote-address: false
+ # 是否开启sip日志
+ sip-log: false
+ # 是否开启sql日志
+ sql-log: false
+ # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
+ push-stream-after-ack: true
+ # 消息通道功能-缺少国标ID是否给所有上级发送消息
+ send-to-platforms-when-id-lost: false
+ # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
+ refuse-channel-status-channel-form-notify: true
+ # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000
+ max-notify-count-queue: 10000
+ # 设备/通道状态变化时发送消息
+ device-status-notify: true
+ # 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式
+ use-custom-ssrc-for-parent-invite: true
+ # 国标级联离线后多久重试一次注册
+ register-again-after-time: 60
+ # 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
+ register-keep-int-dialog: true
+ # 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
+ allowed-origins:
+# - http://localhost:18080
+# - http://127.0.0.1:8080
+# [可选] 日志配置, 一般不需要改
+logging:
+ config: classpath:logback-spring.xml
\ No newline at end of file
diff --git "a/\346\211\223\345\214\205/config/wvp-application.yml" "b/\346\211\223\345\214\205/config/wvp-application.yml"
index 71b5da2..0ac18cd 100644
--- "a/\346\211\223\345\214\205/config/wvp-application.yml"
+++ "b/\346\211\223\345\214\205/config/wvp-application.yml"
@@ -117,6 +117,4 @@
# 设备上线时是否自动同步通道
sync-channel-on-device-online: false
# 消息通道功能-缺少国标ID是否给所有上级发送消息
- send-to-platforms-when-id-lost: false
-
-
+ send-to-platforms-when-id-lost: false
\ No newline at end of file