UNPKG

@itslanguage/api

Version:
121 lines (113 loc) 5.19 kB
import "core-js/modules/es.promise"; import "core-js/modules/es.promise.finally"; /** * This file contains the functions that are needed to interact with the ITSLanguage Speech * Feedback API. * * It's possible to get feedback while recording. After every sentence feedback is provided * indicating whether or not the sentence was read well. This will be done through the * ITSLanguage WebSocket Server. * * The general approach for getting real-time feedback is: * - Prepare the speech feedback * - Register audio procedure for streaming * - Start listening for audio * * To read up on the Speech feedback: * @see https://itslanguage.github.io/itslanguage-docs/websocket/feedback/index.html * * To read more on Speech Challenges: * @see https://itslanguage.github.io/itslanguage-docs/api/speech_challenges/index.html * * @module api/challenges/feedback/speech */ import { registerStreamForRecorder } from '../../utils/audio-over-socket'; import { makeWebsocketCall, closeWebsocketConnection } from '../../communication/websocket'; /** * Prepare a new Speech Feedback. * Should be called upon each new speech feedback. * The backend will generate an unique ID for the feedback and prepare a speech challenge. * * @param {string} challengeId - The ID of the challenge to prepare. * @returns {Promise} - The ID of the Speech Feedback. */ export function prepare(challengeId) { return makeWebsocketCall('feedback.prepare', { args: [challengeId] }); } /** * In order to receive feedback the server needs to listen for audio on a registered audio rpc. * While listening the server will reply using progressive results. The server will stop listening * when the audio rpc returns. * * If you call this function the SDK will register an RPC method to the realm on which audio will be * streamed to the backend. * * @param {string} feedbackId - The Id of the Feedback Challenge. * @param {Function} progressCb - A callback which will be used to receive progress on. * @param {MediaRecorder} recorder - Audio recorder instance. * @param {string} [dataEvent] - Optional the event to collect data from. * @returns {Promise} - After each sentence there will be real-time feedback on that sentence. This * feedback will be given through the progressiveResultsCb function. When the rpc is done, the * promise will return an recording with the appropriate feedback per sentence. */ export function listenAndReply(feedbackId, progressCb, recorder, dataEvent) { // Generate a somewhat unique RPC name var rpcNameToRegister = "feedback.stream." + Math.floor(Date.now() / 1000); // Below we use registration.procedure instead of rpcNameToRegister. This is because the later // lacks some namespace information that we do need. return registerStreamForRecorder(recorder, rpcNameToRegister, dataEvent).then(registration => makeWebsocketCall('feedback.listen_and_reply', { args: [feedbackId, registration.procedure], progressCb: progressCb.bind(null, feedbackId) })); } /** * Feedback can be paused. This will stop the backend from processing the audio stream and returning * feedback. * * Important note: Pausing the feedback will not stop the feedback. Also make sure to stop sending * data from the recorder to the backend. * * @param {string} feedbackId - The ID of the feedback to pause. * @returns {Promise} - An error if something went wrong. */ export function pause(feedbackId) { return makeWebsocketCall('feedback.pause', { args: [feedbackId] }); } /** * A paused feedback can be resumed at a sentence in the challenge. If not provided, it will resume * at the first sentence. * * @param {string} feedbackId - The ID of the feedback to resume. * @param {string} sentenceId - The ID of the sentence to resume feedback from. * @returns {Promise} - An error if something went wrong. */ export function resume(feedbackId, sentenceId) { if (sentenceId === void 0) { sentenceId = 0; } return makeWebsocketCall('feedback.resume', { args: [feedbackId, sentenceId] }); } /** * Function for convenience. Using this function calls the corresponding functions so that the * required backend flow is backed up. * * It will call the following functions (and more important, in the correct order): * - {@link prepare}. * - {@link listenAndReply}. * * @param {string} challengeId - The Id of the Challenge to get feedback on. * @param {Function} progressiveResultsCb - A callback which will be used to receive progress on. * @param {MediaRecorder} recorder - Audio recorder instance. * @param {string} dataEvent - The event to use to collect data from. * @returns {Promise} - After each sentence there will be real-time feedback on that sentence. This * feedback will be given through the progressiveResultsCb function. When the rpc is done, the * promise will return an recording with the appropriate feedback per sentence. */ export function feedback(challengeId, progressiveResultsCb, recorder, dataEvent) { return prepare(challengeId).then(feedbackId => listenAndReply(feedbackId, progressiveResultsCb, recorder, dataEvent)).finally(() => closeWebsocketConnection()); }