xieb
2023-09-13 3667807a7b7418efc090ee3fa6a6b734bc3080bf
src/components/livestream-agora.vue
@@ -3,15 +3,23 @@
    <div id="player" style="width: 720px; height: 420px; border: 1px solid"></div>
    <p class="fz24">Live streaming source selection</p>
    <div class="flex-row flex-justify-center flex-align-center mt10">
      <template v-if="livePara.liveState && dronePara.isDockLive">
        <span class="mr10">Lens:</span>
        <a-radio-group v-model:value="dronePara.lensSelected" button-style="solid">
          <a-radio-button v-for="lens in dronePara.lensList" :key="lens" :value="lens">{{lens}}</a-radio-button>
        </a-radio-group>
      </template>
      <template v-else>
      <a-select
        style="width:150px"
        placeholder="Select Drone"
        @select="onDroneSelect"
        v-model:value="dronePara.droneSelected"
      >
        <a-select-option
          v-for="item in dronePara.droneList"
          :key="item.value"
          :value="item.value"
          @click="onDroneSelect(item)"
          >{{ item.label }}</a-select-option
        >
      </a-select>
@@ -19,12 +27,13 @@
        class="ml10"
        style="width:150px"
        placeholder="Select Camera"
        @select="onCameraSelect"
        v-model:value="dronePara.cameraSelected"
      >
        <a-select-option
          v-for="item in dronePara.cameraList"
          :key="item.value"
          :value="item.value"
          @click="onCameraSelect(item)"
          >{{ item.label }}</a-select-option
        >
      </a-select>
@@ -35,13 +44,13 @@
        @select="onVideoSelect"
      >
        <a-select-option
          class="ml10"
          v-for="item in dronePara.videoList"
          :key="item.value"
          :value="item.value"
          >{{ item.label }}</a-select-option
        >
      </a-select> -->
      </template>
      <a-select
        class="ml10"
        style="width:150px"
@@ -60,12 +69,15 @@
      Note: Obtain The Following Parameters From https://console.agora.io
    </p>
    <div class="flex-row flex-justify-center flex-align-center">
      <span class="mr10">AppId:</span>
      <a-input v-model:value="agoraPara.appid" placeholder="APP ID"></a-input>
      <span class="ml10">Token:</span>
      <a-input
        class="ml10"
        v-model:value="agoraPara.token"
        placeholder="Token"
      ></a-input>
      <span class="ml10">Channel:</span>
      <a-input
        class="ml10"
        v-model:value="agoraPara.channel"
@@ -73,14 +85,15 @@
      ></a-input>
    </div>
    <div class="mt20 flex-row flex-justify-center flex-align-center">
      <a-button type="primary" large @click="onStart">Play</a-button>
      <a-button v-if="livePara.liveState && dronePara.isDockLive" type="primary" large @click="onSwitch">Switch Lens</a-button>
      <a-button v-else type="primary" large @click="onStart">Play</a-button>
      <a-button class="ml20" type="primary" large @click="onStop"
        >Stop</a-button
      >
      <a-button class="ml20" type="primary" large @click="onUpdateQuality"
        >Update Clarity</a-button
      >
      <a-button class="ml20" type="primary" large @click="onRefresh"
      <a-button v-if="!livePara.liveState || !dronePara.isDockLive" class="ml20" type="primary" large @click="onRefresh"
        >Refresh Live Capacity</a-button
      >
    </div>
