Commit fbdad00cdb294a857f55e33b2dd92c61dc37475c

Authored by 648540858
1 parent f9ab13a1

修复无音频通道开启通道音频后无法播放的bug

修复点播接口真的收到视频后回复
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
1 package com.genersoft.iot.vmp.common; 1 package com.genersoft.iot.vmp.common;
2 2
  3 +import com.alibaba.fastjson.JSONArray;
  4 +
3 public class StreamInfo { 5 public class StreamInfo {
4 6
5 private String ssrc; 7 private String ssrc;
@@ -10,6 +12,7 @@ public class StreamInfo { @@ -10,6 +12,7 @@ public class StreamInfo {
10 private String rtmp; 12 private String rtmp;
11 private String hls; 13 private String hls;
12 private String rtsp; 14 private String rtsp;
  15 + private JSONArray tracks;
13 16
14 public String getSsrc() { 17 public String getSsrc() {
15 return ssrc; 18 return ssrc;
@@ -74,4 +77,12 @@ public class StreamInfo { @@ -74,4 +77,12 @@ public class StreamInfo {
74 public void setCahnnelId(String cahnnelId) { 77 public void setCahnnelId(String cahnnelId) {
75 this.cahnnelId = cahnnelId; 78 this.cahnnelId = cahnnelId;
76 } 79 }
  80 +
  81 + public JSONArray getTracks() {
  82 + return tracks;
  83 + }
  84 +
  85 + public void setTracks(JSONArray tracks) {
  86 + this.tracks = tracks;
  87 + }
77 } 88 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -46,6 +46,9 @@ public class ZLMHttpHookListener { @@ -46,6 +46,9 @@ public class ZLMHttpHookListener {
46 @Autowired 46 @Autowired
47 private IVideoManagerStorager storager; 47 private IVideoManagerStorager storager;
48 48
  49 + @Autowired
  50 + private ZLMRESTfulUtils zlmresTfulUtils;
  51 +
49 @Value("${media.ip}") 52 @Value("${media.ip}")
50 private String mediaIp; 53 private String mediaIp;
51 54
@@ -125,6 +128,8 @@ public class ZLMHttpHookListener { @@ -125,6 +128,8 @@ public class ZLMHttpHookListener {
125 } 128 }
126 String app = json.getString("app"); 129 String app = json.getString("app");
127 String streamId = json.getString("id"); 130 String streamId = json.getString("id");
  131 +
  132 +
128 // String ssrc = String.format("%10d", Integer.parseInt(streamId, 16)); // ZLM 要求大写且首位补零 133 // String ssrc = String.format("%10d", Integer.parseInt(streamId, 16)); // ZLM 要求大写且首位补零
129 String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16)); 134 String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
130 StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc); 135 StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
@@ -135,6 +140,8 @@ public class ZLMHttpHookListener { @@ -135,6 +140,8 @@ public class ZLMHttpHookListener {
135 streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId)); 140 streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId));
136 streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); 141 streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
137 streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId)); 142 streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId));
  143 +
  144 +
