Build attendance
Introduction
This guide will help you understand various approaches available to calculate total session duration, aggregated participants' duration, and individual participants' duration for a specific session.
We recommend two approaches:
- Use the Retrieve a specific session API to get the individual participants' duration, total session duration, and aggregated participants' duration.
- Use the data export option available on Sessions page in your 100ms dashboard to get the total session duration and aggregated participants' duration.
Please follow the below sections for more details with examples.
Using Sessions API
Use this API to build the attendance system to gather information about peers for a session, such as join/leave timestamps, duration, peer_id, user_id, etc.
Let's take a quick look at the overall flow of how we can build this:
Listen to session.close.success webhook event
Listen to the session.close.success
webhook event, which indicates that the particular session has ended.
// Build attendance app.post('/webhooks', async function (req, res) { var eventType = req.body.type; var sessionId = req.body.data['session_id']; // Listen to the session.close.success webhook event if (eventType === 'session.close.success') { console.log('Session has ended'); try { console.log(sessionId); } catch (err) { console.log(err.data); } } else console.log('Some other event'); });
Fetch details of peers - Sessions API
Once you receive the webhook, fetch session_id
and trigger the Retrieve a specific session API to fetch details of all the peers who participated in the session.
// Trigger Retrieve a session API to fetch details of all peers in the session. var response = await axios({ method: 'get', url: baseUrl + '/sessions/' + sessionId, headers: { Authorization: `Bearer ${managementToken}` } }); var parsedData = response.data;
Calculate the individual participants' duration
- Calculate the individual participants' duration by finding the difference between the
joined_at
andleft_at
fields for the respective peer- Map the duration against
peer_id
oruser_id
(your internal user identifier used while creating the auth token for peers).
- Map the duration against
Note:
- 100ms generates a
peer_id
(unique identifier) every time a peer joins a room. If a peer leaves and re-joins the room, they will be assigned a new peer_id. - A
user_id
will be unique to a peer as it's associated with the auth token they use to join the room. The below example usesuser_id
to avoid duplicate entries for a single peer.
// Calculate individual participants' duration const peers = Object.values(parsedData.peers); const detailsByUser = peers.reduce((acc, peer) => { const duration = moment .duration(moment(peer.left_at).diff(moment(peer.joined_at))) .asMinutes(); const roundedDuration = Math.round(duration * 100) / 100; acc[peer.user_id] = { "name": peer.name, "user_id": peer.user_id, "duration": (acc[peer.user_id]?.duration || 0) + roundedDuration }; return acc; }, {}); const result = Object.values(detailsByUser); console.log(result);
Calculate aggregated participants' duration
Calculate aggregated participants' duration by adding the duration of all the peers.
// Calculate aggregated participants' duration const totalDuration = result .reduce((a, b) => a + b.duration, 0) .toFixed(2); console.log(`Total duration for all peers: ${totalDuration} minutes`);
Calculate total session duration
Calculate total session duration by finding the difference between created_at
and updated_at
timestamps.
// Calculate total session duration const sessionDuration = moment .duration(moment(parsedData.updated_at).diff(moment(parsedData.created_at))) .asMinutes() .toFixed(2); console.log(`Session duration is: ${sessionDuration} minutes`);
Example output
Check the below example to understand how you can store the data in your preferred database for later review.
[ { name: 'username1', user_id: 'user1', duration: 2.42 }, { name: 'username2', user_id: 'user2', duration: 2.37 } ] Total duration for all peers: 4.79 minutes Total session duration is: 2.42 minutes
Check the complete code sample below.
Using data export - 100ms dashboard
100ms provides a simple way to extract the Sessions data to create reports using the exported data. Please follow the below steps:
- Go to the Sessions page on your dashboard.
- Click on the
download
icon next to "Your Sessions" at the top of the page. - This will initiate a data export request that will be shared as a CSV file via email to your account email address.
Example CSV
The exported data will contain data for fields such as:
- session_id,
- room_id,
- created_at (session start time),
- recording_enabled (recording status),
- total_peers,
- participant duration (aggregated duration for all peers),
- session_duration, and
- recording_duration (only available for SFU recording at the moment).
Other possible methods
- You can use the
peer.leave.success
webhook event for a specific session to calculate individual participants' duration and aggregated participants' duration.- From the webhook events fetch details of
joined_at
andleft_at
fields for each peer and find the difference to calculate individual participants' duration. - Find the sum of the duration for all the peers to calculate the aggregated participants' duration.
- From the webhook events fetch details of
- If you need to get the duration of an ongoing session, you can use the below logic:
- Use Retrieve a specific session API to fetch details of individual peers currently active in the session.
- Find the difference between the value for
joined_at
andcurrent_time
(use some library to get the current time) to get the current duration.
Complete code example - Using sessions API
var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var axios = require('axios'); var jwt = require('jsonwebtoken'); var moment = require('moment'); var uuid4 = require('uuid4'); var baseUrl = 'https://api.100ms.live/v2'; var app_access_key = '<YOUR_APP_ACCESS_KEY>'; var app_secret = '<YOUR_APP_SECRET>'; app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); var managementToken = jwt.sign( { access_key: app_access_key, type: 'management', version: 2, iat: Math.floor(Date.now() / 1000), nbf: Math.floor(Date.now() / 1000) }, app_secret, { algorithm: 'HS256', expiresIn: '24h', jwtid: uuid4() } ); // Build attendance app.post('/webhooks', async function (req, res) { var eventType = req.body.type; var sessionId = req.body.data['session_id']; // Listen to the session.close.success webhook event if (eventType === 'session.close.success') { console.log('Session has ended'); try { // Trigger Retrieve a session API to fetch details of all peers in the session. var response = await axios({ method: 'get', url: baseUrl + '/sessions/' + sessionId, headers: { Authorization: `Bearer ${managementToken}` } }); var parsedData = response.data; // Calculate individual participants' duration const peers = Object.values(parsedData.peers); const detailsByUser = peers.reduce((acc, peer) => { const duration = moment .duration(moment(peer.left_at).diff(moment(peer.joined_at))) .asMinutes(); const roundedDuration = Math.round(duration * 100) / 100; acc[peer.user_id] = { "name": peer.name, "user_id": peer.user_id, "duration": (acc[peer.user_id]?.duration || 0) + roundedDuration }; return acc; }, {}); const result = Object.values(detailsByUser); console.log(result); // Calculate aggregated participants' duration const totalDuration = result .reduce((a, b) => a + b.duration, 0) .toFixed(2); console.log(`Total duration for all peers: ${totalDuration} minutes`); // Calculate total session duration const sessionDuration = moment .duration(moment(parsedData.updated_at).diff(moment(parsedData.created_at))) .asMinutes() .toFixed(2); console.log(`Session duration is: ${sessionDuration} minutes`); } catch (err) { console.log(err.data); } } else console.log('Some other event'); }); app.set('port', process.env.PORT || 2400); app.listen(app.get('port'), function () { console.log('Node app is running on port', app.get('port')); });