浏览代码

fix:
1. 修复语音对讲无法找到zlm的返回
add:
1. zlm 新增axios 请求失败事件
2. webrtc 相关异常事件处理

kindring 2 年之前
父节点
当前提交
5918e7d260

+ 1 - 1
src/main/resources/application.yml

@@ -34,7 +34,7 @@ spring:
         driver-class-name: com.mysql.cj.jdbc.Driver
 #        url: jdbc:mysql://kindring.cn:6543/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
 #        url: jdbc:mysql://192.168.1.203:6543/gb_db?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
-        url: jdbc:mysql://127.0.0.1:3306/gb_db?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
+        url: jdbc:mysql://127.0.0.1:3306/gb_db?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&allowPublicKeyRetrieval=true
 
         #        username: gpsuser
 #        password: tianhui2013

+ 3 - 0
web_src/src/assets/ZLMRTCClient.js

@@ -8248,6 +8248,9 @@ let ZLMRTCClient = (function (exports) {
       return _sdp;
     }
 
+    loadSdp(sdp){
+
+    }
 	}
 
 	const quickScan = [{

+ 64 - 20
web_src/src/components/common/microphone.vue

@@ -1,8 +1,23 @@
 <template>
   <div :class="sizeClass" >
-    <div :class="`mic ${!isRecording?'mic-off':'mic-on'}`" @mousedown="mouseDownHandle" @mouseup="mouseUpHandle" :title="isRecording?'录音中...':'开始录音'">
-      <i :class="`el-icon-${isRecording?'microphone':'turn-off-microphone'}`"></i>
-    </div>
+    <el-tooltip class="item" effect="dark"
+                :content="isWaiting?'启动语音对讲中':isRecording?'录音中...':'点击开始录音'"
+                placement="top-start">
+      <div v-if="isWaiting" class="mic" >
+        <i class="el-icon-loading"></i>
+      </div>
+      <div v-else="!isWaiting" :class="`mic ${!isRecording?'mic-off':'mic-on'}`" @mousedown="mouseDownHandle" @mouseup="mouseUpHandle">
+        <i :class="`el-icon-${isRecording?'microphone':'turn-off-microphone'}`"></i>
+      </div>
+    </el-tooltip>
+    <el-tooltip v-if="!isWaiting && isRecording" class="item" effect="dark"
+                content="停止语音对讲"
+    >
+      <div class="mic mic-t2">
+<!--        停止按钮 -->
+        <i class="el-icon-close" @click="stopBroadcast"></i>
+      </div>
+    </el-tooltip>
   </div>
 </template>
 
@@ -31,6 +46,7 @@ export default {
       player: null,
       mediaStream: null,
       audioConnected: false,
+      isWaiting: false,
     }
   },
   computed: {
@@ -62,6 +78,7 @@ export default {
       this.mediaStream = null;
       this.audioConnected = false;
       this.isRecording = false;
+      this.isWaiting = false;
       // this.getWebrtcAddress();
     },
     closeAudioApplications(){
@@ -87,8 +104,12 @@ export default {
         }
       }else{
         // 开始获取设备端的invite信息
-        this.startBroadcast();
-
+        if (!this.isWaiting){
+          this.isWaiting = true;
+          this.startBroadcast();
+        }else{
+          this.$message.warning("正在开启语音对讲中...")
+        }
       }
     },
     // 录音按钮抬起
@@ -108,7 +129,7 @@ export default {
       let err, stream, res;
       if (!this.mediaStream) {
         if(!this.pushConfig){
-          return this.audioStartFailed(null,"无法获取到推流配置")
+          return this.audioStartFailed(null,"无法获取到推流配置",true)
         }
         // webrtc 请求推流 url
         let zlmSdpUrl = this.pushConfig.webRtcPushUrl;
@@ -124,10 +145,11 @@ export default {
         }
         console.log("启用音频编码")
         console.log(audioEncodeArr)
+        let enableDebug = this.enableDebug;
         let player = new ZLMRTCClient.Endpoint(
           {
             // element: document.getElementById('video'),// video 标签
-            debug: true,// 是否打印日志
+            debug: enableDebug,// 是否打印日志
             zlmsdpUrl: zlmSdpUrl,//流地址
             simulcast: false,
             useCamera: false,
@@ -142,9 +164,16 @@ export default {
         );
         this.player = player;
         // console.log(player);
-        player.on('error', async (err) => {
+        player.on(ZLMRTCClient.Events.CONNECT_FAIL, async (err) => {
           console.log('error', err);
-          this.audioStartFailed(err,`与设备交互错误信息失败${err.message}`)
+          this.$notify.error({
+            title: 'ZLM连接失败',
+            dangerouslyUseHTMLString: true,
+            message: `<span>连接zlm服务失败${err.message}</span> <br/>
+                        <a href="${zlmSdpUrl}" target="_blank"><span>手动访问</span></a>`,
+            duration: 0
+          });
+          this.audioStartFailed(err,`无法连接zlm服务 ${err.message}` , false);
           this.mediaStream = null;
           return player.close();
         });
@@ -153,12 +182,13 @@ export default {
           if (state === 'connected') {
             // 等待1秒
             await sleep(2500);
+            console.log('----------*********==>', state);
             // todo 分析sdp,看最终使用的是什么音频协议,传输给wvp下发invite 与创建zlm转流服务
             [err, res] = await handle(this.sendBroaderCast(this.pushConfig.stream,this.pushConfig.app));
             let response = res.data;
             if (err|| response.code!==0 ) {
               // console.log(err);
-              this.audioStartFailed(err?err:response,`与设备交互错误信息失败${err?err.message:response.msg}`)
+              this.audioStartFailed(err?err:response,`与设备交互错误信息失败${err?err.message:response.msg}`,true)
               this.mediaStream = null;
               return player.close();
             }
@@ -166,27 +196,30 @@ export default {
             this.audioConnected = true;
             this.isRecording = true;
             console.log('创建音视频通道成功');
+            this.isWaiting = false;
           } else if(state === 'close' || state === "disconnected"){
             // this.$message.warning("webrtc连接断开");
-            this.audioStartFailed(null,`webrtc连接断开`);
+            this.audioStartFailed(null,`webrtc连接断开`,true);
             this.audioConnected = false;
           }
         });
         player.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,  (e)=> {
-          this.audioStartFailed(e,"ICE 协商出错");
+          this.audioStartFailed(e,"ICE 协商出错",true);
         });
         // player.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS, function (e) {//获取到了远端流,可以播放
         //   console.log('播放成功', e.streams)
         // });
         player.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,  (e)=> {
-          this.audioStartFailed(e,"offer anwser 交换失败");
+          this.audioStartFailed(e,`offerAnwser 交换失败 请检查zlm 配置`,true);
         });
         player.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM,  (s)=> {
-          console.log("获取到了本地流");
+          if(this.enableDebug){
+            console.log("获取到了本地流");
+          }
           this.mediaStream = s;
         });
         player.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED,  (s)=> {
-          this.audioStartFailed(s,"获取音频信息失败,请检查是否有麦克风");
+          this.audioStartFailed(s,"获取音频信息失败,请检查是否有麦克风",true);
         });
       }
       this.isRecording = true;
@@ -194,13 +227,21 @@ export default {
     async stopRecordAudio() {
       //  todo 停止录音
     },
-    audioStartFailed(e,msg){
+    audioStartFailed(e, msg, failTip = false){
+      this.isWaiting = false;
       if(this.enableDebug){
         console.log(msg);
         console.log(e);
         console.log("-------");
       }
-      this.$message.error(msg);
+      console.log(failTip);
+      if(failTip){
+        this.$notify.error({
+          title: '语音对讲开启失败',
+          message: msg,
+          duration: 4500
+        });
+      }
       this.initAudioApplications();
     },
     async startBroadcast(){
@@ -213,7 +254,7 @@ export default {
       if (err){
         console.log(err)
         this.isLoadAddr = false;
-        this.audioStartFailed(err,err.message);
+        this.audioStartFailed(err,err.message,true);
         return 0;
       }
       console.log(res);
@@ -222,7 +263,7 @@ export default {
         this.pushConfig = data.data;
         await this.startRecordAudio();
       }else{
-        this.audioStartFailed(data,data.msg);
+        this.audioStartFailed(data,data.msg,true);
         console.log(res);
         console.error(data.msg);
       }
@@ -258,6 +299,7 @@ export default {
   justify-content: center;
   align-items: center;
   cursor:pointer;
+  flex-direction: column;
 }
 .microPhone .mic{
   width: 100%;
@@ -266,7 +308,9 @@ export default {
   justify-content: center;
   align-items: center;
 }
-
+.mic-t2{
+  margin-top: 10px;
+}
 .mic-on{
   color:red;
 }

+ 13 - 3
web_src/src/components/dialog/customPlayer.vue

@@ -2,7 +2,7 @@
   <div id="customPlayer" v-loading="isLoging">
     <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" @close="closeHandle()">
       <div style="width: 100%; height: 100%">
-        <rtc-player ref="webRTC" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player>
+        <rtc-player ref="webRTC" @eventCallback="playEventHandle" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player>
       </div>
       <div id="shared" style="text-align: right; margin-top: 1rem;">
         <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick" >
@@ -113,9 +113,17 @@ export default {
       recordStartTime: 0,
       showTimeText: "00:00:00",
       streamInfo: null,
+      enableDebug: true,
     };
   },
   methods: {
+    playEventHandle(type,message){
+      if(this.enableDebug){
+        console.log('playEventHandle');
+        console.log(type,message);
+      }
+    },
+
     tabHandleClick: function(tab, event) {
       console.log(tab)
       var that = this;
@@ -138,7 +146,9 @@ export default {
               type: 'warning'
             });
           }
-        }).catch(function (e) {});
+        }).catch(function (e) {
+
+        });
       }
     },
     videoError: function (e) {
@@ -158,7 +168,7 @@ export default {
     playFromStreamInfo: function (realHasAudio, streamInfo) {
       this.showVideoDialog = true;
       this.hasaudio = realHasAudio && this.hasaudio;
-      this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo))
+      this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo),this.enableDebug)
     },
     openDialog: function (tab, deviceId, channelId, param) {
       if (this.showVideoDialog) {

+ 29 - 14
web_src/src/components/dialog/rtcPlayer.vue

@@ -7,12 +7,16 @@
 </template>
 
 <script>
+import ZLMRTCClient from "@/assets/ZLMRTCClient";
+import {webrtcEvent} from "@/map/eventMap";
+
 let webrtcPlayer = null;
 export default {
     name: 'rtcPlayer',
     data() {
         return {
-            timer: null
+          timer: null,
+          enableDebug: false,
         };
     },
     props: ['videoUrl', 'error', 'hasaudio'],
@@ -34,33 +38,41 @@ export default {
         immediate:true
     },
     methods: {
-        play: function (url) {
-          console.log(url);
+        play: function (url,enableDebug = false) {
+          this.enableDebug = enableDebug;
+          if(enableDebug){
+            console.log(url);
+          }
+
             webrtcPlayer = new ZLMRTCClient.Endpoint({
                 element: document.getElementById('webRtcPlayerBox'),// video 标签
-                debug: true,// 是否打印日志
+                debug: enableDebug,// 是否打印日志
                 zlmsdpUrl: url,//流地址
                 simulecast: false,
                 useCamera: false,
                 audioEnable: false,
                 videoEnable: false,
                 recvOnly: true,
-            })
+            });
+            webrtcPlayer.on(ZLMRTCClient.Events.CONNECT_FAIL, (err) => {
+              if(enableDebug){console.log('error', err);}
+                this.eventCallback(webrtcEvent.apiFail, err)
+            });
             webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,(e)=>{// ICE 协商出错
-                console.error('ICE 协商出错')
-                this.eventcallbacK("ICE ERROR", "ICE 协商出错")
+                if(enableDebug){console.error('ICE 协商出错')}
+                this.eventCallback("ICE ERROR", "ICE 协商出错")
             });
 
             webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS,(e)=>{//获取到了远端流,可以播放
-                console.log('播放成功',e.streams)
-                this.eventcallbacK("playing", "播放成功")
+                if(enableDebug){console.log('播放成功',e.streams)}
+                this.eventCallback("playing", "播放成功")
             });
 
             webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,(e)=>{// offer anwser 交换失败
-                console.error('offer anwser 交换失败',e)
-                this.eventcallbacK("OFFER ANSWER ERROR ", "offer anwser 交换失败")
+                if(enableDebug){console.error('offer anwser 交换失败',e)}
+                this.eventCallback("OFFER ANSWER ERROR ", "offer anwser 交换失败")
                 if (e.code ==-400 && e.msg=="流不存在"){
-                    console.log("流不存在")
+                    if(enableDebug){console.log("流不存在")}
                     this.timer = setTimeout(()=>{
                         this.webrtcPlayer.close();
                         this.play(url)
@@ -72,7 +84,7 @@ export default {
             webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM,(s)=>{// 获取到了本地流
 
                 // document.getElementById('selfVideo').srcObject=s;
-                this.eventcallbacK("LOCAL STREAM", "获取到了本地流")
+                this.eventCallback("LOCAL STREAM", "获取到了本地流")
             });
 
         },
@@ -83,10 +95,13 @@ export default {
             }
 
         },
-        eventcallbacK: function(type, message) {
+        eventCallback: function(type, message) {
+          if(this.enableDebug) {
             console.log("player 事件回调")
             console.log(type)
             console.log(message)
+          }
+          this.$emit("eventCallback", type, message);
         }
     },
     destroyed() {

+ 22 - 0
web_src/src/map/eventMap.js

@@ -0,0 +1,22 @@
+export const webrtcEvent = {
+    icecandidate: {
+        title: "webrtc候选",
+        icon: 'connect',
+        code: 'icecandidate',
+    },
+    played: {
+      title: "播放成功",
+      icon: 'played',
+      code: 'onPlayed',
+    },
+    apiFail: {
+      title: "api调用失败",
+      icon: 'fail',
+      code: 'apiFail',
+    },
+    notFindStream: {
+      title: "未找到流",
+      icon: '404',
+      code: 'notFindStream',
+    }
+}