Hi all!
Iv’e been following this tutorial to make a videoconference app. It’s working as it is supposed to but I’d like to add the option to record audio from calls. Would appreciate some advice how to do it. I’m running OpenVidu from a Docker container and I’ve already enabled the recording when starting the container running this command:
docker run -p 4443:4443 --rm \
-e OPENVIDU_RECORDING=true \
-e OPENVIDU_RECORDING_PATH=/PATH/TO/VIDEO/FILES \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /PATH/TO/VIDEO/FILES:/PATH/TO/VIDEO/FILES \
openvidu/openvidu-server-kms:2.14.0
Can I start the recording in here where I create a new session:
OV.createSession()
.then((session) => {
// Store the new Session in the collection of Sessions
mapSessions[sessionName] = session;
// Store a new empty array in the collection of tokens
mapSessionNamesTokens[sessionName] = [];
// Generate a new token asynchronously with the recently created tokenOptions
session
.generateToken(tokenOptions)
.then((token) => {
// Store the new token in the collection of tokens
mapSessionNamesTokens[sessionName].push(token);
// Return session template with all the needed attributes
res.render("session.ejs", {
sessionName: sessionName,
token: token,
nickName: clientData,
userName: req.session.loggedUser,
});
})
.catch((error) => {
console.error(error);
});
})
.catch((error) => {
console.error(error);
});
Yes, I’ve read that and tried to implement the solution based on that tutorial like this:
var properties = {
recordingMode: RecordingMode.ALWAYS, // RecordingMode.ALWAYS for automatic recording
defaultOutputMode: Recording.OutputMode.INDIVIDUAL
};
// Create a new OpenVidu Session asynchronously
OV.createSession()
.then((session) => {
var recording;
// Starts recording
session
.startRecording(session.id, {
outputMode: Recording.OutputMode.COMPOSED,
name: "MY_RECORDING_NAME",
})
.then((response) => (recording = response))
.catch((error) => console.error(error));
// Stops recording
session
.stopRecording(recording.id)
.then((response) => (recording = response))
.catch((error) => console.error(error));
// Store the new Session in the collection of Sessions
mapSessions[sessionName] = session;
// Store a new empty array in the collection of tokens
mapSessionNamesTokens[sessionName] = [];
// Generate a new token asynchronously with the recently created tokenOptions
session
.generateToken(tokenOptions)
.then((token) => {
// Store the new token in the collection of tokens
mapSessionNamesTokens[sessionName].push(token);
// Return session template with all the needed attributes
res.render("session.ejs", {
sessionName: sessionName,
token: token,
nickName: clientData,
userName: req.session.loggedUser,
});
})
.catch((error) => {
console.error(error);
});
})
.catch((error) => {
console.error(error);
});
That gives me this error when trying to log in to a new session:
ReferenceError: Recording is not defined
It is pointing into this part of the code:
// Starts recording
session
.startRecording(session.id, {
outputMode: Recording.OutputMode.COMPOSED,
name: "MY_RECORDING_NAME",
})
Here is the whole endpoint where is my own implementation (I modified it a little from my previous answer) where creating a new session (OV.createSession() etc.)
I’m pretty sure I don’t use that session.startRecording
and .stopRecording
functions as I should. I was thinking should the .stopRecording
functionality be in the "/leave-session"
-endpoint or can I handle it in the "/session"
-endpoint?
app.post("/session", (req, res) => {
if (!isLogged(req.session)) {
req.session.destroy();
res.redirect("/");
} else {
// The nickname sent by the client
var clientData = req.body.data;
// The video-call to connect
var sessionName = req.body.sessionname;
// Role associated to this user
var role = users.find((u) => u.user === req.session.loggedUser).role;
// Optional data to be passed to other users when this user connects to the video-call
// In this case, a JSON with the value we stored in the req.session object on login
var serverData = JSON.stringify({ serverData: req.session.loggedUser });
console.log("Getting a token | {sessionName}={" + sessionName + "}");
// Build tokenOptions object with the serverData and the role
var tokenOptions = {
data: serverData,
role: role,
};
if (mapSessions[sessionName]) {
// Session already exists
console.log("Existing session " + sessionName);
// Get the existing Session from the collection
var mySession = mapSessions[sessionName];
// Generate a new token asynchronously with the recently created tokenOptions
mySession
.generateToken(tokenOptions)
.then((token) => {
// Store the new token in the collection of tokens
mapSessionNamesTokens[sessionName].push(token);
// Return session template with all the needed attributes
res.render("session.ejs", {
sessionId: mySession.getSessionId(),
token: token,
nickName: clientData,
userName: req.session.loggedUser,
sessionName: sessionName,
});
})
.catch((error) => {
console.error(error);
});
} else {
// New session
console.log("New session " + sessionName);
// Create a new OpenVidu Session asynchronously
OV.createSession()
.then((session) => {
var recording;
let sessionId = session.getSessionId();
// console.log(sessionId);
// Store the new Session in the collection of Sessions
mapSessions[sessionName] = session;
// Store a new empty array in the collection of tokens
mapSessionNamesTokens[sessionName] = [];
// Generate a new token asynchronously with the recently created tokenOptions
session
.startRecording(sessionId, {
outputMode: Recording.OutputMode.INDIVIDUAL,
})
.then((response) => (recording = response))
.catch((error) => console.error(error))
.stopRecording(recording.id)
.then((response) => (recording = response))
.catch((error) => console.error(error))
.generateToken(tokenOptions)
.then((token) => {
// Store the new token in the collection of tokens
mapSessionNamesTokens[sessionName].push(token);
// Return session template with all the needed attributes
res.render("session.ejs", {
sessionName: sessionName,
token: token,
nickName: clientData,
userName: req.session.loggedUser,
});
})
.catch((error) => {
console.error(error);
});
})
.catch((error) => {
console.error(error);
});
}
}
});
What you are doing in your code doesn’t make sense.
You have a single endpoint in which you are doing:
- Creating a Session. That is: initializaing a Session object in which you can create Tokens to be passed to browsers to connect to it.
- Immediately after initializing the Session, you start its recording. But that doesn’t make sense: the operation of starting a recording will return an error if you try to start it without any connected participant: https://docs.openvidu.io/en/2.14.0/reference-docs/REST-API/#post-apirecordingsstart
- And not only that, immediately after starting the recording you are stopping it!!! Why?
To sum up, the code you posted is doing this:
OV.createSession()
.then((session) => {
session
.startRecording() ......
.stopRecording(recording.id) .......
.generateToken(tokenOptions) ......
That flow of operations makes no sense at all. You must initialize the session and generate tokens as always. And in separated endpoints you must implement a method to start the recording, and in a different one a method to stop the recording. (The start one can be dispensed with if the session is configured with ALWAYS recording mode).
Please, take a look at the recording documentation and the source code of the tutorial to fix your code.
Regards.