diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index 0c450a74..b9c05e45 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -128,29 +128,29 @@ public class ZLMHttpHookListener { } String app = json.getString("app"); String streamId = json.getString("id"); + if ("rtp".equals(app)) { + String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16)); + StreamInfo streamInfoForPlay = storager.queryPlayBySSRC(ssrc); + if ("rtp".equals(app) && streamInfoForPlay != null ) { + MediaServerConfig mediaInfo = storager.getMediaInfo(); + streamInfoForPlay.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlay.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlay.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), streamId)); + streamInfoForPlay.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlay.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId)); + storager.startPlay(streamInfoForPlay); + } - - String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16)); - StreamInfo streamInfoForPlay = storager.queryPlayBySSRC(ssrc); - if ("rtp".equals(app) && streamInfoForPlay != null ) { - MediaServerConfig mediaInfo = storager.getMediaInfo(); - streamInfoForPlay.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoForPlay.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoForPlay.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), streamId)); - streamInfoForPlay.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoForPlay.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId)); - storager.startPlay(streamInfoForPlay); - } - - StreamInfo streamInfoForPlayBack = storager.queryPlaybackBySSRC(ssrc); - if ("rtp".equals(app) && streamInfoForPlayBack != null ) { - MediaServerConfig mediaInfo = storager.getMediaInfo(); - streamInfoForPlayBack.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoForPlayBack.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoForPlayBack.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), streamId)); - streamInfoForPlayBack.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoForPlayBack.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId)); - storager.startPlayback(streamInfoForPlayBack); + StreamInfo streamInfoForPlayBack = storager.queryPlaybackBySSRC(ssrc); + if ("rtp".equals(app) && streamInfoForPlayBack != null ) { + MediaServerConfig mediaInfo = storager.getMediaInfo(); + streamInfoForPlayBack.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlayBack.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlayBack.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), streamId)); + streamInfoForPlayBack.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlayBack.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId)); + storager.startPlayback(streamInfoForPlayBack); + } } // TODO Auto-generated method stub diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java index 86f05da4..1e38bdc7 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java @@ -89,6 +89,22 @@ public class ZLMRESTfulUtils { return sendPost("getRtpInfo",param); } + public JSONObject addFFmpegSource(String src_url, String dst_url, String timeout_ms){ + System.out.println(src_url); + System.out.println(dst_url); + Map param = new HashMap<>(); + param.put("src_url", src_url); + param.put("dst_url", dst_url); + param.put("timeout_ms", timeout_ms); + return sendPost("addFFmpegSource",param); + } + + public JSONObject delFFmpegSource(String key){ + Map param = new HashMap<>(); + param.put("key", key); + return sendPost("delFFmpegSource",param); + } + public JSONObject getMediaServerConfig(){ return sendPost("getServerConfig",null); } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index fc519dae..e7cfdb21 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -101,7 +101,8 @@ public class ZLMRunner implements CommandLineRunner { String hookPrex = String.format("http://%s:%s/index/hook", hookIP, serverPort); Map param = new HashMap<>(); - param.put("secret",mediaSecret); + param.put("api.secret",mediaSecret); // -profile:v Baseline + param.put("ffmpeg.cmd","%s -fflags nobuffer -rtsp_transport tcp -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"); param.put("hook.enable","1"); param.put("hook.on_flow_report",""); param.put("hook.on_play",""); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java index f44e7df7..8195b656 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java @@ -29,7 +29,7 @@ public class ZLMUtils { param.put("enable_tcp", 1); param.put("stream_id", streamId); JSONObject jsonObject = zlmresTfulUtils.openRtpServer(param); - if (jsonObject.getInteger("code") == 0) { + if (jsonObject != null && jsonObject.getInteger("code") == 0) { return newPort; } else { return getNewRTPPort(ssrc); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java index a01748e2..300ffc3d 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.play; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.conf.MediaServerConfig; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,7 +47,7 @@ public class PlayController { Integer getEncoding) { if (getEncoding == null) getEncoding = 0; - getEncoding = closeWaitRTPInfo ? 0: getEncoding; + getEncoding = closeWaitRTPInfo ? 0 : getEncoding; Device device = storager.queryVideoDevice(deviceId); StreamInfo streamInfo = storager.queryPlayByDevice(deviceId, channelId); @@ -149,5 +150,73 @@ public class PlayController { return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); } } + + /** + * 将不是h264的视频通过ffmpeg 转码为h264 + aac + * @param ssrc + * @return + */ + @PostMapping("/play/{ssrc}/convert") + public ResponseEntity playConvert(@PathVariable String ssrc) { + StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc); + if (streamInfo == null) { + logger.warn("视频转码API调用失败!, 视频流已经停止!"); + return new ResponseEntity("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK); + } + String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); + if (!rtpInfo.getBoolean("exist")) { + logger.warn("视频转码API调用失败!, 视频流已停止推流!"); + return new ResponseEntity("推流信息在流媒体中不存在, 视频流可能已停止推流", HttpStatus.OK); + } else { + MediaServerConfig mediaInfo = storager.getMediaInfo(); + String dstUrl = String.format("rtmp://%s:%s/convert/%s", "127.0.0.1", mediaInfo.getRtmpPort(), + streamId ); + JSONObject jsonObject = zlmresTfulUtils.addFFmpegSource(streamInfo.getRtsp(), dstUrl, "1000000"); + System.out.println(jsonObject); + JSONObject result = new JSONObject(); + if (jsonObject != null && jsonObject.getInteger("code") == 0) { + result.put("code", 0); + JSONObject data = jsonObject.getJSONObject("data"); + if (data != null) { + result.put("key", data.getString("key")); + result.put("rtmp", dstUrl); + result.put("flv", String.format("http://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + result.put("ws_flv", String.format("ws://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + } + }else { + result.put("code", 1); + result.put("msg", "cover fail"); + } + return new ResponseEntity( result.toJSONString(), HttpStatus.OK); + } + } + + /** + * 结束转码 + * @param key + * @return + */ + @PostMapping("/play/convert/stop/{key}") + public ResponseEntity playConvertStop(@PathVariable String key) { + + JSONObject jsonObject = zlmresTfulUtils.delFFmpegSource(key); + System.out.println(jsonObject); + JSONObject result = new JSONObject(); + if (jsonObject != null && jsonObject.getInteger("code") == 0) { + result.put("code", 0); + JSONObject data = jsonObject.getJSONObject("data"); + if (data != null && data.getBoolean("flag")) { + result.put("code", "0"); + result.put("msg", "success"); + }else { + + } + }else { + result.put("code", 1); + result.put("msg", "delFFmpegSource fail"); + } + return new ResponseEntity( result.toJSONString(), HttpStatus.OK); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 49bd03f9..463548a2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -44,8 +44,11 @@ media: #zlm服务器的ip与http端口, 重点: 这是http端口 wanIp: port: 80 secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc - streamNoneReaderDelayMS: 1800000 # 无人观看多久自动关闭流 - closeWaitRTPInfo: false # 强制关闭等待收到流编码信息后在返回, 设为true可以快速打开播放窗口, 设为false保证返回后流就可以播放 + streamNoneReaderDelayMS: 600000 # 无人观看多久自动关闭流 + # 关闭等待收到流编码信息后在返回, + # 设为false可以获得更好的兼容性,保证返回后流就可以播放, + # 设为true可以快速打开播放窗口,可以获得更好的体验 + closeWaitRTPInfo: true rtp: # 启用udp多端口模式 enable: true udpPortRange: 30000,30500 # 端口范围 diff --git a/web_src/src/components/gb28181/devicePlayer.vue b/web_src/src/components/gb28181/devicePlayer.vue index 780d03e5..c87d0c49 100644 --- a/web_src/src/components/gb28181/devicePlayer.vue +++ b/web_src/src/components/gb28181/devicePlayer.vue @@ -1,7 +1,7 @@