This simple server app shows you how to use Vonage Video Node Server SDK to create Vonage sessions, generate tokens for those sessions, archive (or record) sessions, and download those archives. You can either quick deploy via Vonage's Code Hub or run the project locally.
The routes/index.js
file is the Express routing for the web service. The rest of this tutorial
discusses code in this file.
In order to navigate clients to a designated meeting spot, we associate the Session ID to a room name which is easier for people to recognize and pass. For simplicity, we use a local associated array to implement the association where the room name is the key and the Session ID is the value. For production applications, you may want to configure a persistence (such as a database) to achieve this functionality.
The GET /room/:name
route associates an OpenTok session with a "room" name. This route handles the passed room name and performs a check to determine whether the app should generate a new session ID or retrieve a session ID from the local in-memory hash. Then, it generates a Vonage Video token for that session ID. Once the Application ID, session ID, and token are ready, it sends a response with the body set to a JSON object containing the information.
if (roomToSessionIdDictionary[roomName]) {
sessionId = roomToSessionIdDictionary[roomName];
// generate token
token = vonage.video.generateClientToken(sessionId);
res.setHeader('Content-Type', 'application/json');
res.send({
applicationId: appId,
sessionId: sessionId,
token: token
});
}
// if this is the first time the room is being accessed, create a new session ID
else {
try {
const session = await vonage.video.createSession({ mediaMode:"routed" });
// now that the room name has a session associated wit it, store it in memory
// IMPORTANT: Because this is stored in memory, restarting your server will reset these values
// if you want to store a room-to-session association in your production application
// you should use a more persistent storage for them
roomToSessionIdDictionary[roomName] = session.sessionId;
// generate token
token = vonage.video.generateClientToken(session.sessionId);
res.setHeader('Content-Type', 'application/json');
res.send({
applicationId: appId,
sessionId: session.sessionId,
token: token
});
} catch(error) {
console.error("Error creating session: ", error);
res.status(500).send({ error: 'createSession error:' + error });
}
}
The GET /session
routes generates a convenient session for fast establishment of communication.
router.get('/session', function(req, res, next) {
res.redirect('/room/session');
});
A POST
request to the /archive/start
route starts an archive recording of a Vonage Video session.
The session ID is passed in as JSON data in the body of the request
router.post('/archive/start', async function (req, res) {
console.log('attempting to start archive');
const json = req.body;
const sessionId = json.sessionId;
try {
const archive = await vonage.video.startArchive(sessionId, { name: findRoomFromSessionId(sessionId) });
console.log("archive: ", archive);
res.setHeader('Content-Type', 'application/json');
res.send(archive);
} catch (error){
console.error("error starting archive: ",error);
res.status(500).send({ error: 'startArchive error:' + error });
}
});
Note: You can only create an archive for sessions that have at least one client connected. Otherwise, the app will respond with an error.
A POST
request to the /archive/:archiveId/stop
route stops an archive's recording.
The archive ID is returned by the call to the archive/start
endpoint.
router.post('/archive/:archiveId/stop', async function (req, res) {
const archiveId = req.params.archiveId;
console.log('attempting to stop archive: ' + archiveId);
try {
const archive = await vonage.video.stopArchive(archiveId);
res.setHeader('Content-Type', 'application/json');
res.send(archive);
} catch (error){
console.error("error stopping archive: ",error);
res.status(500).send({ error: 'stopArchive error:', error });
}
});
A GET
request to '/archive/:archiveId/view'
redirects the requested clients to
a URL where the archive gets played.
router.get('/archive/:archiveId/view', async function (req, res) {
const archiveId = req.params.archiveId;
console.log('attempting to view archive: ' + archiveId);
try {
const archive = await vonage.video.getArchive(archiveId);
if (archive.status === 'available') {
res.redirect(archive.url);
} else {
res.render('view', { title: 'Archiving Pending' });
}
} catch (error){
console.log("error viewing archive: ",error);
res.status(500).send({ error: 'viewArchive error:' + error });
}
});
A GET
request to /archive/:archiveId
returns a JSON object that contains all archive properties, including status
, url
, duration
, etc. For more information, see here.
router.get('/archive/:archiveId', async function (req, res) {
const archiveId = req.params.archiveId;
// fetch archive
console.log('attempting to fetch archive: ' + archiveId);
try {
const archive = await vonage.video.getArchive(archiveId);
// extract as a JSON object
res.setHeader('Content-Type', 'application/json');
res.send(archive);
} catch (error){
console.error("error getting archive: ",error);
res.status(500).send({ error: 'getArchive error:' + error });
}
});
A GET
request to /archive
with optional sessionId
, count
and offset
params returns a list of JSON archive objects. For more information, please check here.
Examples:
GET /archive // fetch up to 1000 archive objects
GET /archive?sessionId=1_MX42...xQVJmfn4 // fetch archive(s) with session ID
GET /archive?count=10 // fetch the first 10 archive objects
GET /archive?offset=10 // fetch archives but first 10 archive objetcs
GET /archive?count=10&offset=10 // fetch 10 archive objects starting from 11th
This sample app does not provide client-side functionality (for connecting to Vonage Video sessions and for publishing and subscribing to streams). It is intended to be used with the Vonage Video tutorials for Web, iOS, iOS-Swift, or Android:
Interested in contributing? We :heart: pull requests! See the Contribution guidelines.
We love to hear from you so if you have questions, comments or find a bug in the project, let us know! You can either: