How do i subscribe live stream video in agora? - html

I am setting up agora SDK to my angular project and am getting the following error.
Code:
This is my sample code and is calling the startCall method in ngOnInit. I have a div element with id.
startCall() {
this.agoraService.client.join(null, '1000', null, (uid) => {
this.localStream = this.agoraService.createStream(uid, true, null, null, true, false);
this.localStream.setVideoProfile('720p_3');
this.subscribeToStreams();
});
}
private subscribeToStreams() {
this.localStream.on("accessAllowed", () => {
console.log("accessAllowed");
});
// The user has denied access to the camera and mic.
this.localStream.on("accessDenied", () => {
console.log("accessDenied");
});
this.localStream.init(() => {
console.log("getUserMedia successfully");
this.localStream.play('agora_local');
this.agoraService.client.publish(this.localStream, function (err) {
console.log("Publish local stream error: " + err);
});
this.agoraService.client.on('stream-published', function (evt) {
console.log("Publish local stream successfully");
});
}, function (err) {
console.log("getUserMedia failed", err);
});
// Add
this.agoraService.client.on('error', (err) => {
console.log("Got error msg:", err.reason);
if (err.reason === 'DYNAMIC_KEY_TIMEOUT') {
this.agoraService.client.renewChannelKey("", () => {
console.log("Renew channel key successfully");
}, (err) => {
console.log("Renew channel key failed: ", err);
});
}
});
// Add
this.agoraService.client.on('stream-added', (evt) => {
const stream = evt.stream;
this.agoraService.client.subscribe(stream, (err) => {
console.log("Subscribe stream failed", err);
});
});
// Add
this.agoraService.client.on('stream-subscribed', (evt) => {
const stream = evt.stream;
if (!this.remoteCalls.includes(`agora_remote${stream.getId()}`)) this.remoteCalls.push(`agora_remote${stream.getId()}`);
setTimeout(() => stream.play(`agora_remote${stream.getId()}`), 2000);
});
// Add
this.agoraService.client.on('stream-removed', (evt) => {
const stream = evt.stream;
stream.stop();
this.remoteCalls = this.remoteCalls.filter(call => call !== `#agora_remote${stream.getId()}`);
console.log(`Remote stream is removed ${stream.getId()}`);
});
// Add
this.agoraService.client.on('peer-leave', (evt) => {
const stream = evt.stream;
if (stream) {
stream.stop();
this.remoteCalls = this.remoteCalls.filter(call => call === `#agora_remote${stream.getId()}`);
console.log(`${evt.uid} left from this channel`);
}
});
}
I have a div element with id.
Uncaught (in promise) TypeError: Failed to execute 'getStats' on 'RTCPeerConnection': The callback provided as parameter 1 is not a function.
at Object.C.t.getStats (AgoraRTCSDK.min.js:2)
at AgoraRTCSDK.min.js:2
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask (zone.js:498)
at ZoneTask.invoke (zone.js:487)
at timer (zone.js:2281)
Does anyone face the same issue? Can anyone help me with this?
Thanks.
I have followed this link
https://docs.agora.io/en/Interactive%20Broadcast/web_prepare?platform=Web
Steps I have done,enter code here
1. Import the Agora Web SDK to Your Project
2. Create and Initialize a Client
3. Join a Channel
4. And finally, Subscribe to the remote stream

When testing Agora's WebSDK (or any WebRTC application) make sure that you are using an https connection when trying to run your code as most browsers do not allow getMedia access without an https connection.
There are a number of solutions for using https connections on your local machine. I use the ngrok tool to easily run https connections on my local machine

Related

Firebase Cloud Function - RangeError: Maximum call stack size exceeded

