User not found in channel (AgoraSDK RTC v4)

49 Views Asked by At

You can see the problem in the screenshots. I'm trying to create a channel for 2 people using Agora, but when I try to connect I only get the local stream connection to work. The remote user can't be seen or heard and I get errors in the console.

Below are screenshots and code on AlpineJs where the connection is made after accepting the Agora RTM (Signaling) invitation.

Error 1 Error 2

All token generation happens on the Backend side. Tokens are valid.

document.addEventListener('alpine:init', () => {
        Alpine.data('video', () => ({
                callPlaced: false,
                client: null,
                localStream: null,
                onlineUsers: [],
                incomingCall: false,
                incomingCaller: "",
                remoteInvitation: null,
                localInvitation: null,
                authuser: @js( auth()->user()->username ?? null ),
                authuserid: @js( auth()->id() ?? null ),
                agoraRtmClient: null,
                agoraOnlineChannel: null,
                channelParameters: {
                    localAudioTrack: null,
                    localVideoTrack: null,
                    remoteAudioTrack: null,
                    remoteVideoTrack: null,
                    remoteUid: null,
                },
                agoraOptions: {
                    appId: @js(config('app.agora_app_id'))
                },

                init() {
                    const rtmClient = window.AgoraRTM.createInstance(this.agoraOptions.appId)
                    this.agoraRtmClient = rtmClient

                    let channel = rtmClient.createChannel("online")
                    this.agoraOnlineChannel = channel

                    this.initAgoraRtmListeners();

                    let user = this.authuser
                    window.onload = async function () {
                        let response = await fetch(@js(route('agora.tokens.rtm')), {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json; charset=UTF-8'
                            }
                        });

                        if (response.ok) {
                            let token = (await response.json()).token;

                            await rtmClient.login({
                                uid: user,
                                token: token
                            })

                            await channel.join().then(() => {
                                console.log("You have successfully joined channel " + channel.channelId)
                            })
                        } else {
                            console.log(response.status)
                        }
                    }

                    this.client = AgoraRTC.createClient({mode: "rtc", codec: "vp8"});

                    this.client.on("user-published", async (remoteUser, mediaType) => {
                        console.log('remote user: ' + remoteUser.uid.toString())
                        await this.client.subscribe(remoteUser, mediaType);
                        if (mediaType == "video") {
                            console.log("subscribe video success");
                            this.channelParameters.remoteVideoTrack = remoteUser.videoTrack
                            this.channelParameters.remoteAudioTrack = remoteUser.audioTrack
                            this.channelParameters.remoteUid = remoteUser.uid.toString()
                            this.createRemoteVideoBlock()
                            this.channelParameters.remoteVideoTrack.play("remote-video");
                        }
                        if (mediaType == "audio") {
                            console.log("subscribe audio success");
                            this.channelParameters.remoteAudioTrack = remoteUser.audioTrack
                            remoteUser.audioTrack.play();
                        }
                    });

                    this.client.on("user-unpublished", user => {
                        console.log(user.uid + "has left the channel");
                        this.endCall()

                        let callingStatus = document.createElement('p');
                        callingStatus.id = 'callingState'
                        callingStatus.innerText = "Call ended";
                        let videoBlock = document.getElementById('video-block');
                        videoBlock.append(callingStatus);

                        setTimeout(() => {
                            document.getElementById('callingState').remove()
                        }, 2000)
                    });

                    console.log('Init listeners done')
                },

                initAgoraRtmListeners() {
                    this.agoraRtmClient.on('MessageFromPeer', function (message, peerId) {
                        document.getElementById("receivedPeerMessage").appendChild(document.createElement('div')).append(peerId + ": " + message.text)
                    })

                    this.agoraRtmClient.on('ConnectionStateChanged', function (state, reason) {
                        console.log("State changed To: " + state + " Reason: " + reason)
                    })

                    this.agoraRtmClient.on('RemoteInvitationReceived', (remoteInvitation) => this.showCall(remoteInvitation))

                    this.agoraRtmClient.on('RemoteInvitationRefused', function (response) {
                        console.log('RemoteInvitationRefused')
                    });

                    this.agoraOnlineChannel.on('MemberJoined', function (memberId) {
                        console.log(memberId + " joined the channel")
                    })
                    this.agoraOnlineChannel.on('MemberLeft', function (memberId) {
                        console.log(memberId + " left the channel")
                    })
                },

                showCall(remoteInvitation) {
                    this.incomingCall = true
                    this.remoteInvitation = remoteInvitation
                    remoteInvitation.on('RemoteInvitationAccepted', async () => {
                        console.log("Accepted Remote Invitation")
                    })
                    remoteInvitation.on('RemoteInvitationCanceled', function (content) {
                        this.incomingCall = false
                        this.incomingCaller = ''
                    })
                    this.incomingCaller = remoteInvitation.callerId
                },

                async joinChannel(channel, channelName) {
                    await channel.join().then(() => {
                        document.getElementById("log").appendChild(document.createElement('div')).append("You have successfully joined channel " + channel.channelId)
                    })
                },

                async acceptCall() {
                    this.incomingCall = false;

                    try {
                        const channelName = `${this.incomingCaller}_${this.authuser}`;
                        await this.joinRoom(channelName)

                        this.remoteInvitation.accept();
                    } catch (e) {
                        console.log(e)
                    }
                },

                refuseCall() {
                    this.incomingCall = false;
                    this.remoteInvitation.refuse();
                    this.localInvitation = null;
                    this.incomingCaller = ""
                },

                cancelCall() {
                    this.localInvitation.cancel()
                },

                async sendPeerMessage() {
                    let peerId = this.incomingCaller
                    let peerMessage = document.getElementById("peerMessage").value.toString()

                    if (peerMessage !== '') {
                        await this.agoraRtmClient.sendMessageToPeer(
                            {text: peerMessage},
                            peerId,
                        ).then(sendResult => {
                            if (sendResult.hasPeerReceived) {
                                document.getElementById("receivedPeerMessage").appendChild(document.createElement('div')).append(this.authuser + ": " + peerMessage)
                                // document.getElementById("log").appendChild(document.createElement('div')).append("Message has been received by: " + peerId + " Message: " + peerMessage)
                            } else {
                                document.getElementById("log").appendChild(document.createElement('div')).append("Message sent to: " + peerId + " Message: " + peerMessage)
                            }
                        })

                        document.getElementById("peerMessage").value = ''
                    }
                },

                async placeCall(id, calleeName) {
                    try {
                        if (this.callPlaced) {
                            await this.endCall();
                        }

                        if (this.localInvitation) {
                            this.localInvitation.cancel()
                        }

                        document.getElementById('callingState')?.remove()
                        let callingStatus = document.createElement('p');
                        callingStatus.id = 'callingState'
                        callingStatus.innerText = "Calling";
                        let videoBlock = document.getElementById('video-block');
                        videoBlock.append(callingStatus);

                        const channelName = `${this.authuser}_${calleeName}`;
                        let invitation = this.agoraRtmClient.createLocalInvitation(calleeName.toString());
                        invitation.on('LocalInvitationCanceled', function () {
                            console.log('Local Invitation ended')
                        })
                        invitation.on('LocalInvitationAccepted', async (response) => {
                            document.getElementById('callingState').remove()
                            console.log("Accepted Local Invitation on channel " + channelName)
                            await this.joinRoom(channelName)
                            this.localInvitation = null
                        })
                        invitation.on('LocalInvitationRefused', (response) => {
                            callingStatus.innerText = 'Declined'
                            setTimeout(() => {
                                document.getElementById('callingState').remove()
                            }, 2000)
                            this.incomingCaller = ''
                            this.localInvitation = null
                        })
                        this.localInvitation = invitation
                        invitation.send();
                        this.incomingCaller = calleeName.toString();
                    } catch (error) {
                        console.log(error);
                    }
                },

                async generateVideoToken(channelName) {
                    let response = await fetch(@js(route('agora.tokens.rtc')), {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json;charset=utf-8'
                        },
                        body: JSON.stringify({
                            channelName: channelName.toString()
                        }),
                    });
                    console.log(response)

                    if (response.ok) {
                        return (await response.json()).token
                    } else {
                        console.log(response.status)
                    }
                },

                async joinRoom(channel) {
                    const tokenRes = await this.generateVideoToken(channel);
                    console.log("join channel " + channel)

                    await this.client.join(
                        this.agoraOptions.appId,
                        channel,
                        tokenRes,
                        this.authuserid,
                    );
                    await this.createLocalStream();

                    this.callPlaced = true;
                },

                async endCall() {
                    this.callPlaced = false;
                    this.channelParameters.localAudioTrack.close()
                    this.channelParameters.localVideoTrack.close()

                    this.removeVideoBlock('local-video')
                    this.removeVideoBlock('remote-video')
                    document.getElementById('receivedPeerMessage').innerHTML = ''

                    await this.client.leave();
                    console.log("You left the channel");
                },

                createLocalVideoBlock() {
                    let localVideoBlock = document.createElement('div')
                    localVideoBlock.style.top = '0'
                    localVideoBlock.style.right = '0'
                    localVideoBlock.style.width = '240px'
                    localVideoBlock.style.height = '120px'
                    localVideoBlock.id = "local-video"
                    localVideoBlock.classList.add("position-absolute", "z-3")

                    document.getElementById('video-block').append(localVideoBlock)
                },

                createRemoteVideoBlock() {
                    let removeVideoBlock = document.createElement('div')
                    removeVideoBlock.style.width = '640px'
                    removeVideoBlock.style.height = '480px'
                    removeVideoBlock.style.overflow = 'hidden'
                    removeVideoBlock.style.borderRadius = '0.5rem'
                    removeVideoBlock.id = "remote-video"

                    document.getElementById('video-block').append(removeVideoBlock)
                },

                removeVideoBlock(elementId) {
                    // console.log("Removing " + elementId + " Div");
                    let Div = document.getElementById(elementId);
                    if (Div) {
                        Div.remove();
                    }
                },

                async createLocalStream() {
                    this.channelParameters.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
                    this.channelParameters.localVideoTrack = await AgoraRTC.createCameraVideoTrack();
                    console.log("create local audio/video track success");
                    this.createLocalVideoBlock()

                    this.channelParameters.localVideoTrack.play("local-video");

                    await this.client.publish([
                        this.channelParameters.localAudioTrack,
                        this.channelParameters.localVideoTrack
                    ]);
                    console.log("publish success!");
                },

                // getUserOnlineStatus(id) {
                //     return this.onlineUsers.findIndex((data) => data.id === id) < 0 ? "Offline" : "Online";
                // },
            })
        )
    });

I tried going through all the steps with the console.log output. But in this listener for example the connection is not played back.

                    this.client.on("user-published", async (remoteUser, mediaType) => {
                        console.log('remote user: ' + remoteUser.uid.toString())
                        await this.client.subscribe(remoteUser, mediaType);
                        if (mediaType == "video") {
                            console.log("subscribe video success");
                            this.channelParameters.remoteVideoTrack = remoteUser.videoTrack
                            this.channelParameters.remoteAudioTrack = remoteUser.audioTrack
                            this.channelParameters.remoteUid = remoteUser.uid.toString()
                            this.createRemoteVideoBlock()
                            this.channelParameters.remoteVideoTrack.play("remote-video");
                        }
                        if (mediaType == "audio") {
                            console.log("subscribe audio success");
                            this.channelParameters.remoteAudioTrack = remoteUser.audioTrack
                            remoteUser.audioTrack.play();
                        }
                    });
0

There are 0 best solutions below