@@ -91,8 +104,9 @@
import AgoraRTC, { IAgoraRTCClient, IAgoraRTCRemoteUser } from 'agora-rtc-sdk-ng'
import { message } from 'ant-design-vue'
import { onMounted, reactive } from 'vue'
import { uuidv4 } from '../utils/uuid'
import { CURRENT_CONFIG as config } from '/@/api/http/config'
import { getLiveCapacity, setLivestreamQuality, startLivestream, stopLivestream } from '/@/api/manage'
import { changeLivestreamLens, getLiveCapacity, setLivestreamQuality, startLivestream, stopLivestream } from '/@/api/manage'
import { getRoot } from '/@/root'
const root = getRoot()
@@ -120,6 +134,12 @@
  }
]
interface SelectOption {
  value: any,
  label: string,
  more?: any
}
let agoraClient = {} as IAgoraRTCClient
const agoraPara = reactive({
  appid: config.agoraAPPID,
@@ -130,13 +150,16 @@
})
const dronePara = reactive({
  livestreamSource: [],
  droneList: [] as any[],
  cameraList: [] as any[],
  videoList: [] as any[],
  droneSelected: '',
  cameraSelected: '',
  videoSelected: '',
  claritySelected: 0
  droneList: [] as SelectOption[],
  cameraList: [] as SelectOption[],
  videoList: [] as SelectOption[],
  droneSelected: undefined as string | undefined,
  cameraSelected: undefined as string | undefined,
  videoSelected: undefined as string | undefined,
  claritySelected: 0,
  lensList: [] as string[],
  lensSelected: undefined as string | undefined,
  isDockLive: false
})
const livePara = reactive({
  url: '',
@@ -144,14 +167,14 @@
  videoId: '',
  liveState: false
})
const nonSwitchable = 'normal'
const onRefresh = async () => {
  dronePara.droneList = []
  dronePara.cameraList = []
  dronePara.videoList = []
  dronePara.droneSelected = ''
  dronePara.cameraSelected = ''
  dronePara.videoSelected = ''
  dronePara.droneSelected = undefined
  dronePara.cameraSelected = undefined
  dronePara.videoSelected = undefined
  await getLiveCapacity({})
    .then(res => {
      if (res.code === 0) {
@@ -166,12 +189,13 @@
        if (dronePara.livestreamSource) {
          dronePara.livestreamSource.forEach((ele: any) => {
            dronePara.droneList.push({ label: ele.name + '-' + ele.sn, value: ele.sn })
            dronePara.droneList.push({ label: ele.name + '-' + ele.sn, value: ele.sn, more: ele.cameras_list })
          })
        }
      }
    })
    .catch(error => {
      message.error(error)
      console.error(error)
    })
}
@@ -179,6 +203,10 @@
onMounted(() => {
  onRefresh()
  agoraClient = AgoraRTC.createClient({ mode: 'live', codec: 'vp8' })
  agoraClient.setClientRole('audience', { level: 2 })
  if (agoraClient.connectionState === 'DISCONNECTED') {
    agoraClient.join(agoraPara.appid, agoraPara.channel, agoraPara.token)
  }
  // Subscribe when a remote user publishes a stream
  agoraClient.on('user-joined', async (user: IAgoraRTCRemoteUser) => {
    message.info('user[' + user.uid + '] join')
@@ -190,24 +218,24 @@
      // Get `RemoteVideoTrack` in the `user` object.
      const remoteVideoTrack = user.videoTrack!
      // Dynamically create a container in the form of a DIV element for playing the remote video track.
      const remotePlayerContainer: any = document.getElementById('player')
      // remotePlayerContainer.id = agoraPara.uid
      remoteVideoTrack.play(remotePlayerContainer)
      remoteVideoTrack.play(document.getElementById('player') as HTMLElement)
    }
  })
  agoraClient.on('user-unpublished', async (user: any) => {
    console.log('unpublish live:', user)
    message.info('unpublish live')
  })
  agoraClient.on('exception', async (e: any) => {
    console.log(e)
    message.error(e.msg)
  })
})
const handleError = (err: any) => {
  console.error(err)
}
const handleJoinChannel = (uid: any) => {
  agoraPara.uid = uid
}
const onStart = async () => {
  const that = this
  console.log(
@@ -222,25 +250,20 @@
  if (
    dronePara.droneSelected == null ||
    dronePara.cameraSelected == null ||
    dronePara.videoSelected == null ||
    dronePara.claritySelected == null
  ) {
    message.warn('waring: not select live para!!!')
    return
  }
  agoraClient.setClientRole('audience', { level: 1 })
  agoraClient.setClientRole('audience', { level: 2 })
  if (agoraClient.connectionState === 'DISCONNECTED') {
    agoraClient
      .join(agoraPara.appid, agoraPara.channel, agoraPara.token)
    await agoraClient.join(agoraPara.appid, agoraPara.channel, agoraPara.token)
  }
  livePara.videoId =
    dronePara.droneSelected +
    '/' +
    dronePara.cameraSelected +
    '/' +
    dronePara.videoSelected
    dronePara.cameraSelected + '/' + (dronePara.videoSelected || nonSwitchable + '-0')
  console.log(agoraPara)
  agoraPara.token = encodeURIComponent(agoraPara.token)
  livePara.url =
    'channel=' +
@@ -248,7 +271,7 @@
    '&sn=' +
    dronePara.droneSelected +
    '&token=' +
    agoraPara.token +
    encodeURIComponent(agoraPara.token) +
    '&uid=' +
    agoraPara.uid
@@ -259,6 +282,9 @@
    video_quality: dronePara.claritySelected
  })
    .then(res => {
      if (res.code !== 0) {
        return
      }
      livePara.liveState = true
    })
    .catch(err => {
@@ -266,65 +292,72 @@
    })
}
const onStop = async () => {
  if (
    dronePara.droneSelected == null ||
    dronePara.cameraSelected == null ||
    dronePara.claritySelected == null
  ) {
    message.warn('waring: not select live para!!!')
    return
  }
  livePara.videoId =
    dronePara.droneSelected +
    '/' +
    dronePara.cameraSelected +
    '/' +
    dronePara.videoSelected
    dronePara.cameraSelected + '/' + (dronePara.videoSelected || nonSwitchable + '-0')
  stopLivestream({
    video_id: livePara.videoId
  }).then(res => {
    if (res.code === 0) {
      message.success(res.message)
      livePara.liveState = false
      dronePara.lensSelected = ''
      console.log('stop play livestream')
    }
    livePara.liveState = false
    console.log('stop play livestream')
  })
}
const onDroneSelect = (val: any) => {
  dronePara.droneSelected = val
  if (dronePara.droneSelected) {
    const droneTemp = dronePara.livestreamSource
    dronePara.cameraList = []
const onDroneSelect = (val: SelectOption) => {
  dronePara.cameraList = []
  dronePara.videoList = []
  dronePara.lensList = []
    droneTemp.forEach((ele: any) => {
      const drone = ele
      if (drone.cameras_list && drone.sn === dronePara.droneSelected) {
        const cameraListTemp = drone.cameras_list
        cameraListTemp.forEach((ele: any) => {
          dronePara.cameraList.push({ label: ele.name, value: ele.index })
        })
      }
    })
  dronePara.cameraSelected = undefined
  dronePara.videoSelected = undefined
  dronePara.lensSelected = undefined
  dronePara.droneSelected = val.value
  if (!val.more) {
    return
  }
  val.more.forEach((ele: any) => {
    dronePara.cameraList.push({ label: ele.name, value: ele.index, more: ele.videos_list })
  })
}
const onCameraSelect = (val: any) => {
  dronePara.cameraSelected = val
const onCameraSelect = (val: SelectOption) => {
  dronePara.cameraSelected = val.value
  dronePara.videoSelected = undefined
  dronePara.lensSelected = undefined
  dronePara.videoList = []
  dronePara.lensList = []
  if (!val.more) {
    return
  }
  if (dronePara.cameraSelected) {
    const droneTemp = dronePara.livestreamSource
    droneTemp.forEach((ele: any) => {
      const drone = ele
      if (drone.sn === dronePara.droneSelected) {
        const cameraListTemp = drone.cameras_list
        cameraListTemp.forEach((ele: any) => {
          const camera = ele
          if (camera.index === dronePara.cameraSelected) {
            const videoListTemp = camera.videos_list
            dronePara.videoList = []
            videoListTemp.forEach((ele: any) => {
              dronePara.videoList.push({ label: ele.type, value: ele.index })
            })
            dronePara.videoSelected = dronePara.videoList[0]?.value
          }
        })
      }
    })
  val.more.forEach((ele: any) => {
    dronePara.videoList.push({ label: ele.type, value: ele.index, more: ele.switch_video_types })
  })
  if (dronePara.videoList.length === 0) {
    return
  }
  const firstVideo: SelectOption = dronePara.videoList[0]
  dronePara.videoSelected = firstVideo.value
  dronePara.lensList = firstVideo.more
  dronePara.lensSelected = firstVideo.label
  dronePara.isDockLive = dronePara.lensList?.length > 0
}
const onVideoSelect = (val: any) => {
  dronePara.videoSelected = val
const onVideoSelect = (val: SelectOption) => {
  dronePara.videoSelected = val.value
  dronePara.lensList = val.more
  dronePara.lensSelected = val.label
}
const onClaritySelect = (val: any) => {
  dronePara.claritySelected = val
@@ -343,6 +376,21 @@
    }
  })
}
const onSwitch = () => {
  if (dronePara.lensSelected === undefined || dronePara.lensSelected === nonSwitchable) {
    message.info('The ' + nonSwitchable + ' lens cannot be switched, please select the lens to be switched.', 8)
    return
  }
  changeLivestreamLens({
    video_id: livePara.videoId,
    video_type: dronePara.lensSelected
  }).then(res => {
    if (res.code === 0) {
      message.success('Switching live camera successfully.')
    }
  })
}
</script>
<style lang="scss" scoped>