I am trying to write an onCall Firebase Cloud Function that calls an external Zoho Desk API to return a list of support tickets.
But whenever I call my Firebase Cloud Function it returns this error: Unhandled error RangeError: Maximum call stack size exceeded.
Most of the other answers I have found are in relation to Firebase document snapshots, and they say it is caused by a infinite loop. But I'm not sure how to apply that knowledge to my external api call.
Here is the Cloud Function in question:
export const getZohoDeskTickets = functions
.region('us-central1')
.https.onCall(async (data, context) => {
// Check if it passed App Check
if (context.app == undefined) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called from an App Check verified app.'
);
}
// Check the authentication
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(
'unauthenticated',
'The function must be called while authenticated.'
);
}
// Do the operation
const zohoAccessToken = await getSecretVersion(
'zoho-self-client-api-access-token'
).catch((error) => {
throw new functions.https.HttpsError('unknown', error.message, error);
});
return axios
.get('https://desk.zoho.com/api/v1/tickets', {
headers: {
orgId: '123456789',
Authorization: `Zoho-oauthtoken ${zohoAccessToken}`,
},
})
.catch(async (error) => {
functions.logger.error(error.response.data);
throw new functions.https.HttpsError(
'unknown',
error.response.data.message,
error.response.data
);
});
});
UPDATE:
I found this helpful thread which showed that sometimes the infinite loop is not coming from the Cloud Function but the caller, and also that the call stack can be helpful for debugging.
In the interest of that, here is my call stack as shown in the Firebase Emulator logs. It doesn't make sense to me because it's just the same line repeated again and again:
Unhandled error RangeError: Maximum call stack size exceeded
at TCP.get [as reading] (_tls_wrap.js:617:7)
at Function.entries (<anonymous>)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:157:37)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
And here is the Chrome browser console call stack:
postJSON # index.esm2017.js?6f1f:499
call # index.esm2017.js?6f1f:553
await in call (async)
eval # index.esm2017.js?6f1f:485
eval # SupportPage.vue?c3cc:37
eval # index.js??clonedRule…tup=true&lang=ts:15
__awaiter # index.js??clonedRule…tup=true&lang=ts:11
handleClick # SupportPage.vue?c3cc:36
callWithErrorHandling # runtime-core.esm-bundler.js?f781:155
callWithAsyncErrorHandling # runtime-core.esm-bundler.js?f781:164
emit$1 # runtime-core.esm-bundler.js?f781:718
eval # runtime-core.esm-bundler.js?f781:7232
onClick # QBtn.js?9c40:148
callWithErrorHandling # runtime-core.esm-bundler.js?f781:155
callWithAsyncErrorHandling # runtime-core.esm-bundler.js?f781:164
invoker # runtime-dom.esm-bundler.js?9cec:366
And here is the calling function inside my Vue app:
<template>
<v-btn design="alpha" #click="handleClick">loadData</v-btn>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import VBtn from 'src/components/VBtn.vue';
import { httpsCallable, FunctionsError } from 'firebase/functions';
import { functions } from 'src/config/firebase';
const data = ref();
const getZohoDeskTickets = httpsCallable(functions, 'getZohoDeskTickets');
const isFunctionsError = (error: unknown): error is FunctionsError => {
return (error as FunctionsError).details !== undefined;
};
const handleClick = async () => {
const ticket = await getZohoDeskTickets().catch((error) => {
if (isFunctionsError(error)) {
console.log(error.code);
console.log(error.message);
console.log(error.details);
} else {
console.log(error);
}
});
data.value = ticket;
console.log(ticket);
return ticket;
};
</script>
But even with that I still cannot figure this out.
What is causing the infinite loop?
Or maybe it is something else causing this error?
Finally got it!
The solution came from this answer.
In short; I needed to add a .then() onto the returned axios chain like so:
export const getZohoDeskTickets = functions
.region('us-central1')
.https.onCall(async (data, context) => {
// Check if it passed App Check
if (context.app == undefined) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called from an App Check verified app.'
);
}
// Check the authentication
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(
'unauthenticated',
'The function must be called while authenticated.'
);
}
// Do the operation
const zohoAccessToken = await getSecretVersion(
'zoho-self-client-api-access-token'
).catch((error) => {
throw new functions.https.HttpsError('unknown', error.message, error);
});
return axios
.get('https://desk.zoho.com/api/v1/tickets', {
headers: {
orgId: '774638961',
Authorization: `Zoho-oauthtoken ${zohoAccessToken}`,
},
})
.then((response) => {
functions.logger.info(response.data);
return response.data;
})
.catch((error) => {
functions.logger.error(error.response.data);
throw new functions.https.HttpsError(
'unknown',
error.response.data.message,
error.response.data
);
});
});

get real-time json data from twilio runtime with axios

