Agora Web SDK v4 SEND_VIDEO_BITRATE_TOO_LOW and SEND_AUDIO_BITRATE_TOO_LOW - agora.io

I am implementing Agora v4 in my application. When I am trying to publish my local tracks, it happens with success, but then I receive the following errors:
01:21:17:806 Agora-SDK [DEBUG]: [client-9e8ac] receive exception msg, code: 2001, msg: AUDIO_INPUT_LEVEL_TOO_LOW, uid: 4082215569
index.ts:269 01:21:17:807 Agora-SDK [DEBUG]: [client-9e8ac] receive exception msg, code: 2003, msg: SEND_AUDIO_BITRATE_TOO_LOW, uid: 4082215569
index.ts:269 01:21:17:807 Agora-SDK [DEBUG]: [client-9e8ac] receive exception msg, code: 1003, msg: SEND_VIDEO_BITRATE_TOO_LOW, uid: 4082215569
const agoraAccessToken = await actions.auth.getAgoraAccessToken({ requestParams: {channel: props.config.channel}});
console.log(agoraAccessToken);
let uid = await AgoraClient.join(props.config.appId, props.config.channel, agoraAccessToken);
console.log(uid);
let audioTrack = await AgoraRTC.createMicrophoneAudioTrack();
let videoTrack = await AgoraRTC.createCameraVideoTrack();
await AgoraClient.publish([audioTrack, videoTrack]);

You can use the setVideoEncoderConfiguration for setting a minimum and maximum limit in terms of frameRate and bitrate which automatically gets adjusted according to network speed.
Example: https://docs.agora.io/en/Video/video_profile_web_ng?platform=Web.

Related

Error: This environment's XHR implementation cannot support binary transfer

This work is on react native.
I have created a secret client (secret blockchain client).
But when I am trying to perform transaction, getting the following error:
Error: This environment's XHR implementation cannot support binary transfer.
here is my code snippet:
const tx = await clientt.tx.bank.send(
{
amount: [{amount: '3000000', denom: 'uscrt'}],
fromAddress: wallet.address,
toAddress: recipient, // Set recipient to sender for testing
},
{
gasLimit: 20_000,
gasPriceInFeeDenom: 0.25,
memo: 'send tokens example',
},
);

Resolving audio broadcasting error: client join failed DYNAMIC_KEY_EXPIRED (Agora.io)

I'm a server side developer with rudimentary JS knowhow. I'm tinkering with Agora's audio broadcasting functionality (specifically for the web). For reference, I've been following this: https://docs.agora.io/en/Audio%20Broadcast/start_live_audio_web?platform=Web
I'm attempting to broadcast audio as a host. I have an HTML button which fires a JS function where I:
Initialize a client
Set the role
Join a predefined channel
Publish a local stream
My understanding is that accomplshing the aforementioned will enable me to broadcast audio. When I try this, I end up getting a client join failed DYNAMIC_KEY_EXPIRED error. I'm unable to find documentation regarding how to resolve this. Can you help me resolve this? An illustrative example would be nice.
My JS code is below. Note that I'm using a temp token to test this functionality on localhost.
// rtc object
var rtc = {
client: null,
joined: false,
published: false,
localStream: null,
remoteStreams: [],
params: {}
};
// Options for joining a channel
var option = {
appID: "anAppID",// from 'Project Management' dashboard
channel: "AudioLive",
uid: null,//The user ID should be unique in a channel. If you set the user ID as null or 0, the Agora server assigns a user ID and returns it in the onSuccess callback.
token: "aTempToken"// TEMP Token
}
function createBroadcast(role) {
console.log("entered createBroadcast");
// Create a client
rtc.client = AgoraRTC.createClient({mode: "live", codec: "h264"});
// Initialize the client
rtc.client.init(option.appID, function () {
console.log("init success");
// Note: in a live broadcast, only the host can be heard and seen. You can also call setClientRole() to change the user role after joining a channel.
rtc.client.setClientRole(role);
console.log("role is set");
// Call Client.join in the onSuccess callback of Client.init
rtc.client.join(option.token ? option.token : null, option.channel, option.uid ? +option.uid : null, function (uid) {
console.log("join channel: " + option.channel + " success, uid: " + uid);
rtc.params.uid = uid;
// Call AgoraRTC.createStream to create a stream in the onSuccess callback of Client.join
rtc.localStream = AgoraRTC.createStream({
streamID: rtc.params.uid,
audio: true,
video: false,
screen: false,
})
// Call Stream.init to initialize the stream after 'creating' the stream above
// Initialize the local stream
rtc.localStream.init(function () {
console.log("init local stream success");
// play stream with html element id "local_stream"
rtc.localStream.play("local_stream");
// Call Client.publish in the onSuccess callback of Stream.init to publish the local stream
// Publish the local stream
rtc.client.publish(rtc.localStream, function (err) {
console.log("publish failed");
console.error(err);
})
}, function (err) {
console.error("init local stream failed ", err);
});
}, function(err) {
console.error("client join failed", err)
})
}, (err) => {
console.error(err);
});
}
<div style="background:#f0f3f4;padding:20px">
<button id="broadast" style="height:40px;width:200px" onclick="createBroadcast('host')">Start Live Broadcast</button>
</div>
I've not added the actual values for appID and token in the code above.
Note: Please ask for more information in case you require it.
The error that you are facing is due to the expiry of the token generated for authentication purposes while generating an APP ID. To resolve this you will have to generate a new token as elaborated in the below given links:
Token-expired
renewToken
A token (or a temporary token) expires after a certain period of time. When the SDK notifies the client that the token is about to expire or has expired by the onTokenPrivilegeWillExpire or onTokenPrivilegeDidExpire callbacks, you need to generate a new token and call the renewToken method.
client.on("onTokenPrivilegeWillExpire", function(){
//After requesting a new token
client.renewToken(token);
});
client.on("onTokenPrivilegeDidExpire", function(){
//After requesting a new token
client.renewToken(token);
});
Include the above functions in your javascript code along with the rest of the eventListeners.
Incase your application doesn't require security you can opt to not use a token and generate an App ID without a certificate.
App ID without certificate
Do get back for further support incase the issue remains unresolved.

