diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java index b8d5f186..f4774393 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java @@ -195,8 +195,7 @@ public class StreamInfo implements Serializable, Cloneable{ } } - public void setFlv(String host, int port, int sslPort, String app, String stream, String callIdParam) { - String file = String.format("%s/%s.live.flv%s", app, stream, callIdParam); + public void setFlv(String host, int port, int sslPort, String file) { if (port > 0) { this.flv = new StreamURL("http", host, port, file); } @@ -207,6 +206,15 @@ public class StreamInfo implements Serializable, Cloneable{ } } + public void setWsFlv(String host, int port, int sslPort, String file) { + if (port > 0) { + this.ws_flv = new StreamURL("ws", host, port, file); + } + if (sslPort > 0) { + this.wss_flv = new StreamURL("wss", host, sslPort, file); + } + } + public void setFmp4(String host, int port, int sslPort, String app, String stream, String callIdParam) { String file = String.format("%s/%s.live.mp4%s", app, stream, callIdParam); if (port > 0) { diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java index a61154fc..0dc1ba98 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -42,12 +42,24 @@ public class MediaConfig{ @Value("${media.stream-ip:${media.ip}}") private String streamIp; - @Value("${media.http-port}") + @Value("${media.http-port:0}") private Integer httpPort; + @Value("${media.flv-port:0}") + private Integer flvPort = 0; + + @Value("${media.ws-flv-port:0}") + private Integer wsFlvPort = 0; + @Value("${media.http-ssl-port:0}") private Integer httpSSlPort = 0; + @Value("${media.flv-ssl-port:0}") + private Integer flvSSlPort = 0; + + @Value("${media.ws-flv-ssl-port:0}") + private Integer wsFlvSSlPort = 0; + @Value("${media.rtmp-port:0}") private Integer rtmpPort = 0; @@ -208,7 +220,11 @@ public class MediaConfig{ mediaServerItem.setSdpIp(getSdpIp()); mediaServerItem.setStreamIp(getStreamIp()); mediaServerItem.setHttpPort(httpPort); + mediaServerItem.setFlvPort(flvPort); + mediaServerItem.setWsFlvPort(wsFlvPort); mediaServerItem.setHttpSSlPort(httpSSlPort); + mediaServerItem.setFlvSSLPort(flvSSlPort); + mediaServerItem.setWsFlvSSLPort(wsFlvSSlPort); mediaServerItem.setRtmpPort(rtmpPort); mediaServerItem.setRtmpSSlPort(rtmpSSlPort); mediaServerItem.setRtpProxyPort(getRtpProxyPort()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index c3e5b596..88fffba0 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -500,7 +500,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements String startTimeStr = DateUtil.urlFormatter.format(start); String endTimeStr = DateUtil.urlFormatter.format(end); String stream = device.getDeviceId() + "_" + channelId + "_" + startTimeStr + "_" + endTimeStr; - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0,false, false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0,false,!channel.isHasAudio(), false, device.getStreamModeForParam()); sendRtpItem.setStream(stream); // 写入redis, 超时时回复 redisCatchStorage.updateSendRTPSever(sendRtpItem); @@ -530,7 +530,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements } sendRtpItem.setPlayType(InviteStreamType.DOWNLOAD); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,!channel.isHasAudio(), false, device.getStreamModeForParam()); sendRtpItem.setStream(ssrcInfo.getStream()); // 写入redis, 超时时回复 redisCatchStorage.updateSendRTPSever(sendRtpItem); diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaNodeServerService.java b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaNodeServerService.java index aaa72ddf..644be243 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaNodeServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaNodeServerService.java @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.media.bean.MediaInfo; import com.genersoft.iot.vmp.media.service.IMediaNodeServerService; import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @@ -14,9 +15,12 @@ import java.util.Map; @Service("abl") public class ABLMediaNodeServerService implements IMediaNodeServerService { + @Autowired + private ABLRESTfulUtils ablresTfulUtils; + @Override - public int createRTPServer(MediaServer mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { - return 0; + public int createRTPServer(MediaServer mediaServer, String stream, long ssrc, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode) { + return ablresTfulUtils.openRtpServer(mediaServer, "rtp", stream, 96, port, tcpMode, disableAudio?1:0); } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServerStatusManger.java b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServerStatusManger.java index 5895ce2a..cb55695b 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServerStatusManger.java +++ b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServerStatusManger.java @@ -212,15 +212,24 @@ public class ABLMediaServerStatusManger { // if (mediaServerItem.getHttpSSlPort() == 0) { // mediaServerItem.setHttpSSlPort(ablServerConfig.getHttpSSLport()); // } - if (mediaServerItem.getRtmpPort() == 0) { + if (mediaServerItem.getRtmpPort() == 0 && ablServerConfig.getRtmpPort() != null) { mediaServerItem.setRtmpPort(ablServerConfig.getRtmpPort()); } // if (mediaServerItem.getRtmpSSlPort() == 0) { // mediaServerItem.setRtmpSSlPort(ablServerConfig.getRtmpSslPort()); // } - if (mediaServerItem.getRtspPort() == 0) { + if (mediaServerItem.getRtspPort() == 0 && ablServerConfig.getRtspPort() != null) { mediaServerItem.setRtspPort(ablServerConfig.getRtspPort()); } + if (mediaServerItem.getFlvPort() == 0 && ablServerConfig.getHttpFlvPort() != null) { + mediaServerItem.setFlvPort(ablServerConfig.getHttpFlvPort()); + } + if (mediaServerItem.getWsFlvPort() == 0 && ablServerConfig.getWsPort() != null) { + mediaServerItem.setWsFlvPort(ablServerConfig.getWsPort()); + } + if (mediaServerItem.getRtpProxyPort() == 0 && ablServerConfig.getPsTsRecvPort() != null) { + mediaServerItem.setRtpProxyPort(ablServerConfig.getPsTsRecvPort()); + } // if (mediaServerItem.getRtspSSLPort() == 0) { // mediaServerItem.setRtspSSLPort(ablServerConfig.getRtspSSlport()); // } diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServer高性能流媒体服务器使用说明.txt b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServer高性能流媒体服务器使用说明.txt new file mode 100644 index 00000000..9cffc983 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServer高性能流媒体服务器使用说明.txt @@ -0,0 +1,1743 @@ +一、功能说明 + ABLMediaServer高性能流媒体服务器,windows平台采用高性能的完成端口网络模型、Linux下采用epoll,加上线程池进行媒体数据 + 的接收、转换、发送。服务器的性能强劲、运行稳定,坚如磐石。经过压力测试比较,转发性能、CPU占有率、运行稳定性优势明显 。可 + 以通过ffmpeg命令或者其他标准的rtsp、rtmp推流函数往ABLMediaServer推送rtsp流、rtmp流,请求服务器代理拉流,请求服务器接收国 + 标GB28181。服务器通过转换,输出标准的rtsp码流、rtmp码流、http-flv、ws-flv 码流(支持H265视频输出)、http-mp4(视频支持H264、 + H265,音频支持AAC)、hls码流输出(视频支持H264、H265,音频支持AAC)、GB28181码流(国标PS流 )输出。 + 流媒体服务器支持录像、支持智能录像删除、录像查询、录像文件点播、录像文件极速下载。http-flv、ws-flv、http-mp4 协议点播时 + 支持暂停继续、支持拖动播放。rtsp点播录像文件时支持慢放(1/16、1/8、1/4、1/2),快放(2、4、8、16 )、正常速度、支持拖动播放。 + 流媒体服务器支秒级(基本上1秒以内)图片抓拍,支持对抓拍的图片进行查找,支持抓拍图片以http协议下载。 + 服务器支持H265转码为H264,转码输出视频支持指定分辨率、宽高、码率大小等等参数。Windows平台支持英伟达显卡硬件加速转码。实 + 测linux 平台能最大并发转码40路H265(硬件环境 至强 E5 2650 V3),实测windows 平台能最大并发转码35路H265(i9 + 英伟达 RTX 2080) + Linux 新增支持英伟达专业显卡,支持硬件解码、硬件编码,支持多个显卡同时进行转码。两张特斯拉T4(16G)显卡可以同时把80路1080P + 的H265视频转码为 1280 x 720 的H264,转码延时低于10毫秒,如果需要更强的转码功能可以多插几张显卡或者集群 。 + 服务器支持转码出来的视频打入自定义水印,支持水印的字符内容、字体大小、 字体颜色、字体位置都可以在配置文件中配置。 + 非常感谢ZLMediaKit和Media-Server 两个工程项目的作者,ABLMediaSever参考复用了ZLMediaKit的http请求函数的参数表(请求的URL + 及请求的参数名及一些初始值)以及整个框架的一些设计思想。直接调用了Media-Server 工程的 rtmp、flv、hls、fmp4 复用与解复用等等。 + 非常崇拜与感谢两位大佬为中国的开源流媒体努力与付出,再次感谢。 + + 【欢迎加入高性能流媒体服务QQ群 873666268 】 + +二、ABLMediaServer主要功能 + + 网络协议媒体输入 + rtsp、rtmp外部主动推流输入 + 1、rtsp外部主动推流 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + 2、rtmp外部主动推流 (支持 视频:H264、H265 ,音频:AAC) + 3、国标GB28181输入 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + 4、交通运输部jtt1078 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + + rtsp、rtmp、http-flv、本地mp4文件 拉流输入: + 1、rtsp 拉流 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + 2、rtmp 拉流 (支持 视频:H264、H265 ,音频:AAC) + 3、http-flv 拉流 (支持 视频:H264、H265 ,音频:AAC) + 4、本地mp4 拉流 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + + websock方式私有协议发送PCM数据进入流媒体服务器(可以在浏览器录音通过websocket以下面的私有协议把语音接入流媒体服务器方便国标对讲、或者其他应用比如语音广播) + 1、数据包格式 + 包头 + 数据类型 + 长度 + 数据包 + 包头4个字节 0xAB 0xCD 0xEF 0xAB + 数据类型  1 个字节 ,[ 0x01 推流音频注册 ] [0x02 发送 PCM 音频数据包] [0x03 断开音频推流 ] + 长度   2 个字节 ,网络字节顺序(大端) + 数据包 音频注册包、pcm音频数据包、注销包 + + 2、数据包类型 + 1)、音频注册包 ,json 格式 + {"method":"register","app":"talk","stream":"xian_1","audioCodec":"pcm","channels":1,"sampleRate":16000,"targetAudioCodec":"g711a"} + + 样例:发送音频注册 + websocket 只要连接上来,就首先发送 音频注册包 + (0xAB 0xCD 0xEF 0xAB) + 0x01 + strlen(音频注册包) + {"method":"register","app":"talk","stream":"xian_1","audioCodec":"pcm","channels":1,"sampleRate":16000,"targetAudioCodec":"g711a"} + + 2) 、音频数据包 只支持 16位采样精度的pcm ,单通道、双通道、常见的采样频率都支持(8000、16000、32000、48000) + 样例:现在只发送纯pcm音频数据 + (0xAB 0xCD 0xEF 0xAB) + 0x02 + strlen(pcm纯音频数据) + pcm纯音频数据 + + 3)、注销包 + {"method":"destruction"} + + 样例:发送注销包 + (0xAB 0xCD 0xEF 0xAB) + 0x03 + strlen({"method":"destruction"} ) + {"method":"destruction"} + + 支持用ffmpeg推纯音频流接入流媒体服务器,支持的音频格式有(g711A、G711U、AAC、MP3) + 1、以rtsp协议推本地aac文件接入流媒体 + ffmpeg -re -stream_loop -1 -i F:\music\xxx.aac -c:a aac -rtsp_transport tcp -f rtsp rtsp://190.15.240.11:554/music/aac1 + + 2、以rtmp协议推本地aac文件接入流媒体 + ffmpeg -re -stream_loop -1 -i F:\music\xxx.aac -c:a aac -f flv rtmp://190.15.240.11:1935/music/aac2 + + 3、以rtsp协议推本地mp3文件接入流媒体 + ffmpeg -re -stream_loop -1 -i F:\music\xxx.mp3 -c:a mp3 -rtsp_transport tcp -f rtsp rtsp://190.15.240.11:554/music/aac3 + + 4、以rtmp协议推本地mp3文件接入流媒体 + ffmpeg -re -stream_loop -1 -i F:\music\xxx.mp3 -c:a mp3 -f flv rtmp://190.15.240.11:1935/music/aac4 + + 5、以rtsp协议推本地mp4文件中的纯音频流接入服务器 + 1) 比如推一个视频格式为h264,音频为aac的mp4文件中的音频流进入服务器,那么服务器接收到的音频流为aac ,视频不做推送 + ffmpeg -re -stream_loop -1 -i F:\video\H264_AAC_2021-02-10_1080P.mp4 -vn -acodec copy -rtsp_transport tcp -f rtsp rtsp://44.35.33.39:554/music/aac5 + + 2) 比如推一个视频格式为h264,音频为g711A的mp4文件中的音频流进入服务器,那么服务器接收到的音频流为g711A ,视频不做推送 + ffmpeg -re -stream_loop -1 -i F:\video\H264-G711A-92017.mp4 -vn -acodec copy -rtsp_transport tcp -f rtsp rtsp://44.35.33.39:554/music/aac6 + + 3) 比如推一个视频格式为h264,音频为g711U的mp4文件中的音频流进入服务器,那么服务器接收到的音频流为g711U ,视频不做推送 + ffmpeg -re -stream_loop -1 -i F:\video\H264-G711U-56434.mp4 -vn -acodec copy -rtsp_transport tcp -f rtsp rtsp://44.35.33.39:554/music/aac7 + + 网络协议媒体 输出: + 被动拉流输出 + 1、rtsp (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + 2、rtmp (支持 视频:H264、H265 ,音频:AAC) + 3、GB28181码流 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + 4、http-flv (支持 视频:H264、H265 ,音频:AAC) + 5、http-hls (支持 视频:H264、H265 ,音频:AAC) + 6、http-mp4 (支持 视频:H264、H265 ,音频:AAC) + 7、websocket-flv (支持 视频:H264、H265 ,音频:AAC) + 8、webrtc (支持 视频:H264、H265 ,音频:G711A、G711U、OPUS) + 9、交通运输部jtt1078 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + + rtsp、rtmp、gb28181、jtt1078 主动推流输出: + 1、rtsp推流 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + 2、rtmp推流 (支持 视频:H264、H265 ,音频:AAC) + 3、GB28181推流 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + 4、交通运输部jtt1078 (支持 视频:H264、H265 ,音频:AAC、G711A、G711U) + + +三、简明使用例子 + 1) 首先要配置 ABLMediaServer.ini 里面的 本机的IP地址 localipAddress 、recordPath 项。 + + 1 本机的IP地址,最好需要配置准确(如果不配置程序会自动获取一个地址代替,如果本机有多个地址可能会不准确,如果配置则使用配置的IP地址,这样就准确), + 因为调用 getMediaList 获取可用媒体源的json中,会使用到本机的IP地址来拼接 rtsp、rtmp、http-flv、ws-flv、hls、http-mp4 的播放url 。 + 调用 getMediaList 返回的json串中有如下url子项: + "url": { + "rtsp": "rtsp://10.0.0.239:554/Media/Camera_00001", + "rtmp": "rtmp://10.0.0.239:1935/Media/Camera_00001", + "http-flv": "http://10.0.0.239:8088/Media/Camera_00001.flv", + "ws-flv": "ws://10.0.0.239:6088/Media/Camera_00001.flv", + "http-mp4": "http://10.0.0.239:5088/Media/Camera_00001.mp4", + "http-hls": "http://10.0.0.239:9088/Media/Camera_00001.m3u8" + } + + 其中的 10.0.0.239 就是可以从 localipAddress 配置项 精确获取 。 + + 2、录像路径配置 recordPath,如果不需要录像,可以忽略录像路径配置 + # 录像文件保存路径,如果不配置录像文件保存在应用程序所在的路径下的record子路径,如果配置路径则保存在配置的路径的record里面 + # 注意:如果需要录像存储,存储的硬盘千万不要分区,整个硬盘作为一个区,因为服务器没有执行两个以上的盘符操作。 + # 录像保存路径配置 windows平台的路径配置 比如 D:\video ,Linux 平台配置 /home/video + # 录像路径使用了默认路径,就一直使用默认路径,如果使用了配置路径就一直使用配置路径,确保使用的路径的硬盘空间为最大的,如果需要更换路径,要把原来的录像路径的视频全部删除。 + # 1路高清5M的摄像头,如果录像的话,每小时产生2G大小左右的录像文件。可以根据这个来计算需要购买多大的硬盘,接入多少路摄像头,需要设置录像文件最大的保存时间 + + 2)、 媒体输出规则: [network protocol]://[ip]:[port]/[app]/[stream][.extend] + + 【注:如果自己不想拼接播放url ,可以调用http函数 /index/api/getMediaList,返回可播放媒 + 体源中有各种播放协议的url, 详见下面的函数 /index/api/getMediaList 】 + + 说明: + [network protocol] 有 rtsp、rtmp、http、ws + [ip] 就是服务器所在的IP地址 + [port] 各个网络协议分享时设置的端口号,详见 ABLMediaServer.ini 的配置文件,里面有相应的网络协议配置端口 + [app] 各种网络协议发送过来设置的一级名字 + [stream] 各种网络协议发送过来设置的二级名字 + [.extend] 扩展名字,主要为为了访问服务器时,服务器需要识别网络协议需要客户端发送过来的扩展名。 + rtsp、rtmp 不需要扩展名, + http-flv 、ws-flv 扩展名为 .flv + hls 方式访问时, 扩展名为 .m3u8 + http-mp4访问时 扩展名为 .mp4 + + 比如服务器IP为 190.15.240.11 ,app 为 Media ,stream 为 Camera_00001 ,假定端口都是默认 ,那么各种网络访问url如下: + rtsp: + rtsp://190.15.240.11:554/Media/Camera_00001 + + rtmp: + rtmp://190.15.240.11:1935/Media/Camera_00001 + + http-flv: + http://190.15.240.11:8088/Media/Camera_00001.flv + + http-mp4: + http://190.15.240.11:5088/Media/Camera_00001.mp4 + + websocket-flv: + ws://190.15.240.11:6088/Media/Camera_00001.flv + + http-hls: + http://190.15.240.11:9088/Media/Camera_00001.m3u8 + + 3)、使用ffmpeg往 ABLMediaServer 推送rtsp 码流 【假定 源摄像机rtsp RUL为 rtsp://admin:abldyjh2020@192.168.1.120:554 , ABLMediaServer 所在服务器地址为 190.15.240.11 】 + 【推送rtsp方式说明:视频支持 H264、H265 ,音频支持AAC、G711A、G711U 】 + + ffmpeg -rtsp_transport tcp -i rtsp://admin:abldyjh2020@192.168.1.120:554 -vcodec copy -acodec copy -f rtsp -rtsp_transport tcp rtsp://190.15.240.11:554/Media/Camera_00001 + + 媒体输出: + rtsp: 【rtsp输出格式说明:视频支持 H264、H265 ,音频支持AAC、G711A、G711U 】 + rtsp://190.15.240.11:554/Media/Camera_00001 + + rtmp: 【rtmp输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + rtmp://190.15.240.11:1935/Media/Camera_00001 + + http-flv: 【http-flv输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + http://190.15.240.11:8088/Media/Camera_00001.flv + + ws-flv: 【http-flv输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + ws://190.15.240.11:6088/Media/Camera_00001.flv + + http-hls: 【http-hls输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + http://190.15.240.11:9088/Media/Camera_00001.m3u8 + + 4)、使用ffmpeg往 ABLMediaServer 推送rtmp 码流 【假定 源摄像机rtsp RUL为 rtsp://admin:abldyjh2020@192.168.1.120:554 , ABLMediaServer 所在服务器地址为 190.15.240.11 】 + 【推送rtmp方式说明:视频支持 H264 ,音频支持AAC 】 + + ffmpeg -rtsp_transport tcp -i rtsp://admin:abldyjh2020@192.168.1.120:554 -acodec copy -vcodec copy -f flv rtmp://190.15.240.11:1935/Media/Camera_00001 + + rtsp: 【rtsp输出格式说明:视频支持 H264、H265 ,音频支持AAC、G711A、G711U 】 + rtsp://190.15.240.11:554/Media/Camera_00001 + + rtmp: 【rtmp输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + rtmp://190.15.240.11:1935/Media/Camera_00001 + + http-flv: 【http-flv输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + http://190.15.240.11:8088/Media/Camera_00001.flv + + ws-flv: 【http-flv输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + ws://190.15.240.11:6088/Media/Camera_00001.flv + + http-hls: 【http-hls输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + http://190.15.240.11:9088/Media/Camera_00001.m3u8 + + 5)、使用ffmpeg往 ABLMediaServer 推送rtsp的文件码流 【假定媒体文件为:F:\video\MP4有声音\H264_AAC_2021-02-10_1080P.mp4 , ABLMediaServer 所在服务器地址为 190.15.240.11 】 + 【推送rtsp方式说明:视频支持 H264、H265 ,音频支持AAC、G711A、G711U 】 + + ffmpeg -re -stream_loop -1 -i F:\video\MP4有声音\H264_AAC_2021-02-10_1080P.mp4 -vcodec copy -acodec copy -rtsp_transport tcp -f rtsp rtsp://190.15.240.11:554/Media/Camera_00001 + + 媒体输出: + rtsp: 【rtsp输出格式说明:视频支持 H264、H265 ,音频支持AAC、G711A、G711U 】 + rtsp://190.15.240.11:554/Media/Camera_00001 + + rtmp: 【rtmp输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + rtmp://190.15.240.11:1935/Media/Camera_00001 + + http-flv: 【http-flv输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + http://190.15.240.11:8088/Media/Camera_00001.flv + + ws-flv: 【http-flv输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + ws://190.15.240.11:6088/Media/Camera_00001.flv + + http-hls: 【http-hls输出格式说明:视频支持 H264、H265 ,音频支持AAC 】 + http://190.15.240.11:9088/Media/Camera_00001.m3u8 + + 【特别注明:可以往10000 的udp端口推送TS码流,推送成功后,可以调用 http函数getMediaList来获取接入的rtp码流 】 + ffmpeg.exe -re -stream_loop -1 -i F:\video\H264_20191021094432.mp4 -vcodec copy -f rtp_mpegts rtp://127.0.0.1:100000 + + + 6)、流媒体输出播放验证 + 如果视频是rtsp方式,可以采用VLC进行播放验证  +     如果rtmp、http-flv 协议,视频为h264 ,可以采用VLC播放验证、或者B站的 flv.js 播放器验证 + 如果rtmp、http-flv 协议,视频为h265 ,可以采用EasyPlayer.js 播放器验证,【注:VLC 、flv.js 不支持Rtmp的H265视频、也不支持http-flv的265视频 】 + + 7)、申请代理rtsp、rtmp、flv 拉流 、本地mp4文件 ,申请删除代理拉流 + 1) 申请代理rtsp、rtmp、flv 拉流、本地mp4文件 + + URL: /index/api/addStreamProxy + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + vhost 比如 _defaultVhost_ + app 应用名 比如 Media + stream 媒体流名 比如 Camera_00001 【/app/stream 组合起来不能重复】 + url 代理拉流url 比如 rtsp://admin:abldyjh2020@192.168.1.120:554 或者 + rtmp://190.15.240.36:1935/Media/Camera_00001 或者 + http://190.15.240.36:8088/Media/Camera_00001.flv 或者 + d:\\video\\xxxx.mp4 (windows平台) + /home/video/xxxx.mp4 (Linux平台) + isRtspRecordURL 代理拉流的url是否是rtsp录像回放的url 默认0 ,1 是【可选参数】,如果是rtsp录像回放的url,可以进行控制代理拉流,比如 暂停、继续、控制倍速播放,拖动播放等等 ,参考 + 函数 /index/api/controlStreamProxy + optionsHeartbeat options心跳 options 命令作为心跳包 【可选参数】 代理rtsp拉流成后,是否开启发送 0 不开启, 1 开启 ,默认不开启,如果从 ZLMediaKit 拉取rtsp流,建议设置为 1 + enable_mp4 是否录像 1 录像,0 不录像 【可选参数】 + enable_hls 是否hls切片 1 进行hls 切片 ,0 不切片 【可选参数】 + convertOutWidth 转码宽 转码输出宽 如果指定宽、高 【可选参数】[1920 x 1080, 1280 x 720 ,960 x 640 ,800 x 480 ,720 x 576 , 720 x 480 ,640 x 480 ,352 x 288 ] 就说明 H265 进行转码为 H264 + convertOutHeight 转码高 转码输出高 如果指定宽、高 【可选参数】[1920 x 1080, 1280 x 720 ,960 x 640 ,800 x 480 ,720 x 576 , 720 x 480 ,640 x 480 ,352 x 288 ] 就说明 H265 进行转码为 H264 + H264DecodeEncode_enable H264是否解码 H264分辨率高再编码降分辨率,【可选参数】有时候需要H264视频进行先解码再重新编码降低分辨率,可以设置 H264DecodeEncode_enable 为 1 ,降下来的分辨率为 convertOutWidth 、 convertOutHeight + disableVideo 是否过滤掉视频 0 不过滤 ,1 过滤视频 【可选参数】 默认 0 不过滤视频,国家电网协议中需要摄像头和摄像头直接需要对接,摄像头推上来的媒体流中过滤掉视频(disableVideo=1)再发给对方才能完成对讲 + disableAudio 是否过滤掉音频 0 不过滤 ,1 过滤音频 【可选参数】 默认 0 不过滤音频,有时候不需要音频、或者由于敏感原因禁止收听音频,可以过滤掉音频流接入流媒体服务器,只需要设置 disableAudio = 1即可过滤音频 + + http GET 方式 + 1 请求rtsp拉流样例 + http://190.15.240.11:7088/index/api/addStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=_defaultVhost_&app=Media&stream=Camera_00001&url=rtsp://admin:abldyjh2020@192.168.1.120:554&enable_mp4=0 + + http POST 方式 + 1 请求rtsp拉流样例 + http请求 url 样例 + http://190.15.240.11:7088/index/api/addStreamProxy + body 参数 , json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream":"Camera_00001","url":"rtsp://admin:abldyjh2020@192.168.1.120:554","enable_mp4":0} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 + "key": 93 # 成功时返回大于0的值,为代理拉流的Key ,删除代理拉流时需要用的 + } + + 2) 控制代理拉流,比如 暂停、继续、控制倍速播放,拖动播放等等 + URL: /index/api/controlStreamProxy + + 参数: + secret 服务器密码 ,比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 比如 93 ,调用 addStreamProxy 返回的 key 的值 + command 比如 pause、resume、seek、scale 对于对应意思:暂停、继续、拖动播放、倍速播放 + value (字符串) 比如 1、2、4、8、16(倍速播放) ,npt方式:360、1800、3600(拖动播放),clock方式:clock=20230625T113000Z-19700101T000001Z(拖动到:2023-06-25 11:30:00执行播放) + value 为可选参数,当 command 为 pause,resume 时,value 不用 ,当 command 为seek,sacale + 是,需要填写value的值 + 命令、值样例列表 + command value 注释 + pause 不需要 暂停回放 + resume 不需要 继续回放 + scale 2 2倍速回放 + seek 360 拖拽从开始点计算起到360秒处再回放 【ntp方式拖拽 ,代表 华为 VCN\3800 】 + seek clock=20230625T113000Z-19700101T000001Z 拖拽到20230625T113000Z处再回放 【clock方式拖拽 ,代表 海康NVR 】 + + http GET 方式 + http://190.15.240.11:7088/index/api/controlStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93&command=pause 暂停 + http://190.15.240.11:7088/index/api/controlStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93&command=resume 继续 + http://190.15.240.11:7088/index/api/controlStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93&command=scale&value=2 2倍速回放 + http://190.15.240.11:7088/index/api/controlStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93&command=seek&value=360 拖拽到360秒处继续回放 + http://190.15.240.11:7088/index/api/controlStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93&command=seek&value=clock=20230625T113000Z-19700101T000001Z + + http POST 方式 + http URL : + http://190.15.240.11:7088/index/api/controlStreamProxy + + body 参数 Json格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93,"command":"pause"} + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93,"command":"resume"} + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93,"command":"sacale","value":"2"} + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93,"command":"seek","value":"360"} + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93,"command":"seek","value":"clock=20230625T113000Z-19700101T000001Z"} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 【注:发送http请求 可以使用curl、postman、或者其他标准的http工具 】 + + + 3) 申请删除代理rtsp、rtmp、flv 拉流 + URL: /index/api/delStreamProxy + + 参数: + secret 服务器密码 ,比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 比如 93 ,调用 addStreamProxy 返回的 key 的值 + + http GET 方式 + http://190.15.240.11:7088/index/api/delStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93 + + http POST 方式 + http URL : + http://190.15.240.11:7088/index/api/delStreamProxy + + body 参数 Json格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 【注:发送http请求 可以使用curl、postman、或者其他标准的http工具 】 + + + + 8)、申请代理rtsp、rtmp、推流 、申请删除代理拉流 + 1) 申请代理rtsp、rtmp 推流(注意:不是国标GB28181推流) + + URL: /index/api/addPushProxy + + 参数: 参数说明 参考值 + secret 服务器密码 , 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + vhost 比如 _defaultVhost_ + app 应用名 比如 Media + stream 媒体流名 比如 Camera_00001 + url 代理推流url 比如 rtsp://190.15.240.36:554/Media/Camera_00001 或者 rtmp://190.15.240.36:1935/Media/Camera_00001 + disableVideo 是否过滤掉视频 0 不过滤 ,1 过滤视频 【可选参数】 默认 0 不过滤视频,国家电网协议中需要摄像头和摄像头直接需要对接,摄像头推上来的媒体流中过滤掉视频(disableVideo=1)再发给对方才能完成对讲 + disableAudio 是否过滤掉音频 0 不过滤 ,1 过滤音频 【可选参数】 默认 0 不过滤音频,有时候不需要音频、或者由于敏感原因禁止收听音频,可以过滤掉音频流接入流媒体服务器,只需要设置 disableAudio = 1即可过滤音频 + + http GET 方式 + http://190.15.240.11:7088/index/api/addPushProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=_defaultVhost_&app=Media&stream=Camera_00001&url=rtsp://190.15.240.36:554/Media/Camera_00001 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/addPushProxy + + http Body 参数 (json格式) + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream":"Camera_00001","url":"rtsp://190.15.240.36:554/Media/Camera_00001"} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 + "key": 93 # 成功时返回大于0的值,为代理推流的Key ,删除代理推流时需要用的 + } + + 2) 申请删除代理rtsp、rtmp 推流 + URL: /index/api/delPushProxy + + 参数: 参数说明 参数参考值 + secret 服务器密码 , 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 主键ID 比如 93 ,调用 /index/api/addPushProxy 返回的 key 的值 + + http GET 方式 + http://190.15.240.11:7088/index/api/delPushProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/delPushProxy + + http Body json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 9)、创建GB28181\Jtt1078接收端口、删除GB28181\Jtt1078接收端口、国标暂停、继续 + + 1 创建GB28181\Jtt1078接收端口 + + URL: /index/api/openRtpServer + 功能: + 创建GB28181\Jtt1078接收端口,如果该端口接收超时,会自动回收,不用调用 /index/api/closeRtpServer + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + vhost 比如 _defaultVhost_ + app 应用名 比如 gb28181 、rtp 等等 (接入) + stream_id 媒体流名 比如 44030012343220234234 (最好是国标编号)( 接入 ) + payload PS负载值 国标SDP里面PS负载值 ,比如 96,98 ,108 ,一定要从国标SDP里面获取 + port 端口号 0 ,由服务器自动分配,别的值 比如 26324 为指定端口 + enable_tcp 是否为tcp 0 为 udp , 1 为tcp被动方式 ,2 为tcp主动连接方式 + dst_url 目标IP 目标IP地址 【可选参数 ,当 enable_tcp 为 2 时必须填写 】 + dst_port 目标端口 目标端口 【可选参数 ,当 enable_tcp 为 2 时必须填写】 + + enable_mp4 是否录像 1 录像,0 不录像 【可选参数】 + enable_hls 是否hls切片 1 进行hls 切片 ,0 不切片 【可选参数】 + convertOutWidth 转码宽 转码输出宽 如果指定宽、高 【可选参数】[1920 x 1080, 1280 x 720 ,960 x 640 ,800 x 480 ,720 x 576 , 720 x 480 ,640 x 480 ,352 x 288 ] 就说明 H265 进行转码为 H264 + convertOutHeight 转码高 转码输出高 如果指定宽、高 【可选参数】[1920 x 1080, 1280 x 720 ,960 x 640 ,800 x 480 ,720 x 576 , 720 x 480 ,640 x 480 ,352 x 288 ] 就说明 H265 进行转码为 H264 + H264DecodeEncode_enable H264是否解码 H264分辨率高再编码降分辨率,【可选参数】有时候需要H264视频进行先解码再重新编码降低分辨率,可以设置 H264DecodeEncode_enable 为 1 ,降下来的分辨率为 convertOutWidth 、 convertOutHeight + RtpPayloadDataType rtp打包数据格式 rtp打包数据格式 【可选参数 ,默认 1 】 [1 PS 国标gb28181 ]、[ 2 ES 视频支持 H246\H265,音频只支持G711A、G711U ]、[3 XHB (一家公司的打包格式) 只支持视频,音频不能加入打包 ] [ 4 、Jt1078(2016版本)码流接入 ] + disableVideo 是否过滤掉视频 0 不过滤 ,1 过滤视频 【可选参数】 默认 0 不过滤视频,国家电网协议中需要摄像头和摄像头直接需要对接,摄像头推上来的媒体流中过滤掉视频(disableVideo=1)再发给对方才能完成对讲 + disableAudio 是否过滤掉音频 0 不过滤 ,1 过滤音频 【可选参数】 默认 0 不过滤音频,有时候不需要音频、或者由于敏感原因禁止收听音频,可以过滤掉音频流接入流媒体服务器,只需要设置 disableAudio = 1即可过滤音频 + jtt1078_version 指定1078版本号 2013、2016、2019 【可选参数】 2013 指定为 2013版本 、2016 指定为 2016版本、 2019 指定为 2019 版本 + + send_app 应用名 比如 gb28181 、rtp 等等 【可选参数】 用于把本服务器的码流(send_app/send_stream_id)回复给发送端 + send_stream_id 媒体流名 比如 44030012343220234234 【可选参数】 用于把本服务器的码流(send_app/send_stream_id)回复给发送端 + send_disableVideo 是否过滤掉视频 0 不过滤 ,1 过滤视频 【可选参数】 默认 0 不过滤视频,国家电网协议中需要摄像头和摄像头直接需要对接,摄像头推上来的媒体流中过滤掉视频(disableVideo=1)再发给对方才能完成对讲 + send_disableAudio 是否过滤掉音频 0 不过滤 ,1 过滤音频 【可选参数】 默认 0 不过滤音频,有时候不需要音频、或者由于敏感原因禁止收听音频,可以过滤掉音频流接入流媒体服务器,只需要设置 disableAudio = 1即可过滤音频 + detectSendAppStream 是否检测发送流ID 0 不检测 ,1 检测 【可选参数】 默认 1 在需要回传码流时,事先检测 send_app、send_stream_id 是否存在。0 不检测,先打开接收成功后,稍后再把send_app、send_stream_id接入流媒体,openRtpServer函数自动回复给下级流媒体。 + + http GET 方式 + http://190.15.240.11:7088/index/api/openRtpServer?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=_defaultVhost_&app=gb28181&stream_id=44030012343220234234&payload=96&port=0&enable_tcp=0&enable_mp4=0 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/openRtpServer + + http 参数值 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream_id":"Camera_00001","payload":96,"port":0,"enable_tcp":0,"enable_mp4":0} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "port": 8356, # 端口号 + "memo": "success", # success 为成功 + "key": 93 # 成功时返回大于0的值,GB28181接收实例key ,关闭时需要 + } + + 2 删除 GB28181\Jtt1078接收端口 + URL: /index/api/closeRtpServer + 功能: + 删除GB28181\Jtt1078接收端口 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 主键值ID 比如 93 , 调用 /index/api/openRtpServer 返回的 key 的值 + + http GET 方式 + http://190.15.240.11:7088/index/api/closeRtpServer?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/closeRtpServer + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 3 暂停 GB28181\Jtt1078接收端口,只是不检测接收端口是否有码流进入。 + URL: /index/api/pauseRtpServer + 功能: + 暂停GB28181\Jtt1078接收 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 主键值ID 比如 93 , 调用 /index/api/openRtpServer 返回的 key 的值 + + http GET 方式 + http://44.35.33.249:7088/index/api/pauseRtpServer?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=588 + + http POST 方式 + http URL + http://44.35.33.249:7088/index/api/pauseRtpServer + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":588} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 4 继续 GB28181\Jtt1078接收端口,开启检测端口是否有码流到达,如果时长到达最大超时没有码流进入会立即删除接收端口 + URL: /index/api/resumeRtpServer + 功能: + 继续GB28181\Jtt1078接收 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 主键值ID 比如 93 , 调用 /index/api/openRtpServer 返回的 key 的值 + + http GET 方式 + http://44.35.33.249:7088/index/api/resumeRtpServer?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=588 + + http POST 方式 + http URL + http://44.35.33.249:7088/index/api/resumeRtpServer + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":588} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 10)、创建GB28181\Jtt1078 发送端口、删除GB28181\Jtt1078发送端口 + + 1 创建GB28181\Jtt1078发送端口 + + URL: /index/api/startSendRtp + 功能: + 创建GB28181\Jtt1078发送端口,如果该发送端端口没有数据发送,会自动回收,不用调用 /index/api/stopSendRtp + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + vhost 比如 _defaultVhost_ + app 应用名 比如 gb28181 、rtp 等等 (发送出去) + stream 媒体流名 比如 44030012343220234234 (发送出去) + payload PS负载值 国标SDP里面PS负载值 ,比如 96,98 ,108 ,rtp打包时需要 + ssrc 同步源 ssrc + src_port 发送端绑定的端口号 指定服务器在发送国标流时绑定的端口号,如果为 0 ,由服务器自动分配,别的值 比如 26324 为指定端口 + dst_url 目标IP 目标IP地址 + dst_port 目标端口 目标端口 + is_udp 是否设置udp 0 TCP主动方式,1 udp 方式 ,2 为 TCP 被动方式 + RtpPayloadDataType rtp打包数据格式 【可选参数 ,默认 1 】 [ 1 PS 国标gb28181 ]、[ 2 ES 视频支持 H246\H265,音频只支持G711A、G711U ]、[3 XHB (一家公司的打包格式) 只支持视频,音频不能加入打包 ] [ 4 、Jt1078(2016版本)码流发送 ] + disableVideo 是否过滤掉视频 0 不过滤 ,1 过滤视频 【可选参数】 默认 0 不过滤视频,国家电网协议中需要摄像头和摄像头直接需要对接,摄像头推上来的媒体流中过滤掉视频(disableVideo=1)再发给对方才能完成对讲 + disableAudio 是否过滤掉音频 0 不过滤 ,1 过滤音频 【可选参数】 默认 0 不过滤音频,有时候不需要音频、或者由于敏感原因禁止收听音频,可以过滤掉音频流接入流媒体服务器,只需要设置 disableAudio = 1即可过滤音频 + jtt1078_version 指定1078版本号 2013、2016、2019 【可选参数】 2013 指定为 2013版本 、2016 指定为 2016版本、 2019 指定为 2019 版本 + + recv_app 应用名 比如 gb28181 、rtp 等等 【可选参数】 接入进来 通过在发送的连接中接收进来的码流 + recv_stream 媒体流名 比如 44030012343220234234 【可选参数】 接入进来 通过在发送的连接中接收进来的码流 + recv_disableVideo 是否过滤掉视频 0 不过滤 ,1 过滤视频 【可选参数】 默认 0 不过滤视频,国家电网协议中需要摄像头和摄像头直接需要对接,摄像头推上来的媒体流中过滤掉视频(disableVideo=1)再发给对方才能完成对讲 + recv_disableAudio 是否过滤掉音频 0 不过滤 ,1 过滤音频 【可选参数】 默认 0 不过滤音频,有时候不需要音频、或者由于敏感原因禁止收听音频,可以过滤掉音频流接入流媒体服务器,只需要设置 disableAudio = 1即可过滤音频 + + http GET 方式 + http://190.15.240.11:7088/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=_defaultVhost_&app=gb28181&stream=44030012343220234234&payload=96&ssrc=5224&src_port=26324&dst_url=190.15.240.11&dst_port=9824&is_udp=1 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/startSendRtp + + http 参数值 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream":"Camera_00001","payload":96,"ssrc":2432,"src_port":26324,"dst_url":"190.15.240.11","dst_port":9824,"is_udp":1} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "port": 8356, # 端口号 + "memo": "success", # success 为成功 + "key": 93 # 成功时返回大于0的值,GB28181发送码流实例key ,关闭时需要 + } + + 2 删除 GB28181\Jtt1078发送端口 + URL: /index/api/stopSendRtp + 功能: + 删除GB28181\Jtt1078发送端口 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 主键值ID 比如 93 , 调用 /index/api/startSendRtp 返回的 key 的值 + + http GET 方式 + http://190.15.240.11:7088/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/stopSendRtp + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 11)、获取流媒体服务器所有可用的媒体源 + URL: /index/api/getMediaList + + 功能: + 获取流媒体服务器所有媒体源 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + app 应用名 比如 rtp、gb28181、Media 等等 ,自己起的名字 【可选参数】 + stream 媒体流名 比如 Camera_00001、44303403343034243200234 等等 【可选参数】 + + 参数填写样例说明: + 样例1(app、stream 都不填写) + secret 035c73f7-bb6b-4889-a715-d9eb2d1925cc + + 返回所有在线的媒体源 + + 样例2 (只填写 app ) + secret 035c73f7-bb6b-4889-a715-d9eb2d1925cc + app rtp + 返回 app 等于 rtp 的所有媒体源 + + 样例3 (填写 app = rtp , stream = 44303403343034243200234) + secret 035c73f7-bb6b-4889-a715-d9eb2d1925cc + app rtp + stream 44303403343034243200234 + 返回 app 等于 rtp、并且 stream 等于 44303403343034243200234 的所有媒体源 + + 样例4 (填写 stream = 44303403343034243200234) + secret 035c73f7-bb6b-4889-a715-d9eb2d1925cc + stream 44303403343034243200234 + 返回 stream 等于 44303403343034243200234 的所有媒体源 + + http GET 方式 + http://127.0.0.1:7088/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/getMediaList + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc"} + + 返回Body: + { + "code": 0, + "memo": "success", + "mediaList": [ + { + "key": 34, + "app": "Media", + "stream": "Camera_00001", + "sim": "123456789123", 【1078码流接入这个字段的值不会为空,代表设备的sim卡编码 】 + "status": false , 【 false 尚未录像,true 正在录像 】 + "enable_hls": false, 【 false 尚未启用,true 启用hls回放 】 + "transcodingStatus": false, 【 false 尚未转码,true 正在转码 】 + "sourceURL": "rtsp://10.0.0.239:554/Media/Camera_00001", + "sourceType": 23, + "readerCount": 0, + "videoCodec": "H264", + "width": 1920, + "height": 1080, + "networkType": 24, + "audioCodec": "AAC", + "audioChannels": 1, + "audioSampleRate": 16000, + "url": { + "rtsp": "rtsp://10.0.0.239:554/Media/Camera_00001", + "rtmp": "rtmp://10.0.0.239:1935/Media/Camera_00001", + "http-flv": "http://10.0.0.239:8088/Media/Camera_00001.flv", + "ws-flv": "ws://10.0.0.239:6088/Media/Camera_00001.flv", + "http-mp4": "http://10.0.0.239:5088/Media/Camera_00001.mp4", + "http-hls": "http://10.0.0.239:9088/Media/Camera_00001.m3u8", + "webrtc":"http://10.0.0.239:8892/webrtc-streamer.html?video=/Media/Camera_00001" + } + } + ] + } + + 【注释:可以根据 "networkType": 24, 这个字段值区分 媒体接入的类型 ,具体详见网络类型的对照表 】 + + 12) 删除 某一个媒体源 + URL: /index/api/delMediaStream + 功能: + 某一个媒体源,这媒体源,可以是rtp推流、rtmp推流,各种方式代理拉流接入的,国标接入 等等。 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 主键值ID 比如 93 , 调用 /index/api/getMediaList 返回的 key 的值 + + http GET 方式 + http://190.15.240.11:7088/index/api/delMediaStream?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/delMediaStream + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 13)、获取流媒体服务器所有往外部输出码流列表,包括外部请求的rtsp、rtmp、http-flv、ws-flv、hls 列表 + 也包括服务器代理rtsp推流、rtmp推流列表 + 也包括服务器以国标方式往上级推rtp流列表 + 【必要时可以调用 /index/api/delOutList 接口删除某一个列表对象,比如删除某一路国标推流、删除某一路rtsp推流、 删除某一路rtmp推流】 + URL: /index/api/getOutList + + 功能: + 获取流媒体服务器所有输出流列表 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http GET 方式 + http://44.35.33.239:7088/index/api/getOutList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http POST 方式 + http URL + http://44.35.33.239:7088/index/api/getOutList + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc"} + + 返回Body: + { + "code": 0, + "memo": "success", + "outList": [ + { + "key": 103, 【请求客户端的标识ID ,可以调用 /index/api/delOutList 删除 该请求】 + "app": "Media", + "stream": "Camera_00001", + "sourceURL": "rtsp://44.35.33.239:554/Media/Camera_00001", 【表示外界以rtsp方式向服务器请求码流】 + "videoCodec": "H264", + "audioCodec": "AAC", + "audioChannels": 1, + "audioSampleRate": 16000, + "networkType": 24, 【网络类型为24 ,标识为rtsp 方式】 + "dst_url": "44.35.33.39", 【 请求码流客户端IP 】 + "dst_port": 43801 【 请求码流客户端端口 】 + }, + { + "key": 85, 【请求客户端的标识ID ,可以调用 /index/api/delOutList 删除 该请求】 + "app": "Media", + "stream": "Camera_00001", + "sourceURL": "http://localhost:8088/Media/Camera_00001.flv",【表示外界以 http-flv 方式向服务器请求码流】 + "videoCodec": "H264", + "audioCodec": "AAC", + "audioChannels": 1, + "audioSampleRate": 16000, + "networkType": 25, 【网络类型为25 ,标识为 http-flv 方式】 + "dst_url": "44.35.33.39", 【 请求码流客户端IP 】 + "dst_port": 43806 【 请求码流客户端端口 】 + } + ] + } + + 【注释:可以根据 "networkType": 24, 这个字段值区分 媒体输出的类型 ,具体详见网络类型的对照表 】 + + 14) 删除 某一个服务器所有往外部输出码流列表 + URL: /index/api/delOutList + 功能: + 删除某一个流媒体服务器所有往外部输出码流列表,包括外部请求的rtsp、rtmp、http-flv、ws-flv、hls 点播 。国标推流、rtsp推流、rtmp 推流 等等 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + key 主键值ID 比如 93 , 调用 /index/api/getOutList 返回的 key 的值 + + http GET 方式 + http://190.15.240.11:7088/index/api/delOutList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=93 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/delOutList + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","key":93} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 ,如果失败是其他值 + } + + 15)根据条件组合,删除任意一个或一组或者全部媒体输入列表 + URL: /index/api/close_streams + + 功能 + 删除任意一个或一组或者全部媒体输入列表 + + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + vhost 比如 _defaultVhost_ 【可选参数】 + app 应用名 比如 gb28181 、rtp 等等 【可选参数】 + stream 媒体流名 比如 Camera_00001、dsafdsafassdafadsfas、等等 【可选参数】 + force 是否强制关闭 1 强制关闭,不管是否有人在观看、0 非强制关闭,当有人观看时不关闭。 【必填参数】 + + http GET 方式 + 示例1: http://190.168.24.112:7088/index/api/close_streams?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=live&force=1 + 【表示强行关闭 app 等于 live 的码流接入】 + 示例2: http://190.168.24.112:7088/index/api/close_streams?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=live&stream=Camera_00001&force=1 + 【表示强行关闭 app 等于 live, 并且 stream 等于 Camera_00001 的码流接入 】 + 示例3: http://190.168.24.112:7088/index/api/close_streams?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&force=1 + 【表示强行关闭 所有码流(app全部、stream全部) 接入 】 + + http pos 方式 + 示例1: http URL: + http://190.168.24.112:7088/index/api/close_streams + body: + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","app":"live","force":1} + + 【表示强行关闭 app 等于 live 的码流接入】 + + 示例2: http URL: + http://190.168.24.112:7088/index/api/close_streams + body: + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","app":"live","stream":"Camera_00001","force":1} + + 【表示强行关闭 app 等于 live, 并且 stream 等于 Camera_00001 的码流接入 】 + + 示例3: http URL: + http://190.168.24.112:7088/index/api/close_streams + body: + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","force":1} + + 【 表示强行关闭 所有码流(app全部、stream全部) 接入 】 + + 16)、 开始录像、停止录像 + 1) 申请开始录像 + + URL: /index/api/startRecord + + 参数: 参数说明 参考值 + secret 服务器密码 ,比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + vhost 比如 _defaultVhost_ + app 应用名 比如 Media + stream 媒体流名 比如 Camera_00001 + + http GET 方式 + http://190.15.240.11:7088/index/api/startRecord?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=_defaultVhost_&app=Media&stream=Camera_00001 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/startRecord + + http Body 参数 (json格式) + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream":"Camera_00001"} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "MediaSource: /Media/Camera_00001 start Record", # "code": 0 为成功 + } + + 2) 申请停止录像 + URL: /index/api/stopRecord + + 参数: 参数说明 参考值 + secret 服务器密码 ,比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + vhost 比如 _defaultVhost_ + app 应用名 比如 Media + stream 媒体流名 比如 Camera_00001 + + http GET 方式 + http://190.15.240.11:7088/index/api/stopRecord?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=_defaultVhost_&app=Media&stream=Camera_00001 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/stopRecord + + http Body 参数 (json格式) + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream":"Camera_00001"} + + 返回Body: + { + "code": 0, # 0为操作成功,其他值为操作失败 + "memo": "success", # success 为成功 + } + + 17 获取系统配置参数 + URL: /index/api/getServerConfig + 功能: + 获取服务器的配置参数 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http GET 方式 + http://190.15.240.11:7088/index/api/getServerConfig?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/getServerConfig + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc"} + + 返回Body: + { + "code": 0, + "params": [ + + { + "secret": "035c73f7-bb6b-4889-a715-d9eb2d1925cc", + "memo": "server password", + }, + { + "ServerIP": "44.35.33.239", + "memo": "ABLMediaServer ip address" + }, + { + "rtc.listening-ip": "192.168.2.5", + "memo": "Total number of video playback threads ." + }, + { + "mediaServerID": "ABLMediaServer_00001", + "memo": "media Server ID " + }, + { + "hook_enable": 0, + "memo": "hook_enable = 1 open notice , hook_enable = 0 close notice " + }, + { + "enable_audio": 1, + "memo": "enable_audio = 1 open Audio , enable_audio = 0 Close Audio " + }, + { + "httpServerPort": 7088, + "memo": "http api port " + }, + { + "rtspPort": 554, + "memo": "rtsp port " + }, + { + "rtmpPort": 1935, + "memo": "rtmp port " + }, + { + "httpFlvPort": 8088, + "memo": "http-flv port " + }, + { + "hls_enable": 0, + "memo": "hls whether enable " + }, + { + "hlsPort": 9088, + "memo": "hls port" + }, + { + "wsPort": 6088, + "memo": "websocket flv port" + }, + { + "mp4Port": 5088, + "memo": "http mp4 port" + }, + { + "ps_tsRecvPort": 10000, + "memo": "recv ts , ps Stream port " + }, + { + "hlsCutType": 2, + "memo": "hlsCutType = 1 hls cut to Harddisk,hlsCutType = 2 hls cut Media to memory" + }, + { + "h265CutType": 1, + "memo": " 1 h265 cut TS , 2 cut fmp4 " + }, + { + "RecvThreadCount": 128, + "memo": " RecvThreadCount " + }, + { + "SendThreadCount": 128, + "memo": "SendThreadCount" + }, + { + "GB28181RtpTCPHeadType": 2, + "memo": "rtp Length Type" + }, + { + "ReConnectingCount": 40320, + "memo": "Try reconnections times ." + }, + { + "maxTimeNoOneWatch": 9999999, + "memo": "maxTimeNoOneWatch ." + }, + { + "pushEnable_mp4": 0, + "memo": "pushEnable_mp4 ." + }, + { + "fileSecond": 180, + "memo": "fileSecond ." + }, + { + "fileKeepMaxTime": 1, + "memo": "fileKeepMaxTime ." + }, + { + "httpDownloadSpeed": 6, + "memo": "httpDownloadSpeed ." + }, + { + "RecordReplayThread": 32, + "memo": "Total number of video playback threads ." + } + ] + } + + 18)、查询录像列表 + URL: /index/api/queryRecordList + + 功能: + 查询某一路输入源的录像列表(可以查询代理拉流输入、推流输入、国标输入等等 ) + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + vhost 比如 _defaultVhost_ 【可选参数】 + app 应用名 比如 rtp、gb28181、Media 等等 ,自己起的名字 【必填参数】 + stream 媒体流名 比如 Camera_00001、44303403343034243200234 等等 【必填参数】 + starttime 开始时间 比如 20220116154810 年月日时分秒 【必填参数】 + endtime 结束时间 比如 20220116155115 年月日时分秒 【必填参数】 + + 【注意:1、开始时间必须小于 当前时间减去切片时长的时间 2、从 开始时间 至 结束时间 不能超过3天】 + + http GET 方式 + http://10.0.0.239:7088/index/api/queryRecordList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=Media&stream=Camera_00001&starttime=20220116154810&endtime=20220116155115 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/queryRecordList + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream":"Camera_00001","starttime":"20220116154810","endtime":"20220116155115"} + + 返回Body: + { + "code": 0, + "app": "Media", + "stream": "Camera_00001", + "starttime": "20220116154810", + "endtime": "20220116155115", + "recordFileList": [ + { + "file": "20220116154810.mp4", + "duration": 300, 当前录像时间长度,单位 秒 + "url": { + "rtsp": "rtsp://10.0.0.239:554/Media/Camera_00001__ReplayFMP4RecordFile__20220116154810", + "rtmp": "rtmp://10.0.0.239:1935/Media/Camera_00001__ReplayFMP4RecordFile__20220116154810", + "http-flv": "http://10.0.0.239:8088/Media/Camera_00001__ReplayFMP4RecordFile__20220116154810.flv", + "ws-flv": "ws://10.0.0.239:6088/Media/Camera_00001__ReplayFMP4RecordFile__20220116154810.flv", + "http-mp4": "http://10.0.0.239:5088/Media/Camera_00001__ReplayFMP4RecordFile__20220116154810.mp4?download_speed=1", + "download": "http://10.0.0.239:5088/Media/Camera_00001__ReplayFMP4RecordFile__20220116154810.mp4?download_speed=6" + } + }, + { + "file": "20220116155110.mp4", + "duration": 256, 当前录像时间长度,单位 秒 + "url": { + "rtsp": "rtsp://10.0.0.239:554/Media/Camera_00001__ReplayFMP4RecordFile__20220116155110", + "rtmp": "rtmp://10.0.0.239:1935/Media/Camera_00001__ReplayFMP4RecordFile__20220116155110", + "http-flv": "http://10.0.0.239:8088/Media/Camera_00001__ReplayFMP4RecordFile__20220116155110.flv", + "ws-flv": "ws://10.0.0.239:6088/Media/Camera_00001__ReplayFMP4RecordFile__20220116155110.flv", + "http-mp4": "http://10.0.0.239:5088/Media/Camera_00001__ReplayFMP4RecordFile__20220116155110.mp4?download_speed=1", + "download": "http://10.0.0.239:5088/Media/Camera_00001__ReplayFMP4RecordFile__20220116155110.mp4?download_speed=6" + } + } + ] + } + 19)、消息通知使用 + 功能说明:消息通知是流媒体服务器的一些消息比如无人观看、fmp4录像切片完成、播放时流地址不存在等等信息能及时的通知到另外一个http服务器上,需要此功能 + 消息通知功能用在什么地方,比如说无人观看消息通知,当收到无人观看消息时,国标服务器可以关闭国标发流,断开代理拉流,断开推流等等操作 + 要使用此功能把配置文件的参数hook_enable 值设置为 1,同时通知的http服务器地址、端口号一定要设置对,下面列举出配置文件中的相关参数 + + hook_enable=1 #事件通知部分,当 hook_enable=1 时,开启事件通知,hook_enable=0时关闭事件通知 + on_stream_arrive=http://10.0.0.238:7088/index/hook/on_stream_arrive #当某一路的码流达到时会通知一次 + on_stream_none_reader=http://10.0.0.238:8080/index/hook/on_stream_none_reader #当某一路流无人观看时,会触发该通知事件,接收端收到后可以进行断流操作 + on_stream_disconnect=http://10.0.0.238:7088/index/hook/on_stream_disconnect #当某一路码流断开时会通知一次 + on_stream_not_found=http://10.0.0.238:8080/index/hook/on_stream_not_found #播放时,找不到播放的码流,通过配合on_stream_none_reader事件可以完成按需拉流 + on_record_mp4=http://10.0.0.238:8080/index/hook/on_record_mp4 #录制完毕一段mp4文件通知 + + 【注:http url的 IP,端口 是代表消息接收服务器的IP,端口,一定要填写正确,url 地址要合法,不要有空格 】 + 1、当某一路码流到达时会发送通知: + POST /index/hook/on_stream_arrive HTTP/1.1 # 根据 /index/hook/on_stream_arrive 这个可以判断是某一路码流到达 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 105 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-5.2.9(2022-03-28) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + { + "app":"Media", # app + "stream":"Camera_00001", # stream + "mediaServerId":"ABLMediaServer_00001", # 流媒体服务器编号 ,在配置文件可以配置,如果集群流媒体服务器时,可以给每台流媒体服务器起个编号 + "networkType":23, # 媒体流来源网络编号,可参考附表 + "key":130, # 媒体流来源编号,可以根据这个key进行关闭流媒体 可以调用delMediaStream或close_streams 函数进行关闭 + "status":true, + "enable_hls":false, + "transcodingStatus":false, + "sourceURL":"rtsp://admin:abldyjh2020@44.35.33.248:554", + "readerCount":0, + "noneReaderDuration":0, + "videoCodec":"H265", + "videoFrameSpeed":25, + "width":1920, + "height":1080, + "videoBitrate":0, + "audioCodec":"AAC", + "audioChannels":1, + "audioSampleRate":8000, + "audioBitrate":0, + "url": + { + "rtsp":"rtsp://44.35.33.249:554/Media/Camera_00001", + "rtmp":"rtmp://44.35.33.249:1935/Media/Camera_00001", + "http-flv":"http://44.35.33.249:8088/Media/Camera_00001.flv", + "ws-flv":"ws://44.35.33.249:6088/Media/Camera_00001.flv", + "http-mp4":"http://44.35.33.249:5088/Media/Camera_00001.mp4", + "http-hls":"http://44.35.33.249:9088/Media/Camera_00001.m3u8" + } + } + + 2、无人观看消息通知样例: + POST /index/hook/on_stream_none_reader HTTP/1.1 # 根据 /index/hook/on_stream_none_reader 这个可以判断是无人观看消息通知 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 105 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-5.2.9(2022-03-28) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + { + "app":"Media", # app + "stream":"Camera_00001", # stream + "mediaServerId":"ABLMediaServer_00001", # 流媒体服务器编号 ,在配置文件可以配置,如果集群流媒体服务器时,可以给每台流媒体服务器起个编号 + "networkType":23, # 媒体流来源网络编号,可参考附表 + "key":130 # 媒体流来源编号,可以根据这个key进行关闭流媒体 可以调用delMediaStream或close_streams 函数进行关闭 + } + + 3、 fmp4录像切片录像完成一个文件时会发送一个消息通知 + POST /index/hook/on_record_mp4 HTTP/1.1 # 根据 /index/hook/on_record_mp4 这个可以判断是mp4录像切片完毕一个通知 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 127 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-5.2.9(2022-03-28) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + { + "app":"Media", # app + "stream":"Camera_00001", # stream + "mediaServerId":"ABLMediaServer_00001", # 流媒体服务器编号 ,在配置文件可以配置,如果集群流媒体服务器时,可以给每台流媒体服务器起个编号 + "networkType":70, # 媒体流来源网络编号,可参考附表 + "fileName":"20220312212546.mp4" # 录像切片完成的文件名字 + } + + 4、当某一路码流断开时会发送通知: + POST /index/hook/on_stream_disconnect HTTP/1.1 # 根据 /index/hook/on_stream_disconnect 这个可以判断是某一路码流断开 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 105 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-5.2.9(2022-03-28) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + { + "app":"Media", # app + "stream":"Camera_00001", # stream + "mediaServerId":"ABLMediaServer_00001", # 流媒体服务器编号 ,在配置文件可以配置,如果集群流媒体服务器时,可以给每台流媒体服务器起个编号 + "networkType":23, # 媒体流来源网络编号,可参考附表 + "key":130 # 媒体流来源编号,可以根据这个key进行关闭流媒体 可以调用delMediaStream或close_streams 函数进行关闭 + } + + 5、 当播放一个url,如果不存在时,会发出一个消息通知 + POST /index/hook/on_stream_not_found HTTP/1.1 # 根据 /index/hook/on_stream_not_found ,Http接收服务器得知流不不存在 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 127 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-5.2.9(2022-03-28) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + { + "app":"Media", # app 不存在的app + "stream":"Camera_00001", # stream 不存在的stream + "mediaServerId":"ABLMediaServer_00001" # 流媒体服务器编号 ,在配置文件可以配置,如果集群流媒体服务器时,可以给每台流媒体服务器起个编号 + } + 6、ABLMediaServer启动时会发送上线通知 + POST /index/hook/on_server_started HTTP/1.1 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 105 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-6.3.5(2023-04-30) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + {"localipAddress":"44.35.33.249","mediaServerId":"ABLMediaServer_00001","datetime":"2023-04-18 10:04:37"} + + 7、某一个码流接入流媒体服务器时会产生 发布 事件通知 + POST /index/hook/on_publish HTTP/1.1 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 149 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-6.3.5(2023-04-30) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + {"app":"Media","stream":"Camera_00001","mediaServerId":"ABLMediaServer_00001","networkType":50,"key":470,"ip":"44.35.33.248" ,"port":554,"params":""} + + 8、当播放流媒体服务器里面某一个码流时,会触发 播放事件 ,可以通知 parmas 参数值进行播放鉴权 + POST /index/hook/on_play HTTP/1.1 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 135 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-6.3.5(2023-04-30) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + {"app":"Media","stream":"Camera_00001","mediaServerId":"ABLMediaServer_00001","networkType":30,"key":472,"ip":"" ,"port":0,"params":"user=admin&password=safsa234234&token=@#$@#$@#ASDFasfdsa@#$23"} + + 9、如果某一个码流进行MP4录像(enable_mp4=1),会触发录像进度通知事件 + POST /index/hook/on_record_progress HTTP/1.1 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 204 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-6.3.5(2023-04-30) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + {"app":"Media","stream":"Camera_00001","mediaServerId":"ABLMediaServer_00001","networkType":472,"key":470,"fileName":"20230418100440.mp4","currentFileDuration":49,"TotalVideoDuration":49} + + 10、如果某一个码流开启hls(enable_hls=1)并且设置为切片到硬盘(hlsCutType=1 在配置文件中) ,每当切片完成一个ts文件会触发该事件 + POST /index/hook/on_record_ts HTTP/1.1 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 246 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-6.3.5(2023-04-30) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + {"app":"Media","stream":"Camera_00001","mediaServerId":"ABLMediaServer_00001","networkType":30,"key":470,"createDateTime":"2023-04-18 10:05:47","currentFileDuration":3,"fileName":"D:\WorkDir\ABLMediaServer\x64\Debug\www\Media\Camera_00001\23.ts"} + + 11、流媒体服务器每隔60秒会触发心跳事件通知 + POST /index/hook/on_server_keepalive HTTP/1.1 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 105 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-6.3.5(2023-04-30) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + {"localipAddress":"44.35.33.249","mediaServerId":"ABLMediaServer_00001","datetime":"2023-04-18 10:25:40"} + + 12、当代理拉流、国标接入等等 码流不到达时会发出 码流不到达的事件通知 + POST /index/hook/on_stream_not_arrive HTTP/1.1 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 155 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-6.3.5(2023-04-30) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + {"mediaServerId":"ABLMediaServer_00001","app":"gb28181","stream":"440300123432202342349","networkType":60,"key":470} + + 13、如果某一个码流进行MP4录像(enable_mp4=1),当某个MP4文件被删除会触发该事件通知 + POST /index/hook/on_delete_record_mp4 HTTP/1.1 + Accept: */* + Accept-Language: zh-CN,zh;q=0.8 + Connection: keep-alive + Content-Length: 204 + Content-Type: application/json + Host: 127.0.0.1 + Tools: ABLMediaServer-6.3.5(2023-04-30) + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 + + {"app":"Media","stream":"Camera_00001","mediaServerId":"ABLMediaServer_00001","fileName":"20230418100440.mp4"} + + + + 20) 图片抓拍 + URL: /index/api/getSnap + + 功能: + 查询某一接入的媒体源进行抓拍 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + vhost 比如 _defaultVhost_ 【可选参数】 + app 应用名 比如 rtp、gb28181、Media 等等 ,自己起的名字 【必填参数】 + stream 媒体流名 比如 Camera_00001、44303403343034243200234 等等 【必填参数】 + timeout_sec 超时时长 10 即本次抓拍最大超时时长 单位 秒 【必填参数】 + + http GET 方式 + http://127.0.0.1:7088/index/api/getSnap?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=_defaultVhost_&app=Media&stream=Camera_00001&timeout_sec=10 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/getSnap + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream":"Camera_00001","timeout_sec":10} + + 抓拍成功返回: + { + "code": 0, + "memo": "success , Catpuring takes time 219 millisecond .", + "url": "http://10.0.0.239:7088/Media/Camera_00001/2022031910034501.jpg" + } + + 21)图片列表查询 + URL: /index/api/queryPictureList + + 功能: + 查询某一路输入源的抓拍图片列表 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + vhost 比如 _defaultVhost_ 【可选参数】 + app 应用名 比如 rtp、gb28181、Media 等等 ,自己起的名字 【必填参数】 + stream 媒体流名 比如 Camera_00001、44303403343034243200234 等等 【必填参数】 + starttime 开始时间 比如 20220317081201 年月日时分秒 【必填参数】 + endtime 结束时间 比如 20220319231201 年月日时分秒 【必填参数】 + + 【注意:1、开始时间必须小于 当前时间减去切片时长的时间 2、从 开始时间 至 结束时间 不能超过7天】 + + http GET 方式 + http://10.0.0.239:7088/index/api/queryPictureList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=Media&stream=Camera_00001&starttime=20220317081201&endtime=20220319231201 + + http POST 方式 + http URL + http://190.15.240.11:7088/index/api/queryPictureList + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","vhost":"_defaultVhost_","app":"Media","stream":"Camera_00001","starttime":"20220317081201","endtime":"20220319231201"} + + 成功返回Body值 + { + "code": 0, + "app": "Media", + "stream": "Camera_00001", + "starttime": "20220317081201", + "endtime": "20220319231201", + "PictureFileList": [ + { + "file": "2022031816153857.jpg", + "url": "http://10.0.0.239:7088/Media/Camera_00001/2022031816153857.jpg" + }, + { + "file": "2022031816153958.jpg", + "url": "http://10.0.0.239:7088/Media/Camera_00001/2022031816153958.jpg" + }, + { + "file": "2022031816154059.jpg", + "url": "http://10.0.0.239:7088/Media/Camera_00001/2022031816154059.jpg" + }, + ] + } + + 22、修改某一路的水印相关参数 + + URL: index/api/setTransFilter + + 功能: + 修改某一路的水印相关参数,比水印的内容、颜色、字体大小、字体位置、字体透明度 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + vhost 比如 _defaultVhost_ 【可选参数】 + app 应用名 比如 rtp、gb28181、Media 等等 ,自己起的名字 【必填参数】 + stream 媒体流名 比如 Camera_00001、44303403343034243200234 等等 【必填参数】 + text 水印内容 比如 某某市某某公安局 【必填参数】 + size 字体大小 20、30 、40 、50 【必填参数】 + color 字体颜色 red,green,blue,white,black, + alpha 透明度 0.1 ~ 0.9 , + left 水印x坐标 比如 5 、 10 、20 + top 水印y坐标 比如 5 、 10 、 20 + trans 是否转换 固定为 1 + + http POST 方式 + http://127.0.0.1:7088/index/api/setTransFilter + + Body 参数内容为 + { + "secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc", + "app" : "live", + "stream" : "test", + "text" : "ABL", + "size" : 60, + "color" : "red", + "alpha" : 0.8, + "left" : 40, + "top" : 40, + "trans" : 1 + } + + 23、为了功能更新的需要,增加设置参数值的接口,可以单独设置 ABLMediaServer.ini 的某一个值,并且服务器不用重启,立即起效 + + URL: index/api/setConfigParamValue + + 功能: + 为了功能更新的需要,增加设置参数值的接口,可以单独设置 ABLMediaServer.ini 的某一个值,并且服务器不用重启,立即起效 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + vhost 比如 _defaultVhost_ 【可选参数】 + key 参数名 比如 saveGB28181Rtp (保存接入的国标PS流)、 saveProxyRtspRtp (保存rtsp代理拉流的rtp流) + 还有 ABLMediaServer.ini 里面的配置参数,如果参数值不填就设置空,不是空格 + mediaServerID = ABLMediaServer_00001 + secret = 035c73f7-bb6b-4889-a715-d9eb2d1925cc + localipAddress = + maxTimeNoOneWatch = 9999999 + recordPath = + picturePath = + maxSameTimeSnap = 16 + snapOutPictureWidth = 0 + snapOutPictureHeight = 0 + snapObjectDestroy = 1 + snapObjectDuration = 120 + captureReplayType = 1 + pictureMaxCount = 30 + pushEnable_mp4 = 0 + fileSecond = 300 + videoFileFormat = 1 + fileKeepMaxTime = 3 + httpDownloadSpeed = 6 + fileRepeat = 0 + H265ConvertH264_enable = 0 + H265DecodeCpuGpuType = 0 + H264DecodeEncode_enable = 0 + filterVideo_enable = 0 + filterVideo_text = ABL水印测试123 + FilterFontSize = 30 + FilterFontColor = red + FilterFontLeft = 5 + FilterFontTop = 5 + FilterFontAlpha = 0.6 + convertOutWidth = 720 + convertOutHeight = 480 + convertMaxObject = 26 + convertOutBitrate = 1024 + hook_enable = 0 + noneReaderDuration = 15 + on_server_started = http://10.0.0.238:4088/index/hook/on_server_started + on_server_keepalive = http://10.0.0.238:4088/index/hook/on_server_keepalive + on_stream_arrive = http://10.0.0.238:4088/index/hook/on_stream_arrive + on_stream_not_arrive = http://10.0.0.238:4088/index/hook/on_stream_not_arrive + on_stream_none_reader = http://10.0.0.238:4088/index/hook/on_stream_none_reader + on_stream_disconnect = http://10.0.0.238:4088/index/hook/on_stream_disconnect + on_stream_not_found = + on_record_mp4 = http://10.0.0.238:4088/index/hook/on_record_mp4 + on_delete_record_mp4 = http://10.0.0.238:4088/index/hook/on_delete_record_mp4 + on_record_progress = http://10.0.0.238:4088/index/hook/on_record_progress + on_record_ts = http://10.0.0.238:4088/index/hook/on_record_ts + httpServerPort = 7088 + rtspPort = 554 + rtmpPort = 1935 + httpMp4Port = 5088 + wsFlvPort = 6088 + httpFlvPort = 8088 + ps_tsRecvPort = 10000 + hls_enable = 0 + hlsPort = 9088 + hlsCutTime = 3 + hlsCutType = 2 + h265CutType = 1 + enable_audio = 1 + G711ConvertAAC = 0 + IOContentNumber = 16 + ThreadCountOfIOContent = 8 + RecvThreadCount = 128 + SendThreadCount = 128 + RecordReplayThread = 32 + GB28181RtpTCPHeadType = 2 + ReConnectingCount = 40320 + MaxDiconnectTimeoutSecond = 36 + ForceSendingIFrame = 1 + value 参数值 详见 ABLMediaServer.ini 的参数值及参数值说明 + + http GET 方式 +   比如: + 打开保存国标PS标志 +    http://44.35.33.239:7088/index/api/setConfigParamValue?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=saveGB28181Rtp&value=1 + 关闭存国标PS标志 +    http://44.35.33.239:7088/index/api/setConfigParamValue?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=saveGB28181Rtp&value=0 + + 打开保存代理拉rtsp流标志 +    http://44.35.33.239:7088/index/api/setConfigParamValue?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=saveProxyRtspRtp&value=1 + 关闭保存代理拉rtsp流标志 +    http://44.35.33.239:7088/index/api/setConfigParamValue?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=saveProxyRtspRtp&value=0 + + 24)安全停止服务器 + URL: /index/api/shutdownServer + + 功能: + 安全停止服务器,如果服务器正在录像、抓拍等等操作,需要调用该函数安全停止服务器,这样录制的mp4才能正常播放 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + + http GET 方式 + http://127.0.0.1:7088/index/api/shutdownServer?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http POST 方式 + http URL + http://127.0.0.1:7088/index/api/shutdownServer + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc"} + + 返回Body: + { + "code": 0, + "memo": "ABLMediaServer shutdown Successed !" + } + + 25)重新启动服务器 + URL: /index/api/restartServer + + 功能: + 安全重启服务器,如果服务器正在录像、抓拍等等操作,需要调用该函数安全重启服务器,这样录制的mp4才能正常播放 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + + http GET 方式 + http://127.0.0.1:7088/index/api/restartServer?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http POST 方式 + http URL + http://127.0.0.1:7088/index/api/restartServer + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc"} + + 返回Body: + { + "code": 0, + "memo": "ABLMediaServer restartServer Successed ! " + } + + 26)获取当前转码的数量 + URL: /index/api/getTranscodingCount + + 功能: + 获取当前正在转码的数量 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + + http GET 方式 + http://127.0.0.1:7088/index/api/getTranscodingCount?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http POST 方式 + http URL + http://127.0.0.1:7088/index/api/getTranscodingCount + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc"} + + 返回Body: + { + "code": 0, + "currentTranscodingCount": 2 + } + + 27)、列举流媒体服务器所有占用端口 + URL: /index/api/listServerPort + + 功能: + 列举流媒体服务器所有占用端口 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + app 应用名 比如 rtp、gb28181、Media 等等 ,自己起的名字 【可选参数】 + stream 媒体流名 比如 Camera_00001、44303403343034243200234 等等 【可选参数】 + + 参数填写样例说明: + 样例1(app、stream 都不填写) + secret 035c73f7-bb6b-4889-a715-d9eb2d1925cc + + 返回所有在线的媒体源 + + 样例2 (只填写 app ) + secret 035c73f7-bb6b-4889-a715-d9eb2d1925cc + app rtp + 返回 app 等于 rtp 的所有媒体源 + + 样例3 (填写 app = rtp , stream = 44303403343034243200234) + secret 035c73f7-bb6b-4889-a715-d9eb2d1925cc + app rtp + stream 44303403343034243200234 + 返回 app 等于 rtp、并且 stream 等于 44303403343034243200234 的所有媒体源 + + 样例4 (填写 stream = 44303403343034243200234) + secret 035c73f7-bb6b-4889-a715-d9eb2d1925cc + stream 44303403343034243200234 + 返回 stream 等于 44303403343034243200234 的所有媒体源 + + http GET 方式 + http://127.0.0.1:7088/index/api/listServerPort?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc + + http POST 方式 + http URL + http://127.0.0.1:7088/index/api/listServerPort + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc"} + + 返回Body: + { + "code": 0, + "memo": "success", + "data": [ + { + "key": 478, + "app": "Media", + "stream": "Camera_00003", + "networkType": 23, + "port": 34988 + }, + { + "key": 477, + "app": "Media", + "stream": "Camera_00002", + "networkType": 23, + "port": 34986 + }, + { + "key": 476, + "app": "Media", + "stream": "Camera_00001", + "networkType": 23, + "port": 34984 + }, + { + "key": 456, + "app": "", + "stream": "", + "networkType": 68, + "port": 10000 + } + ] + } + + 【注释:可以根据 "networkType": 23, 这个字段标识对象的网络类型 ,具体详见网络类型的对照表 】 + + 28)、批量设置服务器的配置参数 + URL: /index/api/setServerConfig + + 功能: + 批量设置服务器的配置参数 + + 参数: 参数说明 参数参考值 + secret 服务器密码 比如 035c73f7-bb6b-4889-a715-d9eb2d1925cc 【必填参数】 + noneReaderDuration 多少秒无人观看通知一次 20 【可选参数】 + on_server_started 服务器启动通知 http://10.0.0.238:4088/index/hook/on_server_started 【可选参数】 + iframeArriveNoticCount i帧达到通知总数 30 【可选参数】 + + http GET 方式 + http://127.0.0.1:7088/index/api/setServerConfig?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&noneReaderDuration=20&on_server_started=http://10.0.0.238:4088/index/hook/on_server_started&iframeArriveNoticCount=30 + + http POST 方式 + http URL + http://127.0.0.1:7088/index/api/setServerConfig + + http Body 参数 json 格式 + {"secret":"035c73f7-bb6b-4889-a715-d9eb2d1925cc","noneReaderDuration":20,"iframeArriveNoticCount":30,"on_server_started":"http://10.0.0.238:4088/index/hook/on_server_started"} + + 29) 为了方便某些特殊场合,服务器支持udp的10000 端口接入国标PS码流,就是人们常说的单端口模式,url的命名规则为 /rtp/ssrc ,其中ssrc为下级rtp打包 + 的16进制的值转换为大小的字符串,即可sprintf(url,"rtp/%X",ssrc) ,具体接入的url名字可以调用 getMediaList 查询出接入的国标流 。需要注意的是 + 下级 rtp 打包时每路视频的rtp中的ssrc不能相同。 + + + 30) 网络类型的对照表 + 1 媒体输入网络类型对照表 + + 整形值 代表意义 + 21 以rtmp方式推送接入流媒体服务器 + 23 以rtsp方式推送接入流媒体服务器 + 30 服务器以rtsp方式主动拉流接入 + 31 服务器以rtmp方式主动拉流接入 + 32 服务器以flv方式主动拉流接入 + 33 服务器以hls方式主动拉流接入 + 50 代理拉流接入服务器 + 60 服务器以国标28181的UDP方式接入 + 61 服务器以国标28181的TCP方式接入 + + 80 服务器录像文件点播以读取fmp4文件输入 + 81 服务器录像文件点播以读取TS文件输入 + 82 服务器录像文件点播以读取PS文件输入 + 83 服务器录像文件点播以读取FLV文件输入 + + 2 媒体输出网络类型对照表 + 整形值 代表意义 + 22 服务器以rtsp被动方式往外发送码流 ,即常见的vlc点播 + 24 服务器以rtmp被动方式往外发送码流 ,即常见的vlc点播 + 25 服务器以flv被动方式往外发送码流 ,即常见的vlc点播 、浏览器播放 + 26 服务器以hls被动方式往外发送码流 ,即常见的vlc点播 、浏览器播放 + 27 服务器以ws-flv被动方式往外发送码流 ,EasyPlayer.js插件播放、浏览器播放 + 28 服务器以http-mp4被动方式往外发送码流 ,即常见的vlc点播 、浏览器播放 + + 40 服务器以rtsp主动方式往外发送码流 ,即常见的rtsp推流 + 41 服务器以rtmp主动方式往外发送码流 ,即常见的rtmp推流 + 65 服务器以国标GB28181主动UDP方式往外发送码流 ,即常见的国标以UDP方式往上级推流 + 66 服务器以国标GB28181主动TCP方式往外发送码流 ,即常见的国标以TCP方式往上级推流 + \ No newline at end of file diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLRESTfulUtils.java index b2f36029..5eca3bf9 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLRESTfulUtils.java @@ -270,67 +270,38 @@ public class ABLRESTfulUtils { } } - public JSONObject getMediaList(MediaServer mediaServerItem, String app, String stream, String schema, RequestCallback callback){ + + public Integer openRtpServer(MediaServer mediaServer, String app, String stream, int payload, Integer port, Integer tcpMode, Integer disableAudio) { Map param = new HashMap<>(); - if (app != null) { - param.put("app",app); + param.put("vhost", "_defaultVhost_"); + param.put("app", app); + param.put("stream_id", stream); + param.put("payload", payload); + if (port != null) { + param.put("port", port); } - if (stream != null) { - param.put("stream",stream); + if (tcpMode != null) { + param.put("enable_tcp", tcpMode); } - if (schema != null) { - param.put("schema",schema); + if (disableAudio != null) { + param.put("disableAudio", disableAudio); + } + + JSONObject jsonObject = sendPost(mediaServer, "openRtpServer", param, null); + if (jsonObject.getInteger("code") == 0) { + return jsonObject.getInteger("port"); + }else { + return 0; } - param.put("vhost","__defaultVhost__"); - return sendPost(mediaServerItem, "getMediaList",param, callback); } - public JSONObject getMediaList(MediaServer mediaServerItem, String app, String stream){ - return getMediaList(mediaServerItem, app, stream,null, null); - } - - public JSONObject getMediaList(MediaServer mediaServerItem, RequestCallback callback){ - return sendPost(mediaServerItem, "getMediaList",null, callback); - } - - public JSONObject getMediaInfo(MediaServer mediaServerItem, String app, String schema, String stream){ + public JSONObject closeStreams(MediaServer mediaServerItem, String app, String stream) { Map param = new HashMap<>(); - param.put("app",app); - param.put("schema",schema); - param.put("stream",stream); - param.put("vhost","__defaultVhost__"); - return sendPost(mediaServerItem, "getMediaInfo",param, null); - } - - public JSONObject getRtpInfo(MediaServer mediaServerItem, String stream_id){ - Map param = new HashMap<>(); - param.put("stream_id",stream_id); - return sendPost(mediaServerItem, "getRtpInfo",param, null); - } - - public JSONObject addFFmpegSource(MediaServer mediaServerItem, String src_url, String dst_url, Integer timeout_ms, - boolean enable_audio, boolean enable_mp4, String ffmpeg_cmd_key){ - logger.info(src_url); - logger.info(dst_url); - Map param = new HashMap<>(); - param.put("src_url", src_url); - param.put("dst_url", dst_url); - param.put("timeout_ms", timeout_ms); - param.put("enable_mp4", enable_mp4); - param.put("ffmpeg_cmd_key", ffmpeg_cmd_key); - return sendPost(mediaServerItem, "addFFmpegSource",param, null); - } - - public JSONObject delFFmpegSource(MediaServer mediaServerItem, String key){ - Map param = new HashMap<>(); - param.put("key", key); - return sendPost(mediaServerItem, "delFFmpegSource",param, null); - } - - public JSONObject delStreamProxy(MediaServer mediaServerItem, String key){ - Map param = new HashMap<>(); - param.put("key", key); - return sendPost(mediaServerItem, "delStreamProxy",param, null); + param.put("vhost", "__defaultVhost__"); + param.put("app", app); + param.put("stream", stream); + param.put("force", 1); + return sendPost(mediaServerItem, "close_streams",param, null); } public JSONObject getServerConfig(MediaServer mediaServerItem){ @@ -343,116 +314,4 @@ public class ABLRESTfulUtils { param.put("value", value); return sendGet(mediaServerItem,"setConfigParamValue", param); } - - public JSONObject openRtpServer(MediaServer mediaServerItem, Map param){ - return sendPost(mediaServerItem, "openRtpServer",param, null); - } - - public JSONObject closeRtpServer(MediaServer mediaServerItem, Map param) { - return sendPost(mediaServerItem, "closeRtpServer",param, null); - } - - public void closeRtpServer(MediaServer mediaServerItem, Map param, RequestCallback callback) { - sendPost(mediaServerItem, "closeRtpServer",param, callback); - } - - public JSONObject listRtpServer(MediaServer mediaServerItem) { - return sendPost(mediaServerItem, "listRtpServer",null, null); - } - - public JSONObject startSendRtp(MediaServer mediaServerItem, Map param) { - return sendPost(mediaServerItem, "startSendRtp",param, null); - } - - public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map param) { - return sendPost(mediaServerItem, "startSendRtpPassive",param, null); - } - - public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map param, RequestCallback callback) { - return sendPost(mediaServerItem, "startSendRtpPassive",param, callback); - } - - public JSONObject stopSendRtp(MediaServer mediaServerItem, Map param) { - return sendPost(mediaServerItem, "stopSendRtp",param, null); - } - - public JSONObject restartServer(MediaServer mediaServerItem) { - return sendPost(mediaServerItem, "restartServer",null, null); - } - - public JSONObject addStreamProxy(MediaServer mediaServerItem, String app, String stream, String url, boolean enable_audio, boolean enable_mp4, String rtp_type) { - Map param = new HashMap<>(); - param.put("vhost", "__defaultVhost__"); - param.put("app", app); - param.put("stream", stream); - param.put("url", url); - param.put("enable_mp4", enable_mp4?1:0); - param.put("enable_audio", enable_audio?1:0); - param.put("rtp_type", rtp_type); - return sendPost(mediaServerItem, "addStreamProxy",param, null, 20); - } - - public JSONObject closeStreams(MediaServer mediaServerItem, String app, String stream) { - Map param = new HashMap<>(); - param.put("vhost", "__defaultVhost__"); - param.put("app", app); - param.put("stream", stream); - param.put("force", 1); - return sendPost(mediaServerItem, "close_streams",param, null); - } - - public JSONObject getAllSession(MediaServer mediaServerItem) { - return sendPost(mediaServerItem, "getAllSession",null, null); - } - - public void kickSessions(MediaServer mediaServerItem, String localPortSStr) { - Map param = new HashMap<>(); - param.put("local_port", localPortSStr); - sendPost(mediaServerItem, "kick_sessions",param, null); - } - - public void getSnap(MediaServer mediaServerItem, String streamUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { - Map param = new HashMap<>(3); - param.put("url", streamUrl); - param.put("timeout_sec", timeout_sec); - param.put("expire_sec", expire_sec); - sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName); - } - - public JSONObject pauseRtpCheck(MediaServer mediaServerItem, String streamId) { - Map param = new HashMap<>(1); - param.put("stream_id", streamId); - return sendPost(mediaServerItem, "pauseRtpCheck",param, null); - } - - public JSONObject resumeRtpCheck(MediaServer mediaServerItem, String streamId) { - Map param = new HashMap<>(1); - param.put("stream_id", streamId); - return sendPost(mediaServerItem, "resumeRtpCheck",param, null); - } - - public JSONObject connectRtpServer(MediaServer mediaServerItem, String dst_url, int dst_port, String stream_id) { - Map param = new HashMap<>(1); - param.put("dst_url", dst_url); - param.put("dst_port", dst_port); - param.put("stream_id", stream_id); - return sendPost(mediaServerItem, "connectRtpServer",param, null); - } - - public JSONObject updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) { - Map param = new HashMap<>(1); - param.put("ssrc", ssrc); - param.put("stream_id", streamId); - return sendPost(mediaServerItem, "updateRtpServerSSRC",param, null); - } - - public JSONObject deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName) { - Map param = new HashMap<>(1); - param.put("vhost", "__defaultVhost__"); - param.put("app", app); - param.put("stream", stream); - param.put("period", date); - param.put("name", fileName); - return sendPost(mediaServerItem, "deleteRecordDirectory",param, null); - } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/bean/hook/ABLHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/abl/bean/hook/ABLHookParam.java index 8662085a..796935ea 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/abl/bean/hook/ABLHookParam.java +++ b/src/main/java/com/genersoft/iot/vmp/media/abl/bean/hook/ABLHookParam.java @@ -21,7 +21,7 @@ public class ABLHookParam { /** * 媒体流来源网络编号,可参考附表 */ - private String networkType; + private Integer networkType; public String getMediaServerId() { return mediaServerId; @@ -55,11 +55,11 @@ public class ABLHookParam { this.key = key; } - public String getNetworkType() { + public Integer getNetworkType() { return networkType; } - public void setNetworkType(String networkType) { + public void setNetworkType(Integer networkType) { this.networkType = networkType; } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java index 2853cd2a..8ee0eaf3 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.media.abl.bean.hook.OnStreamArriveABLHookParam; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OriginType; import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; @@ -186,6 +187,24 @@ public class MediaInfo { mediaInfo.setReaderCount(param.getReaderCount()); mediaInfo.setOnline(true); mediaInfo.setVideoCodec(param.getVideoCodec()); + switch (param.getNetworkType()) { + case 21: + mediaInfo.setOriginType(OriginType.RTMP_PUSH.ordinal()); + break; + case 23: + mediaInfo.setOriginType(OriginType.RTSP_PUSH.ordinal()); + break; + case 30: + case 31: + case 32: + case 33: + mediaInfo.setOriginType(OriginType.PULL.ordinal()); + break; + default: + mediaInfo.setOriginType(OriginType.UNKNOWN.ordinal()); + break; + + } mediaInfo.setWidth(param.getWidth()); mediaInfo.setHeight(param.getHeight()); mediaInfo.setAudioCodec(param.getAudioCodec()); diff --git a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java index 5c32ea7a..decbd4e8 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java +++ b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java @@ -32,6 +32,18 @@ public class MediaServer { @Schema(description = "RTMP端口") private int rtmpPort; + @Schema(description = "flv端口") + private int flvPort; + + @Schema(description = "https-flv端口") + private int flvSSLPort; + + @Schema(description = "ws-flv端口") + private int wsFlvPort; + + @Schema(description = "wss-flv端口") + private int wsFlvSSLPort; + @Schema(description = "RTMPS端口") private int rtmpSSlPort; @@ -98,7 +110,11 @@ public class MediaServer { sdpIp = ObjectUtils.isEmpty(zlmServerConfig.getSdpIp())? zlmServerConfig.getIp(): zlmServerConfig.getSdpIp(); streamIp = ObjectUtils.isEmpty(zlmServerConfig.getStreamIp())? zlmServerConfig.getIp(): zlmServerConfig.getStreamIp(); httpPort = zlmServerConfig.getHttpPort(); + flvPort = zlmServerConfig.getHttpPort(); + wsFlvPort = zlmServerConfig.getHttpPort(); httpSSlPort = zlmServerConfig.getHttpSSLport(); + flvSSLPort = zlmServerConfig.getHttpSSLport(); + wsFlvSSLPort = zlmServerConfig.getHttpSSLport(); rtmpPort = zlmServerConfig.getRtmpPort(); rtmpSSlPort = zlmServerConfig.getRtmpSslPort(); rtpProxyPort = zlmServerConfig.getRtpProxyPort(); @@ -328,4 +344,36 @@ public class MediaServer { public void setType(String type) { this.type = type; } + + public int getFlvPort() { + return flvPort; + } + + public void setFlvPort(int flvPort) { + this.flvPort = flvPort; + } + + public int getFlvSSLPort() { + return flvSSLPort; + } + + public void setFlvSSLPort(int flvSSLPort) { + this.flvSSLPort = flvSSLPort; + } + + public int getWsFlvPort() { + return wsFlvPort; + } + + public void setWsFlvPort(int wsFlvPort) { + this.wsFlvPort = wsFlvPort; + } + + public int getWsFlvSSLPort() { + return wsFlvSSLPort; + } + + public void setWsFlvSSLPort(int wsFlvSSLPort) { + this.wsFlvSSLPort = wsFlvSSLPort; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookSubscribe.java index 345cc48a..33536568 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookSubscribe.java @@ -35,7 +35,7 @@ public class HookSubscribe { @Async("taskExecutor") @EventListener public void onApplicationEvent(MediaArrivalEvent event) { - if ("rtsp".equals(event.getSchema())) { + if (event.getSchema() == null || "rtsp".equals(event.getSchema())) { sendNotify(HookType.on_media_arrival, event); } @@ -47,7 +47,7 @@ public class HookSubscribe { @Async("taskExecutor") @EventListener public void onApplicationEvent(MediaDepartureEvent event) { - if ("rtsp".equals(event.getSchema())) { + if (event.getSchema() == null || "rtsp".equals(event.getSchema())) { sendNotify(HookType.on_media_departure, event); } diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java index 39770457..4b6b2215 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java @@ -10,7 +10,7 @@ import java.util.List; import java.util.Map; public interface IMediaNodeServerService { - int createRTPServer(MediaServer mediaServer, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode); + int createRTPServer(MediaServer mediaServer, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode); void closeRtpServer(MediaServer mediaServer, String streamId); diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java index 2b11c033..2a72eb43 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java @@ -33,9 +33,7 @@ public interface IMediaServerService { void updateVmServer(List mediaServerItemList); SSRCInfo openRTPServer(MediaServer mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, - boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode); - - SSRCInfo openRTPServer(MediaServer mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto); + boolean isPlayback, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode); void closeRTPServer(MediaServer mediaServerItem, String streamId); diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java index add9d949..1b5d109e 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java @@ -132,7 +132,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public SSRCInfo openRTPServer(MediaServer mediaServer, String streamId, String presetSsrc, boolean ssrcCheck, - boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { + boolean isPlayback, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode) { if (mediaServer == null || mediaServer.getId() == null) { logger.info("[openRTPServer] 失败, mediaServer == null || mediaServer.getId() == null"); return null; @@ -163,19 +163,13 @@ public class MediaServerServiceImpl implements IMediaServerService { logger.info("[openRTPServer] 失败, mediaServer的类型: {},未找到对应的实现类", mediaServer.getType()); return null; } - rtpServerPort = mediaNodeServerService.createRTPServer(mediaServer, streamId, ssrcCheck ? Long.parseLong(ssrc) : 0, port, onlyAuto, reUsePort, tcpMode); + rtpServerPort = mediaNodeServerService.createRTPServer(mediaServer, streamId, ssrcCheck ? Long.parseLong(ssrc) : 0, port, onlyAuto, disableAudio, reUsePort, tcpMode); } else { rtpServerPort = mediaServer.getRtpProxyPort(); } return new SSRCInfo(rtpServerPort, ssrc, streamId); } - @Override - public SSRCInfo openRTPServer(MediaServer mediaServer, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto) { - return openRTPServer(mediaServer, streamId, ssrc, ssrcCheck, isPlayback, port, onlyAuto, null, 0); - } - - @Override public void closeRTPServer(MediaServer mediaServer, String streamId) { if (mediaServer == null) { @@ -770,7 +764,18 @@ public class MediaServerServiceImpl implements IMediaServerService { String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId; streamInfoResult.setRtmp(addr, mediaServer.getRtmpPort(),mediaServer.getRtmpSSlPort(), app, stream, callIdParam); streamInfoResult.setRtsp(addr, mediaServer.getRtspPort(),mediaServer.getRtspSSLPort(), app, stream, callIdParam); - streamInfoResult.setFlv(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); + + + if ("abl".equals(mediaServer.getType())) { + String flvFile = String.format("%s/%s.flv%s", app, stream, callIdParam); + streamInfoResult.setFlv(addr, mediaServer.getFlvPort(),mediaServer.getFlvSSLPort(), flvFile); + streamInfoResult.setWsFlv(addr, mediaServer.getWsFlvPort(),mediaServer.getWsFlvSSLPort(), flvFile); + }else { + String flvFile = String.format("%s/%s.live.flv%s", app, stream, callIdParam); + streamInfoResult.setFlv(addr, mediaServer.getFlvPort(),mediaServer.getFlvSSLPort(), flvFile); + streamInfoResult.setWsFlv(addr, mediaServer.getWsFlvPort(),mediaServer.getWsFlvSSLPort(), flvFile); + } + streamInfoResult.setFmp4(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); streamInfoResult.setHls(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); streamInfoResult.setTs(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java index 5b566d80..8fbe5303 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java @@ -39,7 +39,7 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService { private String sipIp; @Override - public int createRTPServer(MediaServer mediaServer, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { + public int createRTPServer(MediaServer mediaServer, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode) { return zlmServerFactory.createRTPServer(mediaServer, streamId, ssrc, port, onlyAuto, reUsePort, tcpMode); } @@ -178,7 +178,9 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService { String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId; streamInfoResult.setRtmp(addr, mediaServer.getRtmpPort(),mediaServer.getRtmpSSlPort(), app, stream, callIdParam); streamInfoResult.setRtsp(addr, mediaServer.getRtspPort(),mediaServer.getRtspSSLPort(), app, stream, callIdParam); - streamInfoResult.setFlv(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); + String flvFile = String.format("%s/%s.live.flv%s", app, stream, callIdParam); + streamInfoResult.setFlv(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), flvFile); + streamInfoResult.setWsFlv(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), flvFile); streamInfoResult.setFmp4(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); streamInfoResult.setHls(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); streamInfoResult.setTs(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java index 2cc4f49a..e4ddb120 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java @@ -542,7 +542,7 @@ public class PlatformServiceImpl implements IPlatformService { } else { tcpMode = 0; } - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, ssrcCheck, false, null, true, false, tcpMode); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, ssrcCheck, false, null, true, false, false, tcpMode); if (ssrcInfo == null || ssrcInfo.getPort() < 0) { logger.info("[国标级联] 发起语音喊话 开启端口监听失败, platform: {}, channel: {}", platform.getServerGBId(), channelId); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult<>(); 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 c8d6f862..5c6bca2f 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -259,7 +259,7 @@ public class PlayServiceImpl implements IPlayService { ); SSRCInfo ssrcInfo = mediaServerService.openRTPServer(event.getMediaServer(), event.getStream(), null, - device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); + device.isSsrcCheck(), true, 0, false, !deviceChannel.isHasAudio(), false, device.getStreamModeForParam()); playBack(event.getMediaServer(), ssrcInfo, deviceId, channelId, startTime, endTime, null); } } @@ -321,7 +321,7 @@ public class PlayServiceImpl implements IPlayService { } } String streamId = String.format("%s_%s", device.getDeviceId(), channelId); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.isHasAudio(), false, device.getStreamModeForParam()); if (ssrcInfo == null) { callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null); inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, @@ -762,6 +762,12 @@ public class PlayServiceImpl implements IPlayService { throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到设备:" + deviceId); } + DeviceChannel channel = channelService.getOne(deviceId, channelId); + if (channel == null) { + logger.warn("[录像回放] 未找到通道 deviceId: {},channelId:{}", deviceId, channelId); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到通道:" + channelId); + } + MediaServer newMediaServerItem = getNewMediaServerItem(device); if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && ! newMediaServerItem.isRtpEnable()) { logger.warn("[录像回放] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId); @@ -774,7 +780,7 @@ public class PlayServiceImpl implements IPlayService { .replace(":", "") .replace(" ", ""); String stream = deviceId + "_" + channelId + "_" + startTimeStr + "_" + endTimeTimeStr; - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, !channel.isHasAudio(), false, device.getStreamModeForParam()); playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, callback); } @@ -959,6 +965,10 @@ public class PlayServiceImpl implements IPlayService { if (device == null) { return; } + DeviceChannel channel = channelService.getOne(deviceId, channelId); + if (channel == null) { + return; + } MediaServer newMediaServerItem = this.getNewMediaServerItem(device); if (newMediaServerItem == null) { callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(), @@ -967,7 +977,7 @@ public class PlayServiceImpl implements IPlayService { return; } // 录像下载不使用固定流地址,固定流地址会导致如果开始时间与结束时间一致时文件错误的叠加在一起 - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,!channel.isHasAudio(), false, device.getStreamModeForParam()); download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, callback); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java index 1ea22548..6473c42f 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java @@ -24,6 +24,10 @@ public interface MediaServerMapper { "rtmp_ssl_port,"+ "rtp_proxy_port,"+ "rtsp_port,"+ + "flv_port," + + "flv_ssl_port," + + "ws_flv_port," + + "ws_flv_ssl__port," + "rtsp_ssl_port,"+ "auto_config,"+ "secret,"+ @@ -51,6 +55,10 @@ public interface MediaServerMapper { "#{rtmpSSlPort}, " + "#{rtpProxyPort}, " + "#{rtspPort}, " + + "#{flvPort}, " + + "#{flvSSLPort}, " + + "#{wsFlvPort}, " + + "#{wsFlvSSLPort}, " + "#{rtspSSLPort}, " + "#{autoConfig}, " + "#{secret}, " + @@ -81,6 +89,10 @@ public interface MediaServerMapper { ", rtp_proxy_port=#{rtpProxyPort}" + ", rtsp_port=#{rtspPort}" + ", rtsp_ssl_port=#{rtspSSLPort}" + + ", flv_port=#{flvPort}" + + ", flv_ssl_port=#{flvSSLPort}" + + ", ws_flv_port=#{wsFlvPort}" + + ", ws_flv_ssl_port=#{wsFlvSSLPort}" + ", auto_config=#{autoConfig}" + ", rtp_enable=#{rtpEnable}" + ", rtp_port_range=#{rtpPortRange}" + @@ -108,6 +120,10 @@ public interface MediaServerMapper { ", rtp_proxy_port=#{rtpProxyPort}" + ", rtsp_port=#{rtspPort}" + ", rtsp_ssl_port=#{rtspSSLPort}" + + ", flv_port=#{flvPort}" + + ", flv_ssl_port=#{flvSSLPort}" + + ", ws_flv_port=#{wsFlvPort}" + + ", ws_flv_ssl_port=#{wsFlvSSLPort}" + ", auto_config=#{autoConfig}" + ", rtp_enable=#{rtpEnable}" + ", rtp_port_range=#{rtpPortRange}" + diff --git a/数据库/abl/初始化-mysql-2.7.0.sql b/数据库/abl/初始化-mysql-2.7.0.sql index 7fece768..0290a06c 100644 --- a/数据库/abl/初始化-mysql-2.7.0.sql +++ b/数据库/abl/初始化-mysql-2.7.0.sql @@ -155,6 +155,10 @@ create table wvp_media_server ( rtp_proxy_port integer, rtsp_port integer, rtsp_ssl_port integer, + flv_port integer, + flv_ssl_port integer, + ws_flv_port integer, + ws_flv_ssl_port integer, auto_config bool default false, secret character varying(50), type character varying(50) default 'zlm', diff --git a/数据库/abl/初始化-postgresql-kingbase-2.7.0.sql b/数据库/abl/初始化-postgresql-kingbase-2.7.0.sql index 656f7a00..b2fbea55 100644 --- a/数据库/abl/初始化-postgresql-kingbase-2.7.0.sql +++ b/数据库/abl/初始化-postgresql-kingbase-2.7.0.sql @@ -155,6 +155,10 @@ create table wvp_media_server ( rtp_proxy_port integer, rtsp_port integer, rtsp_ssl_port integer, + flv_port integer, + flv_ssl_port integer, + ws_flv_port integer, + ws_flv_ssl_port integer, auto_config bool default false, secret character varying(50), type character varying(50) default 'zlm', diff --git a/数据库/abl/更新-mysql-2.7.0.sql b/数据库/abl/更新-mysql-2.7.0.sql index de92cb2c..85136587 100644 --- a/数据库/abl/更新-mysql-2.7.0.sql +++ b/数据库/abl/更新-mysql-2.7.0.sql @@ -1,2 +1,11 @@ alter table wvp_media_server add type character varying(50) default 'zlm'; + +alter table wvp_media_server + add flv_port integer; +alter table wvp_media_server + add flv_ssl_port integer; +alter table wvp_media_server + add ws_flv_port integer; +alter table wvp_media_server + add ws_flv_ssl_port integer; diff --git a/数据库/abl/更新-postgresql-kingbase-2.7.0.sql b/数据库/abl/更新-postgresql-kingbase-2.7.0.sql index 45f69593..9a527cb3 100644 --- a/数据库/abl/更新-postgresql-kingbase-2.7.0.sql +++ b/数据库/abl/更新-postgresql-kingbase-2.7.0.sql @@ -1,2 +1,11 @@ alter table wvp_media_server - add type character varying(50) default 'zlm',; \ No newline at end of file + add type character varying(50) default 'zlm'; + +alter table wvp_media_server + add flv_port integer; +alter table wvp_media_server + add flv_ssl_port integer; +alter table wvp_media_server + add ws_flv_port integer; +alter table wvp_media_server + add ws_flv_ssl_port integer; \ No newline at end of file