@itslanguage/api
Version:
The JavaScript API SDK for ITSLanguage.
168 lines (155 loc) • 7.44 kB
JavaScript
/**
* This file contains the readily available functions which interact with the
* ITSLanguage choice recognition API.
*
* Speech recognitions can be stored and retrieved for user submitted audio using the ITSLanguage
* Speech API. The actual recognitions are performed by the ITSLanguage websocket server.
*
* For streaming, note that this is one of the "nested" or "composite" APIs; You can only obtain the
* data if you provide a reference to the challenge for which you want a recording.
*
* @module api/challenges/choice/recognition
*/
import { registerStreamForRecorder, encodeAndSendAudioOnDataAvailable, prepareServerForAudio } from '../../utils/audio-over-socket';
import { authorisedRequest } from '../../communication';
import { makeWebsocketCall } from '../../communication/websocket';
/**
* The URL for the choice recognition challenge handler(s).
*
* @param challengeId
* @returns {string}
*/
var url = challengeId => "/challenges/choice/" + challengeId + "/recognitions";
/**
* Submit an audio fragment for recognition. The recognition is created for the current
* authenticated user.
*
* @see https://itslanguage.github.io/itslanguage-docs/api/recognitions/index.html#create-a-choice-recognition
* @param {string} challengeId - The ID of the challenge to relate the recognition to.
* @param {Blob} audio - The actual audio.
* @param {string} recognised - The recognised string.
* @param {string} [recognitionId=null] - Unique identifier for the recognition. If none is given,
* one is generated.
* @returns {Promise} - The created recognition with an url to download the audio if needed.
*/
export function create(challengeId, audio, recognised, recognitionId) {
if (recognitionId === void 0) {
recognitionId = null;
}
var recognition = {
audio,
recognised
};
if (recognitionId) {
recognition.id = recognitionId;
}
return authorisedRequest('POST', "" + url(challengeId), recognition);
}
/**
* Get a single ChoiceRecognition by its ID.
*
* @see https://itslanguage.github.io/itslanguage-docs/api/recognitions/index.html#get-a-single-choice-recognition
* @param {string} challengeId - ID of the Choice Challenge to get all the recognitions for.
* @param {string} id - ID of the choice recognition to get.
* @returns {Promise} - Promise with the Choice Recognition as result if successful.
*/
export function getById(challengeId, id) {
return authorisedRequest('GET', url(challengeId) + "/" + id);
}
/**
* Get all Choice Recognitions for a specific Choice Challenge.
*
* @see https://itslanguage.github.io/itslanguage-docs/api/recognitions/index.html#list-choice-recognitions
* @param {string} challengeId - ID of the Choice Challenge to get all the recognitions for.
* @returns {Promise} - Promise with the Choice Recognitions as result if successful.
*/
export function getAll(challengeId) {
return authorisedRequest('GET', "" + url(challengeId));
}
/**
* This is the starting point for a choice recognition. A unique recognition id is generated,
* which serves a leading role in the recognition. Each other call requires the recognition id
* as a parameter.
*
* If other RPCs are called without this RPC being called first, the error
* `nl.itslanguage.session_not_initialised` will be returned.
*
* @see https://itslanguage.github.io/itslanguage-docs/websocket/choice_recognitions/index.html#initialising-a-choice-recognition
* @returns {Promise} - Returns a promise. When successfully the ID of the recognition is returned.
*/
export function prepare() {
return makeWebsocketCall('choice.init_recognition');
}
/**
* Before performing the recognition, a WFST needs to be prepared for the challenge. When the RPC is
* called, the challenge is initialised asynchronously. When the challenge is to be used, the server
* automatically waits for the challenge initialisation to finish. If the initialisation results in
* an error, the error is relayed to the client.
*
* @see https://itslanguage.github.io/itslanguage-docs/websocket/choice_recognitions/index.html#initialise-choice-challenge
* @param {string} recognitionId - The ID of the recognition to prepare the challenge for.
* @param {string} challengeId - The ID of the challenge to prepare.
* @returns {Promise} - If succesful the promise returns nothing. On error, there will be an error.
*/
export function prepareChallenge(recognitionId, challengeId) {
return makeWebsocketCall('choice.init_challenge', {
args: [recognitionId, challengeId]
});
}
/**
* Based on a recognitionId and a recorder register a RPC call that will be used to send the audio
* across the line. The actual registration will not be done here, but we send the RPC that the
* backend needs to call to the 'nl.itslanguage.choice.recognise' function.
*
* @param {string} recognitionId - The ID of the recognition to send audio for.
* @param {MediaRecorder} recorder - Audio recorder instance.
* @returns {Promise} - When all good, the result will have the actual recognition.
*/
export function recogniseAudioStream(recognitionId, recorder) {
// Generate a somewhat unique RPC name
var rpcNameToRegister = "choice.stream." + Math.floor(Date.now() / 1000);
return registerStreamForRecorder(recorder, rpcNameToRegister) // We don't use rpcNameToRegister here because it lacks some namespacing info. The
// registration.procedure does have the needed information.
.then(registration => makeWebsocketCall('choice.recognise', {
args: [recognitionId, registration.procedure]
}));
}
/**
* Easy function to do a recognition in one go. This is the "dance of the RPC's" that needs to be
* done in order to get correct feedback from the backend.
*
* @param {string} challengeId - The ID of the challenge to take the recognition for.
* @param {MediaRecorder} recorder - Audio recorder instance.
* @returns {Promise<*>} - If all good it returns the actual recognition. If not, any error can be
* expected to be returned.
*/
export function recognise(challengeId, recorder) {
var recognitionId;
return prepare().then(rId => {
recognitionId = rId;
return rId;
}).then(() => prepareChallenge(recognitionId, challengeId)).then(() => recogniseAudioStream(recognitionId, recorder).then(result => result));
}
/**
* Easy function to do a recognition in one go. This is the "dance of the RPC's" that needs to be
* done in order to get correct feedback from the backend.
*
* This function is here to support possible old backend servers where we did not use the streaming
* for choice challenges yet. It is deprecated and will be removed in the first minor update of the
* api sdk.
*
* @deprecated
* @param {string} challengeId - The ID of the challenge to take the recognition for.
* @param {MediaRecorder} recorder - Audio recorder instance.
* @returns {Promise<*>} - If all good it returns the actual recognition. If not, any error can be
* expected to be returned.
*/
export function recogniseNonStreaming(challengeId, recorder) {
var recognitionId;
return prepare().then(rId => {
recognitionId = rId;
return rId;
}).then(() => prepareChallenge(recognitionId, challengeId)).then(() => prepareServerForAudio(recognitionId, recorder, 'choice.init_audio')).then(() => encodeAndSendAudioOnDataAvailable(recognitionId, recorder, 'choice.write')).then(() => makeWebsocketCall('choice.recognise', {
args: [recognitionId]
}));
}