Frequent timeout with app using Serverless Framework (AWS Lambda/Gateway), Express, Mongoose/MongoDB Atlas

Trigger warning : Beginner question.
I built an api using Express and Mongoose with a MongoDB Atlas DB.
Most of the time, it works normally, but often I get timeout errors. This seems to happen very randomly and concerns all routes, etc... Precisely, I get :
`502 Internal server error via POSTMAN`
and in the Serverless Dashboard, I get :
invocation
time invoked 1 day ago, mar 08 at 1:38pm
fatal error Function execution duration going to exceeded configured timeout limit.
cold start
duration 48.9 s
memory used na
request
endpoint /{proxy+}
method POST
status 502
message Internal server error
latency 27 ms
and span & log :
I used this tutorial to wrap my express app to deploy it with serverless framework : https://dev.to/adnanrahic/a-crash-course-on-serverless-apis-with-express-and-mongodb-193k
Serverless.yml file :
service: serviceName
app: appName
org: orgName
provider:
name: aws
runtime: nodejs12.x
stage: ${env:NODE_ENV}
region: eu-central-1
environment:
NODE_ENV: ${env:NODE_ENV}
DB: ${env:DB}
functions:
app:
handler: server.run
events:
- http:
path: /
method: ANY
cors: true
- http:
path: /{proxy+}
method: ANY
cors: true
plugins:
- serverless-offline # Utiliser pour tester localement
- serverless-dotenv-plugin
server.js file :
const sls = require('serverless-http')
const app = require('./app')
module.exports.run = sls(app)
app.js file :
const express = require('express')
const cors = require('cors')
const bodyParser = require('body-parser')
const newRoutes = require('./routes/file')
const app = express()
app.use(bodyParser.json())
const helmet = require('helmet')
app.use(helmet())
app.options('*', cors())
app.use(cors({ allowedHeaders: 'Content-Type, Authorization' }))
app.use('/new-route', newRoutes)
app.use((error, req, res, next) => {
console.log(error)
const status = error.status || 500
const message = error.message
res.status(status).json({
status: status,
message: message
})
})
// Gère la connexion à la base de donnée :
require('./db')
module.exports = app
and finally db.js file :
const mongoose = require('mongoose')
mongoose
.connect(
process.env.DB, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log('connected')
})
.catch(err => console.log(err))
From what I have read, it is related to cold start in Lambda and the way API Gateway handles timeouts (!?). I have read this on mongoose documentation (https://mongoosejs.com/docs/lambda.html), and read also other tutorials, but I don't how exaclty I should adapt it to my situation.
Thank you for your help
Under your provider add timeout, maximum value of timeout in lambda is
900 seconds, place it according to your execution time like 30 seconds
and see what happens
provider:
timeout: 30
The error is clearly saying that it's execution exceeded timeout, since you have not configured timeout so it was using default timeout of 3 seconds, hopefully it will solve the issue
The issue is likely due to your open database connection. While this connection is established any calls to callback won't be returned to the client and your function will timeout.
You need to set context.callbackWaitsForEmptyEventLoop to false.
Here is the explanation from the docs:
callbackWaitsForEmptyEventLoop – Set to false to send the response right away when the callback executes, instead of waiting for the Node.js event loop to be empty. If this is false, any outstanding events continue to run during the next invocation.
With serverless-http you can set this option quite easily within your server.js file:
const sls = require('serverless-http')
const app = require('./app')
module.exports.run = sls(app, { callbackWaitsForEmptyEventLoop: false })

unable to encrypt message in matrix-js-sdk

I'm used 'olm' version '3.1.4' and 'matrix-js-sdk' version '2.4.6'
Trying use end to end encryption supported in matrix using olm
I'm using the following code snipping:
const cryptoStore = new sdk.MemoryCryptoStore(window.localStorage);
const webStorageSessionStore = new sdk.WebStorageSessionStore(window.localStorage);
var matrixStore = new sdk.MatrixInMemoryStore();
matrixClient = sdk.createClient({
baseUrl: 'SERVER_HOME',
accessToken: token,
userId: 'USER_ID',
store: matrixStore,
sessionStore: webStorageSessionStore,
cryptoStore: cryptoStore,
deviceId: 'DEVICE_ID'});
matrixClient.initCrypto()
.then(() => {
matrixClient.startClient({ initialSyncLimit: 10 });
})
1- I have error with post key/upload API bad request
REQUEST: POST Request URL: https://SERVER_HOME/_matrix/client/r0/keys/upload/DEVICE_ID?access_token=XXXX
RESPONSE: 400 Bad Request {"errcode":"M_UNKNOWN","error":"One time key signed_curve25519:XXXX already exists. Old key: {\"key\":\"64zJVMH61Toei8Kaz2SRXEZ4VyNBjjG2vfaGjSXXXX\",\"signatures\":{\"#USER_ID\":{\"ed25519:869254020336060\":\"HBnlhazYGY+IrvImq5d4OcIYsXeo094St2p/SMYWobMfteML1gH1jMSUmAh9o7EYIXQMnshiPSh6FSdL4XXXXw\"}}}; new key: {'key': 'VSfPQ7NFzdPl0owA1pVK8CqTzLCyF6NQCuS8aTIIYmc', 'signatures': {'#USER_ID': {'ed25519:869254020336060': 'rIQHea/3kh5w8PaC91H83zsTKQDevbkPpnJ5Dpj7YHv3o4Jzq1O3AmgMzfhFzhlXBwn1N6gRPfC+jNMCIPXXXX'}}}"}
2- When I test it with encryption Roit room and try to send message from sdk to Roit find this is error get this error
Error sending event UnknownDeviceError: This room contains unknown devices which have not been verified. We strongly recommend you verify them before continuing.
3- When I test it with encryption Roit room and send message from Roit to sdk I get this error
Error decrypting event (id=xxxx): DecryptionError[msg: The sender's device has not sent us the keys for this message., session: FoIZTb4W906iFiQofhzgyZlkjeR9XazjN9vfIC9uzFQ|nCwWvT+VU/FVz7uNLojW51+PtkrXj++eMC1d/Xxxxxxx]

Can't get GCM push messages being sent properly

So my GCM push message works if I use this test link
http://www.androidbegin.com/tutorial/gcm.html
Here's the response
{ "multicast_id":7724943165862866717,
"success":1,
"failure":0,
"canonical_ids":0,
"results":[{"message_id":"0:1418649384921891% 7fd2b314f9fd7ecd"}]}
However if I push using my own service using node push service using the toothlessgear/node-gcm lib
https://github.com/ToothlessGear/node-gcm I get a success message on the server but no msg makes it to the client
{ multicast_id: 5130374164465991000,
success: 1,
failure: 0,
canonical_ids: 0,
results: [ { message_id: '0:1418649238305331%7fd2b3145bca2e79' } ] }
I also tried the same message using pushwoosh and push woosh doesn't work either. How come I'm getting a success message on the server, but no push is received on the client on the latter two services. Is there some sort of ip configuration that I need to do, or some sort of certificate? I've used the same google api server key which is open to all ips on all 3 of these services.
Why does the response show success on the latter but no msg gets received on the client?
Node service server side code
var gcm = require('node-gcm');
// create a message with default values
var message = new gcm.Message();
// or with object values
var message = new gcm.Message({
collapseKey: 'demo',
delayWhileIdle: true,
timeToLive: 3,
data: {
key1: 'message1',
key2: 'message2'
}
});
var sender = new gcm.Sender('insert Google Server API Key here');
var registrationIds = ['regId1'];
/**
* Params: message-literal, registrationIds-array, No. of retries, callback-function
**/
sender.send(message, registrationIds, 4, function (err, result) {
console.log(result);
});
So the pushes were correctly being sent, my issue was with the cordova plugin on the client which requires that the android payload for "message" or "title" be set. The sample php just coincidentally was setting the message property and that's why it worked.
Updating the code to add the following to the data
data: {message:'test'}
works correctly