OpenVidu Node many-to-many recording

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);
    });

Have you read how to record sessions with openvidu?

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:

  1. Creating a Session. That is: initializaing a Session object in which you can create Tokens to be passed to browsers to connect to it.
  2. 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
  3. 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.