From c00578bae75515e52e1f03ba6bb80a91c7dd56bf Mon Sep 17 00:00:00 2001
From: zhangtao <1176193409@qq.com>
Date: Fri, 21 Oct 2022 17:02:40 +0800
Subject: [PATCH] add leave
---
src/views/home/index.vue | 208 ++++++++++++++++++++++++++++++++-------
1 file changed, 170 insertions(+), 38 deletions(-)
diff --git a/src/views/home/index.vue b/src/views/home/index.vue
index 005a322..b100500 100644
--- a/src/views/home/index.vue
+++ b/src/views/home/index.vue
@@ -3,6 +3,17 @@
+
+
+
+
+
+ 退出会议
@@ -34,9 +47,10 @@
import TRTC from 'trtc-js-sdk'
import { useRoute } from 'vue-router'
import DeviceSelect from './components/Device.vue'
-import { reactive, toRefs, onMounted, watch } from 'vue'
+import { reactive, toRefs, onMounted, watch, nextTick } from 'vue'
import { VideocamOutline, VideocamOffOutline } from '@vicons/ionicons5'
import { AudioOutlined, AudioMutedOutlined } from '@vicons/antd'
+import { isUndef } from '@/utils/is.js'
// import { Screen, ScreenOff } from '@vicons/carbon'
export default {
name: 'HomePage',
@@ -55,14 +69,11 @@ export default {
sdkSecret: '9b5fc557f286d7e4d6eafd8023026da59f0674000f319754aa1ec4beefddcdd6',
userId: '',
roomId: null,
- isJoining: false,
- isJoined: false,
- isPublishing: false,
- isPublished: false,
secret: {
'haoran': 'eJwtzEELgjAYxvHvsqsh29ymCB28hIIElZR1G2y1ty2VJSVE3z1Tj8-vgf8HVeUhfGmPUkRDjFbTBqWbHq4wsZGtl83yPJWVXQcKpYRhHHMqGJkfPXTg9eicc4oxnrWHx9*EEFHECGVLBW5jWMn6HCRBW7njJd*WNgNrNrnbFXcZG356V94Vg7W12ydr9P0BbGAyOQ__',
'wanghaoran': 'eJwtzEELgjAcBfDvsnO4ubnFhA6ihwIhUqEOXhZO*6dNUalF9N0z9fh*7-E*KItT56l75CPqELSZMxTajFDCzC9lqptqe2XWdihq1XVQIN-1CNlyKjx3abTtoNeTc84pIWTRER5-E0IwVwq5bgeopnPPRDluaVPGTb1P3nd7CcPMHgJ2zbFJ5HCKrDkHxzLHMmX1Dn1-G3A0Zg__'
- }
+ },
+ remoteStreamList: []
})
const settings = reactive({
@@ -74,6 +85,15 @@ export default {
isMutedAudio: false // 是否关闭音频
})
+ const status = reactive({
+ isJoining: false,
+ isJoined: false,
+ isPublishing: false,
+ isUnPublishing: false,
+ isPublished: false,
+ isLeaving: false
+ })
+
const createMeetingRoom = async() => {
data.client = TRTC.createClient({
sdkAppId: data.sdkAppId, // 填写您申请的 sdkAppId
@@ -85,18 +105,18 @@ export default {
}
const joinMeetingRoom = async() => {
- if (data.isJoining || data.isJoined) {
+ if (status.isJoining || status.isJoined) {
return
}
- data.isJoining = true
+ status.isJoining = true
!data.client && await createMeetingRoom()
try {
await data.client.join({ roomId: data.roomId })
- data.isJoining = false
- data.isJoined = true
+ status.isJoining = false
+ status.isJoined = true
startGetAudioLevel()
} catch (error) {
- data.isJoining = false
+ status.isJoining = false
console.error('join room failed', error)
throw error
}
@@ -140,15 +160,14 @@ export default {
console.log(`peer-leave ${userId}`, event)
})
/* 远端添加流 */
- data.client.on('stream-added', (event) => {
+ data.client.on('stream-added', async(event) => {
const { stream: remoteStream } = event
const remoteUserId = remoteStream.getUserId()
- if (remoteUserId === `share_${this.userId}`) {
- this.unSubscribe(remoteStream)
+ if (remoteUserId === `share_${data.userId}`) {
+ await unsubscribeStream(remoteStream)
} else {
console.log(`remote stream added: [${remoteUserId}] type: ${remoteStream.getType()}`)
- this.subscribe(remoteStream)
- this.addSuccessLog(`RemoteStream added: [${remoteUserId}].`)
+ await subscribeStream(remoteStream)
}
})
/* 远端流订阅成功 */
@@ -156,19 +175,18 @@ export default {
const { stream: remoteStream } = event
const remoteUserId = remoteStream.getUserId()
console.log('stream-subscribed userId: ', remoteUserId)
- this.addSuccessLog(`RemoteStream subscribed: [${remoteUserId}].`)
- this.remoteStreamList.push(remoteStream)
- this.$nextTick(() => {
- this.playRemoteStream(remoteStream, remoteUserId)
+ data.remoteStreamList.push(remoteStream)
+ nextTick(() => {
+ playRemoteStream(remoteStream, remoteUserId)
})
})
/* 远端流移除 */
data.client.on('stream-removed', (event) => {
const { stream: remoteStream } = event
remoteStream.stop()
- const index = this.remoteStreamList.indexOf(remoteStream)
+ const index = data.remoteStreamList.indexOf(remoteStream)
if (index >= 0) {
- this.remoteStreamList.splice(index, 1)
+ data.remoteStreamList.splice(index, 1)
}
console.log(`stream-removed userId: ${remoteStream.getUserId()} type: ${remoteStream.getType()}`)
})
@@ -176,7 +194,6 @@ export default {
data.client.on('stream-updated', (event) => {
const { stream: remoteStream } = event
console.log(`type: ${remoteStream.getType()} stream-updated hasAudio: ${remoteStream.hasAudio()} hasVideo: ${remoteStream.hasVideo()}`)
- this.addSuccessLog(`RemoteStream updated: [${remoteStream.getUserId()}] audio:${remoteStream.hasAudio()}, video:${remoteStream.hasVideo()}.`)
})
/* 远端流禁用音频 */
data.client.on('mute-audio', (event) => {
@@ -211,6 +228,47 @@ export default {
})
}
+ /**
+ * @description: 订阅远端流
+ * @return {*}
+ */
+ const subscribeStream = async(remoteStream, config = { audio: true, video: true }) => {
+ try {
+ await data.client.subscribe(remoteStream, {
+ audio: isUndef(config.audio) ? true : config.audio,
+ video: isUndef(config.video) ? true : config.video
+ })
+ } catch (error) {
+ console.error(`subscribe ${remoteStream.getUserId()} with audio: ${config.audio} video: ${config.video} error`, error)
+ }
+ }
+
+ /**
+ * @description: 取消订阅远端流
+ * @return {*}
+ */
+ const unsubscribeStream = async(remoteStream) => {
+ try {
+ await data.client.unsubscribe(remoteStream)
+ } catch (error) {
+ console.error(`unsubscribe ${remoteStream.getUserId()} error`, error)
+ }
+ }
+
+ /**
+ * @description: 播放远端流
+ * @param {*} remoteStream
+ * @param {*} element
+ * @return {*}
+ */
+ const playRemoteStream = (remoteStream, element) => {
+ if (remoteStream.getType() === 'main' && remoteStream.getUserId().indexOf('share') >= 0) {
+ remoteStream.play(element, { objectFit: 'contain' }).catch()
+ } else {
+ remoteStream.play(element).catch()
+ }
+ }
+
/**
* @description: 初始化本地流
* @return {*}
@@ -249,21 +307,41 @@ export default {
* @return {*}
*/
const publishStream = async() => {
- if (!data.isJoined || data.isPublishing || data.isPublished) {
+ if (!status.isJoined || status.isPublishing || status.isPublished) {
return
}
- data.isPublishing = true
+ status.isPublishing = true
try {
await data.client.publish(settings.localStream)
- data.isPublishing = false
- data.isPublished = true
+ status.isPublishing = false
+ status.isPublished = true
} catch (error) {
- data.isPublishing = false
+ status.isPublishing = false
console.error('publish localStream failed', error)
throw error
}
}
+ /**
+ * @description: 终止推流
+ * @return {*}
+ */
+ const unPublishStream = async() => {
+ if (!status.isPublished || status.isUnPublishing) {
+ return
+ }
+ status.isUnPublishing = true
+ try {
+ await data.client.unpublish(settings.localStream)
+ status.isUnPublishing = false
+ status.isPublished = false
+ } catch (error) {
+ status.isUnPublishing = false
+ console.error('unpublish localStream failed', error)
+ throw error
+ }
+ }
+
/**
* @description: 打开摄像头
* @return {*}
@@ -308,18 +386,53 @@ export default {
}
}
+ /**
+ * @description: 销毁房间
+ * @return {*}
+ */
+ const destroyLocalStream = () => {
+ settings.localStream && settings.localStream.stop()
+ settings.localStream && settings.localStream.close()
+ settings.localStream = null
+ settings.isPlayingLocalStream = false
+ }
+
+ /**
+ * @description: 禁用音频
+ * @return {*}
+ */
+ const stopGetAudioLevel = () => {
+ data.client && data.client.enableAudioVolumeEvaluation(-1)
+ }
+
+ /**
+ * @description: 退出直播间
+ * @return {*}
+ */
const leaveMeetingRoom = async() => {
- await data.client.leave()
+ if (!status.isJoined || status.isLeaving) {
+ return
+ }
+ status.isLeaving = true
+ stopGetAudioLevel()
+ status.isPublished && await unPublishStream()
+ settings.localStream && destroyLocalStream()
+
+ try {
+ await data.client.leave()
+ status.isLeaving = false
+ status.isJoined = false
+ } catch (error) {
+ status.isLeaving = false
+ console.error('leave room error', error)
+ throw error
+ }
}
onMounted(() => {
const { userId, roomId } = route.query
data.userId = userId
data.roomId = Number(roomId)
- // nextTick(async() => {
- // await createMeetingRoom()
- // await initLocalStream()
- // })
})
watch(() => [settings.cameraId, settings.microphoneId], async([cameraId, microphoneId]) => {
if (cameraId && microphoneId) {
@@ -334,10 +447,12 @@ export default {
return {
...toRefs(data),
...toRefs(settings),
+ ...toRefs(status),
handleVideoMute,
handleVideoUnMute,
handleAudioMute,
- handleAudioUnMute
+ handleAudioUnMute,
+ leaveMeetingRoom
}
}
}
@@ -347,10 +462,12 @@ export default {
.room{
width: 100vw;
height: 100vh;
+ position: relative;
.local-stream-container{
width: 100%;
height: 100%;
- position: relative;
+ position: absolute;
+ top: 0;
.local-stream-content {
width: 100%;
height: 100%;
@@ -358,9 +475,9 @@ export default {
.local-stream-control {
width: 100%;
height: 100%;
- height: 40px;
+ height: 50px;
position: absolute;
- bottom: 5px;
+ bottom: 0;
z-index: 99;
display: flex;
justify-content: flex-end;
@@ -372,5 +489,20 @@ export default {
}
}
}
+ .remote-container{
+ position: absolute;
+ top: 50px;
+ width: 150px;
+ max-height: calc(100% - 100px);
+ overflow-y: scroll;
+ z-index: 999;
+ right: 10px;
+ .remote-stream-container{
+ width: 100%;
+ height: 200px;
+ background: red;
+ margin-bottom: 10px;
+ }
+ }
}