I am trying to achieve real-time data from twilio server-less function. I am using a boilerplate function edited a little bit.What I want is json data in server and voice response in call consecutively .but the following code is not sending json data to server.
const axios = require('axios');
exports.handler = function (context, event, callback) {
let twiml = new Twilio.twiml.VoiceResponse();
twiml.say('you are welcome ');
const instance = axios.create({
baseURL: 'http://fafc4eac4162.ngrok.io/',
timeout: 3000,
});
instance
.post('/test', {
id: 1,
title: 'Twilio'
})
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
return callback(error);
});
return callback(null, twiml);
};
It shows below error,but it sends data successfully if I do not use the voice response callback return callback(null, twiml) and rather use simple return callback(null, response.data);
{"message":"timeout of 3000ms exceeded","name":"Error","stack":"Error: timeout of 3000ms
exceeded\n at createError (/var/task/node_modules/axios/lib/core/createError.js:16:15)\n
at RedirectableRequest.handleRequestTimeout
(/var/task/node_modules/axios/lib/adapters/http.js:280:16)\n at Object.onceWrapper
(events.js:286:20)\n at RedirectableRequest.emit (events.js:198:13)\n at
Timeout._onTimeout (/var/task/node_modules/follow-redirects/index.js:166:13)\n at
ontimeout (timers.j...
The return callback(null, twiml); should be in the .then block.
.then((response) => {
console.log(JSON.stringify(response.data));
return callback(null, twiml);
})
Also, the error indicates the 3000ms timeout is hit, is your application returning a 200-OK?

this is undefined at axios promise - vuejs

Im registering my axios globally and then using it at every component using this.$axios
I have a save method and items which is an array at my component data.
At my save method i have this piece of code:
this.$axios
.put(`HardwareBoardTracking`, this.items[this.editedIndex])
.then((res) => {
console.log(res);
this.items[this.editedIndex].actions.forEach((test) => {
this.items.forEach((card) => {
if (card.id != this.items[this.editedIndex].id) {
this.addnewActionToCard(card, test);
}
});
});
})
.catch((err) => {
console.log("error caught");
console.log(err);
Object.assign(this.items[this.editedIndex], elementForFail);
});
When getting to then block with debugger i can see this is undefined
This is the error i get:
Uncaught (in promise) TypeError: Cannot convert undefined or null to object
at Function.assign (<anonymous>)
for testing purposes i tried to add testMethod and call it from the promise like this:
testMethod() {
console.log("Test Method");
console.log(this);
},
save() {
const elementForFail = { ...this.editedItem };
if (this.editedIndex > -1) {
Object.assign(this.items[this.editedIndex], this.editedItem);
this.items[this.editedIndex].CompletedAllActions = true;
this.items[this.editedIndex].actions.forEach((element) => {
this.addnewActionToCard(this.items[this.editedIndex], element);
});
this.$axios
.put(`HardwareBoardTracking`, this.items[this.editedIndex])
.then((res) => {
console.log(res);
this.testMethod();
this.items[this.editedIndex].actions.forEach((test) => {
this.items.forEach((card) => {
if (card.id != this.items[this.editedIndex].id) {
this.addnewActionToCard(card, test);
}
});
});
})
.catch((err) => {
console.log("error caught");
console.log(err);
Object.assign(this.items[this.editedIndex], elementForFail);
});
And the method is called and inside it it this is defined properly and logged to consol like this:
VueComponent {...}
I Found this answer https://stackoverflow.com/a/45217521 which looks like exactly what i need, But none of the solution works.
If i try the .bind(this) solution, this is still undefined but it does continue with execution and then i get this error:
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in v-on handler: "TypeError: this.$axios.put(...).then(...).bind is not a function"
html tag added for colorized code

Ionic gives error undefined is not an object (evaluating '_co.user.username') when decoding the login user token

This is part of the error message that I am getting:
[Error] ERROR – TypeError: undefined is not an object (evaluating '_co.user.username') TypeError: undefined is not an object (evaluating '_co.user.username')(anonymous function)checkAndUpdateView — core.js:44...
My login process works fine and data of the user is gotten fine, on ionic serve version of my app, but on ios I can see that error message, like json encoding doesn't work fine or something. Why is the JSON working fine on website, but not on the app? Here is content of TokenService :
constructor(private cookieService: CookieService) {}
setToken(token) {
this.cookieService.set("chat_token", token);
}
getToken() {
return this.cookieService.get("chat_token");
}
deleteToken() {
this.cookieService.delete("chat_token");
}
getPayload() {
const token = this.getToken();
let payload;
if (token) {
payload = token.split(".")[1];
payload = JSON.parse(window.atob(payload));
}
return payload.data;
}
and this is the loginUser function in LoginComponent , that is triggered on logging in:
loginUser() {
this.showSpinner = true;
this.authService.loginUser(this.loginForm.value).subscribe(
data => {
this.tokenService.setToken(data.token);
localStorage.setItem("currentUser", JSON.stringify(data));
this.loginForm.reset();
setTimeout(() => {
this.router.navigate(["/streams"]);
}, 200);
},
err => {
this.showSpinner = false;
if (err.error.message) {
this.errorMessage = err.error.message;
}
}
);
}
Now, the server side, I have this rout in routes/ directory, in node express in file authRoutes.js:
router.post('/login', AuthCtrl.LoginUser);
And then I have this in routes/ directory, in file userRoutes.js:
const express = require('express');
const router = express.Router();
const UserCtrl = require('../controllers/users');
const AuthHelper = require('../Helpers/AuthHelper');
router.get('/users', AuthHelper.VerifyToken, UserCtrl.GetAllUsers);
router.get('/user/:id', AuthHelper.VerifyToken, UserCtrl.GetUser);
router.get(
'/username/:username',
AuthHelper.VerifyToken,
UserCtrl.GetUserByName
);
router.post('/user/view-profile', AuthHelper.VerifyToken, UserCtrl.ProfileView);
router.post(
'/change-password',
AuthHelper.VerifyToken,
UserCtrl.ChangePassword
);
module.exports = router;
This is the part of controller auth.js on node server side:
async LoginUser(req, res) {
if (!req.body.username || !req.body.password) {
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ message: "No empty fields allowed" });
}
await User.findOne({ username: Helpers.firstUpper(req.body.username) })
.then(user => {
if (!user) {
return res.status(HttpStatus.NOT_FOUND).json({ message: "Username not found" });
}
return bcrypt.compare(req.body.password, user.password).then(result => {
if (!result) {
return res
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.json({ message: "Password is incorrect" });
}
const token = jwt.sign({ data: user }, dbConfig.secret, {
expiresIn: "5h"
});
res.cookie("auth", token);
return res.status(HttpStatus.OK).json({ message: "Login successful", user, token });
});
})
.catch(err => {
console.log("Error is:");
console.log(err);
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ message: "Error occured" });
});
}
I resolved the issue by transferring all the stored data from CookieService, which is the main culprit of the error, to a localStorage. Just instead of storing payload and that cookie in CookieService, just transferred it to localStorage, and I didn't have any more problems. Seems like, the simpler - the better.

