I am using the Agora Web SDK NG 4.X, and I am trying to build a video conference application using Vue JS. I have been closely following the Agora documentation, but I keep getting this error "AgoraRTCError INVALID_REMOTE_USER: user is not in the channel" and I have no idea how this is possible Here is my code in the scripe section:
<script>
import AgoraRTC from "agora-rtc-sdk-ng"
export default {
data() {
return {
remoteUsers: {},
agoraClient: null,
agoraAppID: null,
agoraToken: null,
localAudioTrack: null,
localVideoTrack: null,
localScreenTrack: null,
userID: null,
roomID: null,
participants: [],
}
},
mounted() {
this.agoraAppID = import.meta.env.VITE_AGORA_APP_ID
this.getUserID()
this.getRoomID()
this.initializeRTCClient()
this.joinRoomInit()
},
methods: {
async joinRoomInit() {
try {
await this.agoraClient.join(this.agoraAppID, "demo_channel", this.agoraToken, this.userID)
this.joinStream()
this.agoraClient.on('user-published', this.handleUserPublished)
this.agoraClient.on('user-unpublished', this.handleUserLeft)
} catch (error) {
console.log(error);
}
},
initializeRTCClient() {
this.agoraClient = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' })
},
getUserID() {
if (!this.userID) {
this.userID = String(Math.floor(Math.random() * 10000))
}
console.log('user_id', this.userID)
},
getRoomID() {
if (!this.roomID) {
this.roomID = this.$route.params.roomId
console.log('room_id', this.roomID)
}
},
async joinStream() {
this.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack()
this.localVideoTrack = await AgoraRTC.createCameraVideoTrack()
// this.localScreenTrack = await AgoraRTC.createScreenVideoTrack()
this.participants.push({ uid: this.userID })
console.log(this.participants)
let sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
await sleep(500);
this.localVideoTrack.play(`user-${this.userID}`)
await this.agoraClient.publish([this.localAudioTrack, this.localVideoTrack])
},
async handleUserPublished(user, mediaType) {
this.remoteUsers[user.uid] = user
// Initiate the Subscription
await this.agoraClient.subscribe(user, mediaType);
this.participants.push({ uid: user.uid })
console.log(this.participants)
let sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
await sleep(5000);
if (mediaType === 'audio') {
let audioTrack = user.audioTrack
audioTrack.play()
} else {
let videoTrack = user.videoTrack
videoTrack.play(`user-${user.uid}`)
}
},
async handleUserLeft(user) {
delete this.remoteUsers[user.uid]
this.participants = this.participants.filter(participant => participant.uid !== user.uid)
},
handleError(error) {
if (error.name === 'Not Allowed Error') {
console.log('Permissions have not been granted to use your camera and ' +
'microphone, you need to allow the page access to your devices in ' +
'order for the demo to work.')
}
}
}
}
</script>
In the template section I have:
<section id="stream-container" class="h-5/6">
<div id="tracks-container" class="w-full flex flex-nowrap mt-8 mb-12 overflow-x-auto">
<div v-for="participant in participants" :id="'user-container-' + participant.uid" @click="pinStream" class="flex content-center items-center border border-indigo-600 rounded bg-indigo-600 overflow-hidden" style="width: 360px; height: 270px;">
<div class="w-full h-full" :id="'user-' + participant.uid">
</div>
</div>
</div>
</section>
Any help is appreacited!
The problem is with vue3's reactivity system kicking in and creating proxies around all objects assigned to data.
You should use markRaw and make objects returned from agora SDK non-reactive so that Vue doesn't interfere with them.
initializeRTCClient() {
this.agoraClient = markRaw(AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' }))
},
You might also have to wrap the other objects returned from Agora in markRaw.