138 storager.startPlay(streamInfo); 145 storager.startPlay(streamInfo);
139 } 146 }
140 147
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONObject;
  5 +import okhttp3.*;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
  8 +import org.springframework.beans.factory.annotation.Value;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +import java.io.IOException;
  12 +import java.util.HashMap;
  13 +import java.util.HashSet;
  14 +import java.util.Map;
  15 +
  16 +@Component
  17 +public class ZLMRESTfulUtils {
  18 +
  19 + private final static Logger logger = LoggerFactory.getLogger(ZLMRESTfulUtils.class);
  20 +
  21 + @Value("${media.ip}")
  22 + private String mediaIp;
  23 +
  24 + @Value("${media.port}")
  25 + private int mediaPort;
  26 +
  27 + @Value("${media.secret}")
  28 + private String mediaSecret;
  29 +
  30 + public JSONObject sendPost(String api, Map<String, Object> param) {
  31 + OkHttpClient client = new OkHttpClient();
  32 + String url = String.format("http://%s:%s/index/api/%s", mediaIp, mediaPort, api);
  33 + JSONObject responseJSON = null;
  34 + logger.debug(url);
  35 +
  36 + FormBody.Builder builder = new FormBody.Builder();
  37 + builder.add("secret",mediaSecret);
  38 + if (param != null) {
  39 + for (String key : param.keySet()){
  40 + builder.add(key, param.get(key).toString());
  41 + }
  42 + }
  43 +
  44 + FormBody body = builder.build();
  45 +
  46 + Request request = new Request.Builder()
  47 + .post(body)
  48 + .url(url)
  49 + .build();
  50 + try {
  51 + Response response = client.newCall(request).execute();
  52 + if (response.isSuccessful()) {
  53 + String responseStr = response.body().string();
  54 + if (responseStr != null) {
  55 + responseJSON = JSON.parseObject(responseStr);
  56 + }
  57 + }
  58 + } catch (IOException e) {
  59 + e.printStackTrace();
  60 + }
  61 +
  62 + return responseJSON;
  63 + }
  64 +
  65 + public JSONObject getMediaList(String app, String schema){
  66 + Map<String, Object> param = new HashMap<>();
  67 + param.put("app",app);
  68 + param.put("schema",schema);
  69 + param.put("vhost","__defaultVhost__");
  70 + return sendPost("getMediaList",param);
  71 + }
  72 +
  73 + public JSONObject getRtpInfo(String stream_id){
  74 + Map<String, Object> param = new HashMap<>();
  75 + param.put("stream_id",stream_id);
  76 + return sendPost("getRtpInfo",param);
  77 + }
  78 +
  79 + public JSONObject getMediaServerConfig(){
  80 + return sendPost("getServerConfig",null);
  81 + }
  82 +
  83 + public JSONObject setServerConfig(Map<String, Object> param){
  84 + return sendPost("setServerConfig",param);
  85 + }
  86 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -17,6 +17,8 @@ import org.springframework.stereotype.Component; @@ -17,6 +17,8 @@ import org.springframework.stereotype.Component;
17 import java.io.IOException; 17 import java.io.IOException;
18 import java.io.UnsupportedEncodingException; 18 import java.io.UnsupportedEncodingException;
19 import java.net.URLEncoder; 19 import java.net.URLEncoder;
  20 +import java.util.HashMap;
  21 +import java.util.Map;
20 22
21 @Component 23 @Component
22 @Order(value=1) 24 @Order(value=1)
@@ -42,6 +44,9 @@ public class ZLMRunner implements CommandLineRunner { @@ -42,6 +44,9 @@ public class ZLMRunner implements CommandLineRunner {
42 @Value("${server.port}") 44 @Value("${server.port}")
43 private String serverPort; 45 private String serverPort;
44 46
  47 + @Autowired
  48 + private ZLMRESTfulUtils zlmresTfulUtils;
  49 +
45 @Override 50 @Override
46 public void run(String... strings) throws Exception { 51 public void run(String... strings) throws Exception {
47 // 获取zlm信息 52 // 获取zlm信息
@@ -59,41 +64,23 @@ public class ZLMRunner implements CommandLineRunner { @@ -59,41 +64,23 @@ public class ZLMRunner implements CommandLineRunner {
59 64
60 65
61 public MediaServerConfig getMediaServerConfig() { 66 public MediaServerConfig getMediaServerConfig() {
  67 + JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig();
62 MediaServerConfig mediaServerConfig = null; 68 MediaServerConfig mediaServerConfig = null;
63 - OkHttpClient client = new OkHttpClient();  
64 - String url = String.format("http://%s:%s/index/api/getServerConfig?secret=%s", mediaIp, mediaPort, mediaSecret);  
65 - //创建一个Request  
66 - Request request = new Request.Builder()  
67 - .get()  
68 - .url(url)  
69 - .build();  
70 - //通过client发起请求  
71 - final Call call = client.newCall(request);  
72 - //执行同步请求,获取Response对象  
73 - Response response = null;  
74 - try {  
75 - response = call.execute();  
76 - if (response.isSuccessful()) {  
77 - String responseStr = response.body().string();  
78 - if (responseStr != null) {  
79 - JSONObject responseJSON = JSON.parseObject(responseStr);  
80 - JSONArray data = responseJSON.getJSONArray("data");  
81 - if (data != null && data.size() > 0) {  
82 - mediaServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), MediaServerConfig.class);  
83 - mediaServerConfig.setLocalIP(mediaIp);  
84 - }  
85 - }  
86 - }else {  
87 - logger.error("getMediaServerConfig失败, 1s后重试"); 69 + if (responseJSON != null) {
  70 + JSONArray data = responseJSON.getJSONArray("data");
  71 + if (data != null && data.size() > 0) {
  72 + mediaServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), MediaServerConfig.class);
  73 + mediaServerConfig.setLocalIP(mediaIp);
  74 + }
  75 + } else {
  76 + logger.error("getMediaServerConfig失败, 1s后重试");
  77 + try {
88 Thread.sleep(1000); 78 Thread.sleep(1000);
89 - getMediaServerConfig(); 79 + } catch (InterruptedException e) {
  80 + e.printStackTrace();
90 } 81 }
91 - } catch (IOException e) {  
92 - e.printStackTrace();  
93 - } catch (InterruptedException e) {  
94 - e.printStackTrace(); 82 + getMediaServerConfig();
95 } 83 }
96 -  
97 return mediaServerConfig; 84 return mediaServerConfig;
98 } 85 }
99 86
@@ -102,51 +89,30 @@ public class ZLMRunner implements CommandLineRunner { @@ -102,51 +89,30 @@ public class ZLMRunner implements CommandLineRunner {
102 if (mediaIp.equals(sipIP)) { 89 if (mediaIp.equals(sipIP)) {
103 hookIP = "127.0.0.1"; 90 hookIP = "127.0.0.1";
104 } 91 }
105 - OkHttpClient client = new OkHttpClient();  
106 - String url = String.format("http://%s:%s/index/api/setServerConfig", mediaIp, mediaPort);  
107 - String hookPrex = String.format("http://%s:%s/index/hook", hookIP, serverPort);  
108 92
109 - RequestBody body = new FormBody.Builder()  
110 - .add("secret",mediaSecret)  
111 - .add("hook.enable","1")  
112 - .add("hook.on_flow_report","")  
113 - .add("hook.on_http_access","")  
114 - .add("hook.on_publish",String.format("%s/on_publish", hookPrex))  
115 - .add("hook.on_record_mp4","")  
116 - .add("hook.on_record_ts","")  
117 - .add("hook.on_rtsp_auth","")  
118 - .add("hook.on_rtsp_realm","")  
119 - .add("hook.on_server_started",String.format("%s/on_server_started", hookPrex))  
120 - .add("hook.on_shell_login",String.format("%s/on_shell_login", hookPrex))  
121 - .add("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex))  
122 - .add("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex))  
123 - .add("hook.timeoutSec","20")  
124 - .build();  
125 -  
126 - Request request = new Request.Builder()  
127 - .post(body)  
128 - .url(url)  
129 - .build();  
130 - client.newCall(request).enqueue(new Callback() {  
131 - @Override  
132 - public void onFailure(Call call, IOException e) {  
133 - logger.error("saveZLMConfig ",e);  
134 - }  
135 - @Override  
136 - public void onResponse(Call call, Response response) throws IOException {  
137 - if (response.isSuccessful()) {  
138 - String responseStr = response.body().string();  
139 - if (responseStr != null) {  
140 - JSONObject responseJSON = JSON.parseObject(responseStr);  
141 - if (responseJSON.getInteger("code") == 0) {  
142 - logger.info("设置zlm成功");  
143 - }else {  
144 - logger.info("设置zlm失败: " + responseJSON.getString("msg"));  
145 - }  
146 - }  
147 - }  
148 -  
149 - }  
150 - }); 93 + String hookPrex = String.format("http://%s:%s/index/hook", hookIP, serverPort);
  94 + Map<String, Object> param = new HashMap<>();
  95 + param.put("secret",mediaSecret);
  96 + param.put("hook.enable","1");
  97 + param.put("hook.on_flow_report","");
  98 + param.put("hook.on_http_access","");
  99 + param.put("hook.on_publish",String.format("%s/on_publish", hookPrex));
  100 + param.put("hook.on_record_mp4","");
  101 + param.put("hook.on_record_ts","");
  102 + param.put("hook.on_rtsp_auth","");
  103 + param.put("hook.on_rtsp_realm","");
  104 + param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrex));
  105 + param.put("hook.on_shell_login",String.format("%s/on_shell_login", hookPrex));
  106 + param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));
  107 + param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));
  108 + param.put("hook.timeoutSec","20");
  109 +
  110 + JSONObject responseJSON = zlmresTfulUtils.setServerConfig(param);
  111 +
  112 + if (responseJSON != null && responseJSON.getInteger("code") == 0) {
  113 + logger.info("设置zlm成功");
  114 + }else {
  115 + logger.info("设置zlm失败: " + responseJSON.getString("msg"));
  116 + }
151 } 117 }
152 } 118 }
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
1 package com.genersoft.iot.vmp.vmanager.play; 1 package com.genersoft.iot.vmp.vmanager.play;
2 2
3 import com.alibaba.fastjson.JSON; 3 import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONArray;
4 import com.genersoft.iot.vmp.common.StreamInfo; 5 import com.genersoft.iot.vmp.common.StreamInfo;
  6 +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