Puppeteer Google Cloud Function Pub/Sub Trigger can't open browser

I'm trying to create a Puppeteer function in GCP which can be triggered by Pub/Sub messages. The function is callable, but doesn't behave as expected and throws a Timeout Error once browser tries to initialize. Could the trigger possibly be using a NodeJS environment different from HTTP trigger?
I'm also very new to NodeJS, so I apologize ahead of time if the issue is blatantly obvious.
I've created an HTTP trigger for the function which behaves as expected. I copy/paste the Puppeteer Function below into the index.js when creating the Cloud Function, but separated in example for clarity that both triggers are running the identical function.
Puppeteer Function
const puppeteer = require('puppeteer');
scrapeUglyWebsite = () => {
return new Promise(async(resolve, reject) => {
await puppeteer.launch({
headless: true,
args: ['--no-sandbox']
})
.then(async (browser) => {
const page = await browser.newPage();
await page.goto('http://suzannecollinsbooks.com/', {waitUntil: 'load', timeout: 0})
.then(async () => {
//Wait for content to load
await page.waitForFunction('document.body !== null && document.body.innerText.includes(\'Jon Scieszka\')');
//Evaluate page contents
const dom_eval = await page.evaluate(() => document.body.innerText.includes("Here’s a picture of me with a rat"));
await browser.close();
resolve(dom_eval);
});
}).catch((err) => {
reject(err);
});
});
};
HTTP Trigger - index.js
exports.cloudFunctionTest = (req, res) => {
scrapeUglyWebsite()
.then((results) => {
if(results) {
res.send('Suzanne Collins takes pictures with rats.');
} else {
res.send("Suzzane Collins doesn't take pictures with rats.");
};
})
.catch((err) => {
res.send(err.toString());
});
Pub/Sub Trgger - index.js
exports.cloudFunctionTest = (data, context) => {
scrapeUglyWebsite()
.then((results) => {
if(results) {
console.log('Suzanne Collins takes pictures with rats.');
} else {
console.log("Suzzane Collins doesn't take pictures with rats.");
};
})
.catch((err) => {
console.log(err.toString());
});
};
package.json
{
"name": "test",
"version": "0.0.1",
"engines": {
"node": "8"
},
"dependencies": {
"puppeteer": "^1.6.0"
}
}
HTTP Trigger behaves correctly with the expected result
Suzanne Collins takes pictures with rats.
Pub/Sub Trigger throws the following error with no output
TimeoutError: Timed out after 30000 ms while trying to connect to Chrome! The only Chrome revision guaranteed to work is r662092
I know this is late but the reason that the TimeoutError occurs is because cloud functions do not automatically wait for async tasks to finish completing. So in exports.cloudFunctionTest, scrapeUglyWebsite() is called but the function does not wait for the promise to be fulfilled, so the program terminates. Hence the error
More info here on how background functions work in NodeJs
In order for the function to wait for scrapeUglyWebsite(), you need to return a promise that completes when scrapeUglyWebsite() and the resulting code is complete.
Personally, I got it to work by simply wrapping the code currently in the function I am exporting in another async function and then returning the promise of the wrapper function.
async function wrapper() {
try {
const result = await scrapeUglyWebsite();
if(results) {
console.log('Suzanne Collins takes pictures with rats.');
} else {
console.log("Suzzane Collins doesn't take pictures with rats.");
};
} catch (err) {
console.log(err.toString());
}
}
Then in the function you want to export:
exports.cloudFunctionTest = (data, context) => {
return wrapper();
};