| | |
| | | <template> |
| | | <div class="mt20 flex-column flex-justify-start flex-align-center"> |
| | | <div id="player" style="width: 720px; height: 420px; border: 1px solid"></div> |
| | | <p class="fz24">Live streaming source selection</p> |
| | | <p class="fz24">直播源选择</p> |
| | | <div class="flex-row flex-justify-center flex-align-center mt10"> |
| | | <template v-if="livePara.liveState && dronePara.isDockLive"> |
| | | <span class="mr10">Lens:</span> |
| | |
| | | <template v-else> |
| | | <a-select |
| | | style="width:150px" |
| | | placeholder="Select Drone" |
| | | placeholder="选择设备" |
| | | v-model:value="dronePara.droneSelected" |
| | | > |
| | | <a-select-option |
| | |
| | | <a-select |
| | | class="ml10" |
| | | style="width:150px" |
| | | placeholder="Select Camera" |
| | | placeholder="选择相机" |
| | | v-model:value="dronePara.cameraSelected" |
| | | > |
| | | <a-select-option |
| | |
| | | <a-select |
| | | class="ml10" |
| | | style="width:150px" |
| | | placeholder="Select Clarity" |
| | | placeholder="选择画质" |
| | | @select="onClaritySelect" |
| | | > |
| | | <a-select-option |
| | |
| | | </a-select> |
| | | </div> |
| | | <p class="fz16 mt10"> |
| | | Note: Obtain The Following Parameters From https://console.agora.io |
| | | <!-- 注意:从中获取以下参数https://console.agora.io --> |
| | | </p> |
| | | <div class="flex-row flex-justify-center flex-align-center"> |
| | | <span class="mr10">AppId:</span> |
| | |
| | | class="ml10" |
| | | v-model:value="agoraPara.token" |
| | | placeholder="Token" |
| | | @change="encodeToken" |
| | | ></a-input> |
| | | <span class="ml10">Channel:</span> |
| | | <a-input |
| | |
| | | ></a-input> |
| | | </div> |
| | | <div class="mt20 flex-row flex-justify-center flex-align-center"> |
| | | <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 v-if="livePara.liveState && dronePara.isDockLive" type="primary" large @click="onSwitch">切换镜头</a-button> |
| | | <a-button v-else type="primary" large @click="onStart">播放</a-button> |
| | | <a-button class="ml20" type="primary" large @click="onStop" |
| | | >Stop</a-button |
| | | >暂停</a-button |
| | | > |
| | | <a-button class="ml20" type="primary" large @click="onUpdateQuality" |
| | | >Update Clarity</a-button |
| | | >更新画质</a-button |
| | | > |
| | | <a-button v-if="!livePara.liveState || !dronePara.isDockLive" class="ml20" type="primary" large @click="onRefresh" |
| | | >Refresh Live Capacity</a-button |
| | | >刷新实时容量</a-button |
| | | > |
| | | </div> |
| | | </div> |
| | |
| | | liveState: false |
| | | }) |
| | | const nonSwitchable = 'normal' |
| | | |
| | | const onRefresh = async () => { |
| | | dronePara.droneList = [] |
| | | dronePara.cameraList = [] |
| | |
| | | |
| | | onMounted(() => { |
| | | onRefresh() |
| | | agoraPara.token = encodeURIComponent(agoraPara.token) |
| | | 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') |
| | | message.info('用户[' + user.uid + '] 加入') |
| | | }) |
| | | agoraClient.on('user-published', async (user: IAgoraRTCRemoteUser, mediaType: 'audio' | 'video') => { |
| | | await agoraClient.subscribe(user, mediaType) |
| | |
| | | // 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 = user.uid.toString() |
| | | 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') |
| | | message.info('取消发布') |
| | | }) |
| | | 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 encodeToken = (e: any) => { |
| | | agoraPara.token = encodeURIComponent(agoraPara.token) |
| | | } |
| | | const onStart = async () => { |
| | | const that = this |
| | |
| | | } |
| | | 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 + |
| | |
| | | '&sn=' + |
| | | dronePara.droneSelected + |
| | | '&token=' + |
| | | agoraPara.token + |
| | | encodeURIComponent(agoraPara.token) + |
| | | '&uid=' + |
| | | agoraPara.uid |
| | | |
| | |
| | | }) |
| | | } |
| | | 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 + |
| | | '/' + |
| | |
| | | }).then(res => { |
| | | if (res.code === 0) { |
| | | message.success(res.message) |
| | | livePara.liveState = false |
| | | dronePara.lensSelected = '' |
| | | console.log('stop play livestream') |
| | | } |
| | | livePara.liveState = false |
| | | dronePara.lensSelected = '' |
| | | console.log('stop play livestream') |
| | | }) |
| | | } |
| | | const onDroneSelect = (val: SelectOption) => { |
| | |
| | | dronePara.videoSelected = firstVideo.value |
| | | dronePara.lensList = firstVideo.more |
| | | dronePara.lensSelected = firstVideo.label |
| | | dronePara.isDockLive = dronePara.lensList.length > 0 |
| | | dronePara.isDockLive = dronePara.lensList?.length > 0 |
| | | } |
| | | const onVideoSelect = (val: SelectOption) => { |
| | | dronePara.videoSelected = val.value |
| | |
| | | } |
| | | const onUpdateQuality = () => { |
| | | if (!livePara.liveState) { |
| | | message.info('Please turn on the livestream first.') |
| | | message.info('请先打开直播') |
| | | return |
| | | } |
| | | setLivestreamQuality({ |
| | |
| | | video_quality: dronePara.claritySelected |
| | | }).then(res => { |
| | | if (res.code === 0) { |
| | | message.success('Set the clarity to ' + clarityList[dronePara.claritySelected].label) |
| | | message.success('将清晰度设置为 ' + clarityList[dronePara.claritySelected].label) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | 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) |
| | | message.info('当前 ' + nonSwitchable + ' 镜头无法切换,请选择要切换的镜头', 8) |
| | | return |
| | | } |
| | | changeLivestreamLens({ |
| | |
| | | video_type: dronePara.lensSelected |
| | | }).then(res => { |
| | | if (res.code === 0) { |
| | | message.success('Switching live camera successfully.') |
| | | message.success('切换实时摄像头成功') |
| | | } |
| | | }) |
| | | } |