吉安感知网项目-前端
shuishen
2026-02-10 c10a91f2d151ee9da11ff505902f22b0a03e0dd1
applications/drone-command/src/views/audioCall.vue
@@ -36,7 +36,7 @@
import { ref, computed, onBeforeUnmount } from 'vue'
/** ✅ 你的 WS 地址前缀(后面拼 userId) */
const WS_BASE = 'wss://wrj.shuixiongit.com/ws/chat?userId='
const WS_BASE = 'wss://域名/ws/chat?userId='
const uid = ref('2')
const peerUid = ref('3')
@@ -64,13 +64,11 @@
   const s = String(seconds.value % 60).padStart(2, '0')
   return `${m}:${s}`
})
function startTimer() {
   stopTimer()
   seconds.value = 0
   timer = setInterval(() => seconds.value++, 1000)
}
function stopTimer() {
   if (timer) clearInterval(timer)
   timer = null
@@ -78,7 +76,6 @@
// 心跳
let pingTimer = null
function startPing() {
   stopPing()
   // 每 25 秒发一次 ping(你后端有 PING/PONG)
@@ -86,7 +83,6 @@
      if (connected.value) send('ping', 'system', null)
   }, 25000)
}
function stopPing() {
   if (pingTimer) clearInterval(pingTimer)
   pingTimer = null
@@ -130,13 +126,13 @@
      }
   }
   // 步骤7 接收音频流并且播放
   pc.ontrack = (e) => {
      log('✅ 收到远端音频流')
      const stream = e.streams[0]
      if (remoteAudio.value) {
         remoteAudio.value.srcObject = stream
         remoteAudio.value.play().catch(() => {
         })
         remoteAudio.value.play().catch(() => {})
      }
   }
@@ -172,6 +168,7 @@
      pc.getSenders().map(s => (s.track ? s.track.id : null)).filter(Boolean)
   )
   // 步骤6 发送音频流
   stream.getTracks().forEach(track => {
      if (!existingTrackIds.has(track.id)) {
         pc.addTrack(track, stream)
@@ -184,6 +181,7 @@
   return stream
}
// 步骤5
async function flushCandidates() {
   if (!pc || !pc.remoteDescription) return
   while (pendingCandidates.length) {
@@ -240,6 +238,7 @@
      return
   }
   // 步骤2
   if (t === 'offer') {
      // 被叫收到 offer:只有点击接听后才真正应答(你要求“先点接听”)
      offeredByPeer = true
@@ -259,10 +258,12 @@
      return
   }
   // 步骤3
   if (t === 'answer') {
      log('✅ 收到 answer,通话建立')
      if (!pc) createPC()
      await pc.setRemoteDescription(new RTCSessionDescription(msg.payload?.sdp))
      // 步骤4
      await flushCandidates()
      state.value = 'in-call'
@@ -373,6 +374,7 @@
   // ✅ 不会重复 addTrack
   await ensureLocalTracksAdded()
   // 步骤1
   const offer = await pc.createOffer()
   await pc.setLocalDescription(offer)
@@ -380,6 +382,7 @@
   log('➡️ 已发送 offer 给', peerUid.value)
}
// 步骤2
async function answerOffer(offerSdp, from) {
   if (!offerSdp) {
      log('❌ offer sdp 为空,无法接听')
@@ -411,8 +414,7 @@
function cleanup(sendToPeer) {
   try {
      if (sendToPeer) send('hangup', peerUid.value, null)
   } catch {
   }
   } catch {}
   stopTimer()
@@ -442,4 +444,3 @@
   if (ws) ws.close()
})
</script>