Stream Recording JS
The streamrecorder package provides an easy to use interface to connect to an agent session, start and stop recordings, as well as to switch streams during an active recording.
Additionally it provides an interface to connect a supervisor that can watch an agents stream.
The client application requires to have an auth token, received from the streamrecorder service /auth_v2/ endpoints and a unique client identifier.
Read more in the authentication documentation.
Version 3 adds the ability to stream, record, and monitor multiple sources at once.
Although built for multi-stream setups, it remains fully compatible with single-stream use cases and supports from one up to three streams.
Setup
Add the local package and in the project e.g. as streamrecorder-package and locally configure the package in packages.json file.
{
"name": "streamrecorder-ui",
"dependencies": {
"eyeson-streamrec": "./streamrecorder-package"
},
}
Usage
An agent requires to have a proper client identifer and an authentication token in order to connect to the eyeson service.
import eyeson from 'eyeson-streamrec';
const clientId; // A client identifier.
const clientAuthToken; // Client auth token gathered by the streamrec service.
const firstStream; // A media stream
const secondStream; // A media stream
const thirdStream; // A media stream
const webhookUrl; // A target URL for webhooks.
console.info(eyeson.version); // current version of library
console.info(eyeson.maxStreamCount); // maximum supported streams
// Optional maximum bitrate per stream in kbps - min: 150, max: 4000, null for auto
eyeson.setOptionMaxBitrate(250);
async function() {
try {
eyeson.addEventListener(event => {
const { type } = event;
console.debug('[Agent] Event received:', type);
if (type === 'connected') {
setConnected(true);
}
if (type === 'disconnected') {
setRecording(false);
setConnected(false);
console.info(event.termination_cause);
}
if (type === 'recording_state') {
// Whenever recording state changes
// states are STARTED, STOPPED, FAILED
console.info(event.recording_id, event.stream_id, event.state);
}
if (type === 'stream_ended') {
// Info about local stream has stopped
console.info(event.id, event.stream);
}
if (type === 'statistics_ready') {
// onUpdate is called every 5 seconds
event.statistics.onUpdate(stats => {
// contains quality limitation durations in seconds for
// "cpu", "bandwidth", "other" and "none"
// stats.qualityLimitationDurations
// stats.total.qualityLimitationDurations
});
}
});
const streams = {
'first': firstStream,
'second': secondStream,
};
const recordings = {
'first': {
'uploadUrl': firstUploadUrl,
'webhookUrl': firstWebhookUrl,
},
'second': {
'uploadUrl': secondUploadUrl,
'webhookUrl': secondWebhookUrl,
},
'third': {
'uploadUrl': thirdUploadUrl,
'webhookUrl': thirdWebhookUrl,
},
};
// Connect the client to a session.
const sessionId = await eyeson.connect(clientId, clientAuthToken, streams,
webhookUrl);
// Add new streams (NOT during recording)
await eyeson.addStream({ 'third': thirdStream });
// Start a recording for the connected session.
const recordingIds = await eyeson.startRecording(recordings);
// recordingIds:
// {
// "first": { recording_id: "0ecdf0e3...", state: "STARTED" },
// "second": { recording_id: "14399bf0...", state: "STARTED" },
// "third": { recording_id: "1f46bbf7...", state: "STARTED" }
// }
// Switch to another media stream.
await eyeson.switchStream({
'first': newFirstStream // Stream id must already exist
});
// Remove stream by its Id (recording will be stopped and uploaded)
await eyeson.removeStream('third');
// Ensure Recording is started and has not yet been stopped before stopping
// the recording or switching the stream.
await eyeson.stopRecording();
// Disconnect the client session.
await eyeson.disconnect();
} catch(err) {
console.error(err);
}
}()
The termination_cause property is one of the following codes:
CONN_ERROR... generic connection errorCONN_TIMEOUT... connection timeout, client network problemsTERM_BY_CLIENT... terminated by clientAGENT_SESSION_TERM... the monitored agent session was stoppedPEERCONN_FAILED... the peer-connection failedSDP_ERROR... the SDP could not be processedSERVICE_SHUTDOWN... streamrec service is shutting downNO_ACTIVE_AGENT... no active agent exists for the specifiec client-idTWO_TIMER... agent or supervisor already has an active sessionMAX_SUPERVISORS_PER_AGENT... limit of monitoring sessions reachedNO_PACKET_RECEIVED... connection timeout due to missing media packets
Supervisor
A supervisor requires to have a proper client identifier and an authentication
token in order to connect to the eyeson service. Ensure the supervisor is
allowed to monitor the agent when fetching the authentication token at the
/auth_v2/ endpoint.
import { Supervisor as eyeson } from 'eyeson-streamrec';
async function() {
try {
eyeson.addEventListener(event => {
const { type } = event;
console.debug('[Supervisor] Event received:', type)
if (type === 'disconnected') {
setConnected(false);
console.info(event.termination_cause);
}
if (type === 'add_stream') {
showStream(event.id, event.stream);
}
if (type === 'remove_stream') {
removeStream(event.id);
}
});
await eyeson.connect(supervisorId, authToken, agentId, webhookUrl);
setConnected(true);
setTimeout(eyeson.disconnect, 30 * 1000); // just an example
} catch(err) {
console.error(err);
}
}()