Skip to content

Commit

Permalink
feat: adding support for captions (#332)
Browse files Browse the repository at this point in the history
  • Loading branch information
manchuck authored Jun 11, 2024
1 parent 094995b commit d743baa
Show file tree
Hide file tree
Showing 4 changed files with 396 additions and 0 deletions.
131 changes: 131 additions & 0 deletions lib/captions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
const fetch = require('node-fetch');
const errors = require('./errors');
const pkg = require('../package.json');
const generateJwt = require('./generateJwt');
const generateHeaders = (config) => {
return {
'User-Agent': 'OpenTok-Node-SDK/' + pkg.version,
'X-OPENTOK-AUTH': generateJwt(config),
Accept: 'application/json',
};
};
const api = (config, method, path, body, callback) => {
const rurl = config.apiEndpoint + '/v2/project/' + config.apiKey + path;

const headers = generateHeaders(config);

if (body && ['POST', 'PATCH', 'PUT'].includes(method)) {
headers['Content-Type'] = 'application/json';
}

Promise.resolve(fetch(
rurl,
{
method: method,
body: body ? JSON.stringify(body) : null,
headers: headers,
}
))
.then(async (response) => {
const otResponse = {
statusCode: response.status,
}

const body = await response.text();

callback(null, otResponse, body)
})
.catch(async (error) => {
callback(error);
});
};

exports.startCaptions = (
config,
sessionId,
token,
{
languageCode = 'en-US',
maxDuration = 1800,
partialCaptions = true
},
callback,
) => {
if (typeof callback !== 'function') {
throw new errors.ArgumentError('No callback given to startCaptions');
}

api(
config,
'POST',
'/captions',
{
sessionId: sessionId,
token: token,
languageCode: languageCode,
maxDuration: maxDuration,
partialCaptions: partialCaptions,
},
(err, response, body) => {
if (err) {
callback(err);
return;
}

let responseJson = {};
try {
responseJson = JSON.parse(body);
} catch {

}
switch (response?.statusCode) {
case 200:
const { captionsId } = responseJson
callback(null, captionsId);
break;
case 400:
callback(new errors.RequestError(body));
break;
case 409:
callback(new errors.CaptionsError());
break;
default:
callback(new errors.RequestError('Unexpected response from OpenTok: ' + JSON.stringify({ statusCode: response.statusCode, statusMessage: response.statusMessage })));
}
}
);
};

exports.stopCaptions = (
config,
captionsId,
callback,
) => {
if (typeof callback !== 'function') {
throw new errors.ArgumentError('No callback given to stopArchive');
}

api(
config,
'POST',
`/captions/${captionsId}/stop`,
{},
(err, response, body) => {
if (err) {
callback(err);
return;
}

switch (response?.statusCode) {
case 202:
callback(null, true);
break;
case 400:
callback(new errors.NotFoundError(`No matching captions found for ${captionsId}`));
break;
default:
callback(new errors.RequestError('Unexpected response from OpenTok: ' + JSON.stringify({ statusCode: response.statusCode, statusMessage: response.statusMessage })));
}
}
);
};
3 changes: 3 additions & 0 deletions lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ exports.ArchiveError = function (message) {

exports.ArchiveError.prototype = Object.create(Error.prototype);

exports.CaptionsError = function (message = 'Live captions have already started for this OpenTok Session') {
this.message = message;
};

exports.SipError = function (message) {
this.message = message;
Expand Down
96 changes: 96 additions & 0 deletions lib/opentok.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var errors = require('./errors');
var callbacks = require('./callbacks');
var generateJwt = require('./generateJwt');
var render = require('./render.js');
var captions = require('./captions.js');
var OpenTok;
var key;

Expand Down Expand Up @@ -487,6 +488,100 @@ OpenTok = function (apiKey, apiSecret, env) {
);
};


/**
* Starts live captions for an OpenTok Session
* <p>
* The maximum allowed duration is 4 hours, after which the audio captioning will stop without
* any effect on the ongoing OpenTok Session. An event will be posted to your callback URL if
* provided when starting the captions.
* <p>
* Each OpenTok Session supports only one audio captioning session.
*
* @param sessionId The session ID of the OpenTok session to archive.
*
* @param token A valid OpenTok token with role set to Moderator.
*
* @param options {Object} An optional options object with the following properties (each
* of which is optional):
* <p>
* <ul>
* <li>
* <code>languageCode</code> (String) &mdash; The BCP-47 code for a spoken language used on
* this call. The default value is "en-US". The following language codes are supported:
* "en-AU" (English, Australia), "en-GB" (Englsh, UK), "es-US" (English, US),
* "zh-CN” (Chinese, Simplified), "fr-FR" (French), "fr-CA" (French, Canadian),
* "de-DE" (German), "hi-IN" (Hindi, Indian), "it-IT" (Italian), "ja-JP" (Japanese),
* "ko-KR" (Korean), "pt-BR" (Portuguese, Brazilian), "th-TH" (Thai).
* </li>
* <li>
* <code>maxDuration</code> (Integer) &mdash; The maximum duration for the audio captioning,
* in seconds. The default value is 14,400 seconds (4 hours), the maximum duration allowed.
* The minimum value for maxDuration is 300 (300 seconds, or 5 minutes).
* </li>
* <li>
* <code>partialCaptions</code> (Boolean) &mdash; Whether to enable this to faster captioning
* at the cost of some degree of inaccuracies. The default value is true.
* </li>
* </ul>
*
* For more information on captions, see the
* <a href="https://tokbox.com/developer/rest/#starting-live-captions">OpenTok captions</a>
* programming guide.
*
* @param callback {Function} The function to call upon completing the operation. Two arguments
* are passed to the function:
*
* <ul>
* <li>
* <code>error</code> &mdash; An error object (if the call to the method fails).
* </li>
*
* <li>
* <code>captionID</code> &mdash; The id of the captions
* </li>
*
* </ul>
*
* @method #startCaptions
* @memberof OpenTok
*/

this.startCaptions = captions.startCaptions.bind(null, apiConfig);


/**
* Stops live captions for an OpenTok Session
*
* @param captionId The session ID of the OpenTok session to archive.
*
* </ul>
*
* For more information on captions, see the
* <a href="https://tokbox.com/developer/rest/#starting-live-captions">OpenTok captions</a>
* programming guide.
*
* @param callback {Function} The function to call upon completing the operation. Two arguments
* are passed to the function:
*
* <ul>
* <li>
* <code>error</code> &mdash; An error object (if the call to the method fails).
* </li>
*
* <li>
* <code>success</code> &mdash; True always
* </li>
*
* </ul>
*
* @method #startCaptions
* @memberof OpenTok
*/

this.stopCaptions = captions.stopCaptions.bind(null, apiConfig);


/**
* Retrieves a List of {@link Render} objects, representing any renders in the starting,
* started, stopped or failed state, for your API key.
Expand Down Expand Up @@ -2106,6 +2201,7 @@ OpenTok.prototype.generateToken = function (sessionId, opts) {
}

return encodeToken(tokenData, this.apiKey, this.apiSecret);

};

/*
Expand Down
Loading

0 comments on commit d743baa

Please sign in to comment.