I am using laravel API to run video calling with Agora application.
Problem is my video call page sample is not loading and I keep getting this error
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in mounted hook: "TypeError: Cannot read properties of undefined (reading 'join')"
Call.Vue
<script>
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
import AgoraRTC from 'agora-rtc-sdk'
Vue.use(AgoraRTC)
export default {
name: "AgoraChat",
props: ["authuser", "authuserid", "allusers", "agora_id"],
data() {
return {
callPlaced: false,
client: null,
localStream: null,
mutedAudio: false,
mutedVideo: false,
userOnlineChannel: null,
onlineUsers: [],
incomingCall: false,
incomingCaller: "",
agoraChannel: null,
};
},
mounted() {
this.initUserOnlineChannel();
this.initUserOnlineListeners();
},
methods: {
/**
* Presence Broadcast Channel Listeners and Methods
* Provided by Laravel.
* Websockets with Pusher
*/
initUserOnlineChannel() {
this.userOnlineChannel = window.Echo.join("agora-online-channel");
},
initUserOnlineListeners() {
this.userOnlineChannel.here((users) => {
this.onlineUsers = users;
});
this.userOnlineChannel.joining((user) => {
// check user availability
const joiningUserIndex = this.onlineUsers.findIndex(
(data) => data.id === user.id
);
if (joiningUserIndex < 0) {
this.onlineUsers.push(user);
}
});
this.userOnlineChannel.leaving((user) => {
const leavingUserIndex = this.onlineUsers.findIndex(
(data) => data.id === user.id
);
this.onlineUsers.splice(leavingUserIndex, 1);
});
// listen to incomming call
this.userOnlineChannel.listen("MakeAgoraCall", ({ data }) => {
if (parseInt(data.userToCall) === parseInt(this.authuserid)) {
const callerIndex = this.onlineUsers.findIndex(
(user) => user.id === data.from
);
this.incomingCaller = this.onlineUsers[callerIndex]["name"];
this.incomingCall = true;
// the channel that was sent over to the user being called is what
// the receiver will use to join the call when accepting the call.
this.agoraChannel = data.channelName;
}
});
},
getUserOnlineStatus(id) {
const onlineUserIndex = this.onlineUsers.findIndex(
(data) => data.id === id
);
if (onlineUserIndex < 0) {
return "Offline";
}
return "Online";
},
async placeCall(id, calleeName) {
try {
// channelName = the caller's and the callee's id. you can use anything. tho.
const channelName = `${this.authuser}_${calleeName}`;
const tokenRes = await this.generateToken(channelName);
// Broadcasts a call event to the callee and also gets back the token
await axios.post("url/api/agora/call-user", {
user_to_call: id,
username: this.authuser,
channel_name: channelName,
});
this.initializeAgora();
this.joinRoom(tokenRes.data, channelName);
} catch (error) {
console.log(error);
}
},
async acceptCall() {
this.initializeAgora();
const tokenRes = await this.generateToken(this.agoraChannel);
this.joinRoom(tokenRes.data, this.agoraChannel);
this.incomingCall = false;
this.callPlaced = true;
},
declineCall() {
// You can send a request to the caller to
// alert them of rejected call
this.incomingCall = false;
},
generateToken(channelName) {
return axios.post("url/api/agora/token", {
channelName,
});
},
/**
* Agora Events and Listeners
*/
initializeAgora() {
this.client = AgoraRTC.createClient({ mode: "rtc", codec: "h264" });
this.client.init(
this.agora_id,
() => {
console.log("AgoraRTC client initialized");
},
(err =>
{
console.log("AgoraRTC client init failed", err)
})
);
},
async joinRoom(token, channel) {
this.client.join(
token,
channel,
this.authuser,
(uid) => {
console.log("User " + uid + " join channel successfully");
this.callPlaced = true;
this.createLocalStream();
this.initializedAgoraListeners();
},
(err) => {
console.log("Join channel failed", err);
}
);
},
initializedAgoraListeners() {
// Register event listeners
this.client.on("stream-published", function (evt) {
console.log("Publish local stream successfully");
console.log(evt);
});
//subscribe remote stream
this.client.on("stream-added", ({ stream }) => {
console.log("New stream added: " + stream.getId());
this.client.subscribe(stream, function (err) {
console.log("Subscribe stream failed", err);
});
});
this.client.on("stream-subscribed", (evt) => {
// Attach remote stream to the remote-video div
evt.stream.play("remote-video");
this.client.publish(evt.stream);
});
this.client.on("stream-removed", ({ stream }) => {
console.log(String(stream.getId()));
stream.close();
});
this.client.on("peer-online", (evt) => {
console.log("peer-online", evt.uid);
});
this.client.on("peer-leave", (evt) => {
var uid = evt.uid;
var reason = evt.reason;
console.log("remote user left ", uid, "reason: ", reason);
});
this.client.on("stream-unpublished", (evt) => {
console.log(evt);
});
},
createLocalStream() {
this.localStream = AgoraRTC.createStream({
audio: true,
video: true,
});
// Initialize the local stream
this.localStream.init(
() => {
// Play the local stream
this.localStream.play("local-video");
// Publish the local stream
this.client.publish(this.localStream, (err) => {
console.log("publish local stream", err);
});
},
(err) => {
console.log(err);
}
);
},
endCall() {
this.localStream.close();
this.client.leave(
() => {
console.log("Leave channel successfully");
this.callPlaced = false;
},
(err =>
{
console.log("Leave channel failed", err)
})
);
},
handleAudioToggle() {
if (this.mutedAudio) {
this.localStream.unmuteAudio();
this.mutedAudio = false;
} else {
this.localStream.muteAudio();
this.mutedAudio = true;
}
},
handleVideoToggle() {
if (this.mutedVideo) {
this.localStream.unmuteVideo();
this.mutedVideo = false;
} else {
this.localStream.muteVideo();
this.mutedVideo = true;
}
},
},
};
</script>
Controller
public function index(Request $request)
{
// fetch all users apart from the authenticated user
$users = User::where('id', '<>', Auth::id())->get();
return response($users, 201);
}
public function token(Request $request)
{
$appID = 'f0a49490ebe34e7c99464ebc87e94bed';
$appCertificate = 'fd477a4ad9fb455a8ed22445b82cb89f';
$channelName = $request->channelName;
$user = Auth::user()->name;
$role = RtcTokenBuilder::RoleAttendee;
$expireTimeInSeconds = 3600;
$currentTimestamp = now()->getTimestamp();
$privilegeExpiredTs = $currentTimestamp + $expireTimeInSeconds;
$token = RtcTokenBuilder::buildTokenWithUserAccount($appID, $appCertificate, $channelName, $user, $role, $privilegeExpiredTs);
return $token;
}
public function callUser(Request $request)
{
$data['userToCall'] = $request->user_to_call;
$data['channelName'] = $request->channel_name;
$data['from'] = Auth::id();
broadcast(new MakeAgoraCall($data))->toOthers();
}