5 import org.slf4j.Logger; 7 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 8 import org.slf4j.LoggerFactory;
7 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.beans.factory.annotation.Autowired;
@@ -31,6 +33,9 @@ public class PlayController { @@ -31,6 +33,9 @@ public class PlayController {
31 33
32 @Autowired 34 @Autowired
33 private IVideoManagerStorager storager; 35 private IVideoManagerStorager storager;
  36 +
  37 + @Autowired
  38 + private ZLMRESTfulUtils zlmresTfulUtils;
34 39
35 @GetMapping("/play/{deviceId}/{channelId}") 40 @GetMapping("/play/{deviceId}/{channelId}")
36 public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){ 41 public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){
@@ -38,17 +43,44 @@ public class PlayController { @@ -38,17 +43,44 @@ public class PlayController {
38 Device device = storager.queryVideoDevice(deviceId); 43 Device device = storager.queryVideoDevice(deviceId);
39 StreamInfo streamInfo = cmder.playStreamCmd(device, channelId); 44 StreamInfo streamInfo = cmder.playStreamCmd(device, channelId);
40 // 等待推流, TODO 默认超时15s 45 // 等待推流, TODO 默认超时15s
41 - 46 + boolean lockFlag = true;
42 long startTime = System.currentTimeMillis(); 47 long startTime = System.currentTimeMillis();
43 - while (storager.queryPlay(streamInfo) == null || storager.queryPlay(streamInfo).getFlv() == null) { 48 + String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
  49 +
  50 + // 判断推流是否存在
  51 + while (lockFlag) {
44 try { 52 try {
45 - if (System.currentTimeMillis() - startTime > 15 * 1000) 53 + if (System.currentTimeMillis() - startTime > 15 * 1000) {
  54 + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
  55 + if (rtpInfo == null){
  56 + continue;
  57 + }else {
  58 + lockFlag = false;
  59 + streamInfo = storager.queryPlay(streamInfo);
  60 + // 获取媒体信息
  61 + JSONObject mediaList = zlmresTfulUtils.getMediaList("rtp", "rtmp");
  62 + if (mediaList.getInteger("code") == 0) {
  63 + JSONArray data = mediaList.getJSONArray("data");
  64 + if (data!= null) {
  65 + for (Object datum : data) {
  66 + JSONObject media = (JSONObject)datum;
  67 + if (streamId.equals(media.getString("stream"))) {
  68 + streamInfo.setTracks(media.getJSONArray("tracks"));
  69 + storager.startPlay(streamInfo);
  70 + }
  71 + }
  72 + }
  73 + }
  74 + };
  75 +
  76 + }
  77 +
46 Thread.sleep(200); 78 Thread.sleep(200);
47 } catch (InterruptedException e) { 79 } catch (InterruptedException e) {
48 e.printStackTrace(); 80 e.printStackTrace();
49 } 81 }
50 } 82 }
51 - streamInfo = storager.queryPlay(streamInfo); 83 +
52 if (logger.isDebugEnabled()) { 84 if (logger.isDebugEnabled()) {
53 logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId)); 85 logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId));
54 logger.debug("设备预览 API调用,ssrc:"+streamInfo.getSsrc()+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(streamInfo.getSsrc()))); 86 logger.debug("设备预览 API调用,ssrc:"+streamInfo.getSsrc()+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(streamInfo.getSsrc())));
web_src/src/components/gb28181/devicePlayer.vue
@@ -124,6 +124,18 @@ @@ -124,6 +124,18 @@
124 play: function(streamInfo, deviceId, channelId, hasAudio) { 124 play: function(streamInfo, deviceId, channelId, hasAudio) {
125 console.log(hasAudio); 125 console.log(hasAudio);
126 this.hasaudio = hasAudio; 126 this.hasaudio = hasAudio;
  127 + // 根据媒体流信息二次判断
  128 + if( this.hasaudio && !!streamInfo.tracks && streamInfo.tracks.length > 0) {
  129 + var realHasAudio = false;
  130 + for (let i = 0; i < streamInfo.tracks; i++) {
  131 + if (streamInfo.tracks[i].codec_type == 1) { // 判断为音频
  132 + realHasAudio = true;
  133 + }
  134 + }
  135 + this.hasaudio = realHasAudio && this.hasaudio;
  136 + }
  137 + console.log("111")
  138 + console.log(this.hasaudio)
127 this.ssrc = streamInfo.ssrc; 139 this.ssrc = streamInfo.ssrc;
128 this.deviceId = deviceId; 140 this.deviceId = deviceId;
129 this.channelId = channelId; 141 this.channelId = channelId;