UNPKG

@voice-ping/cognitive-services-speech

Version:

VoicePing Cognitive Services Speech SDK for JavaScript forked from Microsoft

448 lines (446 loc) 24.2 kB
"use strict"; // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. Object.defineProperty(exports, "__esModule", { value: true }); var Exports_1 = require("../common/Exports"); var Exports_2 = require("../sdk/Exports"); var Exports_3 = require("./Exports"); var SpeechConnectionMessage_Internal_1 = require("./SpeechConnectionMessage.Internal"); var SynthesisAdapterBase = /** @class */ (function () { function SynthesisAdapterBase(authentication, connectionFactory, synthesizerConfig, speechSynthesizer, audioDestination) { var _this = this; this.speakOverride = undefined; this.receiveMessageOverride = undefined; this.connectImplOverride = undefined; this.configConnectionOverride = undefined; this.fetchConnectionOverride = undefined; this.receiveMessage = function () { return _this.fetchConnection().on(function (connection) { return connection.read() .onSuccessContinueWithPromise(function (message) { if (_this.receiveMessageOverride !== undefined) { return _this.receiveMessageOverride(); } if (_this.privIsDisposed) { // We're done. return Exports_1.PromiseHelper.fromResult(undefined); } // indicates we are draining the queue and it came with no message; if (!message) { if (!_this.privSynthesisTurn.isSynthesizing) { return Exports_1.PromiseHelper.fromResult(true); } else { return _this.receiveMessage(); } } _this.privServiceHasSentMessage = true; var connectionMessage = SpeechConnectionMessage_Internal_1.SpeechConnectionMessage.fromConnectionMessage(message); if (connectionMessage.requestId.toLowerCase() === _this.privSynthesisTurn.requestId.toLowerCase()) { switch (connectionMessage.path.toLowerCase()) { case "turn.start": _this.privSynthesisTurn.onServiceTurnStartResponse(); break; case "response": _this.privSynthesisTurn.onServiceResponseMessage(connectionMessage.textBody); break; case "audio": if (_this.privSynthesisTurn.streamId.toLowerCase() === connectionMessage.streamId.toLowerCase() && !!connectionMessage.binaryBody) { _this.privSynthesisTurn.onAudioChunkReceived(connectionMessage.binaryBody); if (!!_this.privSpeechSynthesizer.synthesizing) { try { var audioWithHeader = SynthesisAdapterBase.addHeader(connectionMessage.binaryBody, _this.privSynthesisTurn.audioOutputFormat); var ev = new Exports_2.SpeechSynthesisEventArgs(new Exports_2.SpeechSynthesisResult(_this.privSynthesisTurn.requestId, Exports_2.ResultReason.SynthesizingAudio, audioWithHeader)); _this.privSpeechSynthesizer.synthesizing(_this.privSpeechSynthesizer, ev); } catch (error) { // Not going to let errors in the event handler // trip things up. } } if (_this.privSessionAudioDestination !== undefined) { _this.privSessionAudioDestination.write(connectionMessage.binaryBody); } } break; case "audio.metadata": var metadataList = Exports_3.SynthesisAudioMetadata.fromJSON(connectionMessage.textBody).Metadata; for (var _i = 0, metadataList_1 = metadataList; _i < metadataList_1.length; _i++) { var metadata = metadataList_1[_i]; if (metadata.Type.toLowerCase() === "WordBoundary".toLowerCase()) { _this.privSynthesisTurn.onWordBoundaryEvent(metadata.Data.text.Text); var ev = new Exports_2.SpeechSynthesisWordBoundaryEventArgs(metadata.Data.Offset, metadata.Data.text.Text, metadata.Data.text.Length, _this.privSynthesisTurn.currentTextOffset); if (!!_this.privSpeechSynthesizer.wordBoundary) { try { _this.privSpeechSynthesizer.wordBoundary(_this.privSpeechSynthesizer, ev); } catch (error) { // Not going to let errors in the event handler // trip things up. } } } } break; case "turn.end": _this.privSynthesisTurn.onServiceTurnEndResponse(); var result = void 0; try { result = new Exports_2.SpeechSynthesisResult(_this.privSynthesisTurn.requestId, Exports_2.ResultReason.SynthesizingAudioCompleted, _this.privSynthesisTurn.allReceivedAudioWithHeader); if (!!_this.privSuccessCallback) { _this.privSuccessCallback(result); } } catch (error) { if (!!_this.privErrorCallback) { _this.privErrorCallback(error); } } if (_this.privSpeechSynthesizer.synthesisCompleted) { try { _this.privSpeechSynthesizer.synthesisCompleted(_this.privSpeechSynthesizer, new Exports_2.SpeechSynthesisEventArgs(result)); } catch (e) { // Not going to let errors in the event handler // trip things up. } } break; default: if (!_this.processTypeSpecificMessages(connectionMessage)) { // here are some messages that the derived class has not processed, dispatch them to connect class if (!!_this.privServiceEvents) { _this.serviceEvents.onEvent(new Exports_1.ServiceEvent(connectionMessage.path.toLowerCase(), connectionMessage.textBody)); } } } } return _this.receiveMessage(); }); }, function (error) { }); }; this.sendSynthesisContext = function (connection) { var synthesisContextJson = _this.synthesisContext.toJSON(); if (synthesisContextJson) { return connection.send(new SpeechConnectionMessage_Internal_1.SpeechConnectionMessage(Exports_1.MessageType.Text, "synthesis.context", _this.privSynthesisTurn.requestId, "application/json", synthesisContextJson)); } return Exports_1.PromiseHelper.fromResult(true); }; this.sendSpeechServiceConfig = function (connection, SpeechServiceConfigJson) { if (SpeechServiceConfigJson) { return connection.send(new SpeechConnectionMessage_Internal_1.SpeechConnectionMessage(Exports_1.MessageType.Text, "speech.config", _this.privSynthesisTurn.requestId, "application/json", SpeechServiceConfigJson)); } return Exports_1.PromiseHelper.fromResult(true); }; this.sendSsmlMessage = function (connection, ssml, requestId) { return connection.send(new SpeechConnectionMessage_Internal_1.SpeechConnectionMessage(Exports_1.MessageType.Text, "ssml", requestId, "application/ssml+xml", ssml)); }; this.fetchConnection = function () { if (_this.fetchConnectionOverride !== undefined) { return _this.fetchConnectionOverride(); } return _this.configureConnection(); }; if (!authentication) { throw new Exports_1.ArgumentNullError("authentication"); } if (!connectionFactory) { throw new Exports_1.ArgumentNullError("connectionFactory"); } if (!synthesizerConfig) { throw new Exports_1.ArgumentNullError("synthesizerConfig"); } this.privAuthentication = authentication; this.privConnectionFactory = connectionFactory; this.privSynthesizerConfig = synthesizerConfig; this.privIsDisposed = false; this.privSpeechSynthesizer = speechSynthesizer; this.privSessionAudioDestination = audioDestination; this.privSynthesisTurn = new Exports_3.SynthesisTurn(); this.privConnectionEvents = new Exports_1.EventSource(); this.privServiceEvents = new Exports_1.EventSource(); this.privSynthesisContext = new Exports_3.SynthesisContext(this.privSpeechSynthesizer); this.privAgentConfig = new Exports_3.AgentConfig(); this.connectionEvents.attach(function (connectionEvent) { if (connectionEvent.name === "ConnectionClosedEvent") { var connectionClosedEvent = connectionEvent; _this.cancelSynthesisLocal(Exports_2.CancellationReason.Error, connectionClosedEvent.statusCode === 1007 ? Exports_2.CancellationErrorCode.BadRequestParameters : Exports_2.CancellationErrorCode.ConnectionFailure, connectionClosedEvent.reason + " websocket error code: " + connectionClosedEvent.statusCode); } }); } Object.defineProperty(SynthesisAdapterBase.prototype, "synthesisContext", { get: function () { return this.privSynthesisContext; }, enumerable: true, configurable: true }); Object.defineProperty(SynthesisAdapterBase.prototype, "agentConfig", { get: function () { return this.privAgentConfig; }, enumerable: true, configurable: true }); Object.defineProperty(SynthesisAdapterBase.prototype, "connectionEvents", { get: function () { return this.privConnectionEvents; }, enumerable: true, configurable: true }); Object.defineProperty(SynthesisAdapterBase.prototype, "serviceEvents", { get: function () { return this.privServiceEvents; }, enumerable: true, configurable: true }); Object.defineProperty(SynthesisAdapterBase.prototype, "activityTemplate", { get: function () { return this.privActivityTemplate; }, set: function (messagePayload) { this.privActivityTemplate = messagePayload; }, enumerable: true, configurable: true }); Object.defineProperty(SynthesisAdapterBase.prototype, "audioOutputFormat", { set: function (format) { this.privAudioOutputFormat = format; this.privSynthesisTurn.audioOutputFormat = format; if (this.privSessionAudioDestination !== undefined) { this.privSessionAudioDestination.format = format; } if (this.synthesisContext !== undefined) { this.synthesisContext.audioOutputFormat = format; } }, enumerable: true, configurable: true }); SynthesisAdapterBase.addHeader = function (audio, format) { if (!format.hasHeader) { return audio; } format.updateHeader(audio.byteLength); var tmp = new Uint8Array(audio.byteLength + format.header.byteLength); tmp.set(new Uint8Array(format.header), 0); tmp.set(new Uint8Array(audio), format.header.byteLength); return tmp.buffer; }; SynthesisAdapterBase.prototype.isDisposed = function () { return this.privIsDisposed; }; SynthesisAdapterBase.prototype.dispose = function (reason) { this.privIsDisposed = true; if (this.privSessionAudioDestination !== undefined) { this.privSessionAudioDestination.close(); } if (this.privConnectionConfigurationPromise) { this.privConnectionConfigurationPromise.onSuccessContinueWith(function (connection) { connection.dispose(reason); }); } }; SynthesisAdapterBase.prototype.connect = function () { this.connectImpl().result(); }; SynthesisAdapterBase.prototype.connectAsync = function (cb, err) { this.connectImpl().continueWith(function (promiseResult) { try { if (promiseResult.isError) { if (!!err) { err(promiseResult.error); } } else if (promiseResult.isCompleted) { if (!!cb) { cb(); } } } catch (e) { if (!!err) { err(e); } } }); }; SynthesisAdapterBase.prototype.sendNetworkMessage = function (path, payload, success, err) { var _this = this; var type = typeof payload === "string" ? Exports_1.MessageType.Text : Exports_1.MessageType.Binary; var contentType = typeof payload === "string" ? "application/json" : ""; this.fetchConnection().on(function (connection) { connection.send(new SpeechConnectionMessage_Internal_1.SpeechConnectionMessage(type, path, _this.privSynthesisTurn.requestId, contentType, payload)).on(function () { if (!!success) { success(); } }, function (error) { if (!!err) { err(error); } }); }, function (error) { if (!!err) { err(error); } }); }; SynthesisAdapterBase.prototype.Speak = function (text, isSSML, requestId, successCallback, errorCallBack, audioDestination) { var _this = this; var ssml; if (isSSML) { ssml = text; } else { ssml = this.privSpeechSynthesizer.buildSsml(text); } if (this.speakOverride !== undefined) { return this.speakOverride(ssml, requestId, successCallback, errorCallBack); } this.privSuccessCallback = successCallback; this.privErrorCallback = errorCallBack; this.privSynthesisTurn.startNewSynthesis(requestId, text, isSSML, audioDestination); return this.fetchConnection().continueWithPromise(function (connection) { if (connection.isError) { _this.cancelSynthesisLocal(Exports_2.CancellationReason.Error, Exports_2.CancellationErrorCode.ConnectionFailure, connection.error); return Exports_1.PromiseHelper.fromError(connection.error); } return _this.sendSynthesisContext(connection.result).continueWithPromise(function (result) { if (result.isError) { _this.cancelSynthesisLocal(Exports_2.CancellationReason.Error, Exports_2.CancellationErrorCode.ConnectionFailure, result.error); return Exports_1.PromiseHelper.fromError(result.error); } return _this.sendSsmlMessage(connection.result, ssml, requestId).continueWithPromise(function (result) { if (result.isError) { _this.cancelSynthesisLocal(Exports_2.CancellationReason.Error, Exports_2.CancellationErrorCode.ConnectionFailure, result.error); return Exports_1.PromiseHelper.fromError(result.error); } var synthesisStartEventArgs = new Exports_2.SpeechSynthesisEventArgs(new Exports_2.SpeechSynthesisResult(requestId, Exports_2.ResultReason.SynthesizingAudioStarted)); if (!!_this.privSpeechSynthesizer.synthesisStarted) { _this.privSpeechSynthesizer.synthesisStarted(_this.privSpeechSynthesizer, synthesisStartEventArgs); } var messageRetrievalPromise = _this.receiveMessage(); return Exports_1.PromiseHelper.fromResult(true); }); }); }); }; // Cancels synthesis. SynthesisAdapterBase.prototype.cancelSynthesis = function (requestId, cancellationReason, errorCode, error) { var properties = new Exports_2.PropertyCollection(); properties.setProperty(Exports_3.CancellationErrorCodePropertyName, Exports_2.CancellationErrorCode[errorCode]); var result = new Exports_2.SpeechSynthesisResult(requestId, Exports_2.ResultReason.Canceled, undefined, error, properties); if (!!this.privSpeechSynthesizer.SynthesisCanceled) { var cancelEvent = new Exports_2.SpeechSynthesisEventArgs(result); try { this.privSpeechSynthesizer.SynthesisCanceled(this.privSpeechSynthesizer, cancelEvent); /* tslint:disable:no-empty */ } catch (_a) { } } if (!!this.privSuccessCallback) { try { this.privSuccessCallback(result); /* tslint:disable:no-empty */ } catch (_b) { } } }; // Cancels synthesis. SynthesisAdapterBase.prototype.cancelSynthesisLocal = function (cancellationReason, errorCode, error) { if (!!this.privSynthesisTurn.isSynthesizing) { this.privSynthesisTurn.onStopSynthesizing(); this.cancelSynthesis(this.privSynthesisTurn.requestId, cancellationReason, errorCode, error); } }; SynthesisAdapterBase.prototype.processTypeSpecificMessages = function (connectionMessage, successCallback, errorCallBack) { return true; }; // Establishes a websocket connection to the end point. SynthesisAdapterBase.prototype.connectImpl = function (isUnAuthorized) { var _this = this; if (isUnAuthorized === void 0) { isUnAuthorized = false; } if (this.connectImplOverride !== undefined) { return this.connectImplOverride(isUnAuthorized); } if (this.privConnectionPromise) { if (this.privConnectionPromise.result().isCompleted && (this.privConnectionPromise.result().isError || this.privConnectionPromise.result().result.state() === Exports_1.ConnectionState.Disconnected) && this.privServiceHasSentMessage === true) { this.privConnectionId = null; this.privConnectionPromise = null; this.privServiceHasSentMessage = false; return this.connectImpl(); } else { return this.privConnectionPromise; } } this.privAuthFetchEventId = Exports_1.createNoDashGuid(); this.privConnectionId = Exports_1.createNoDashGuid(); this.privSynthesisTurn.onPreConnectionStart(this.privAuthFetchEventId, this.privConnectionId); var authPromise = isUnAuthorized ? this.privAuthentication.fetchOnExpiry(this.privAuthFetchEventId) : this.privAuthentication.fetch(this.privAuthFetchEventId); this.privConnectionPromise = authPromise .continueWithPromise(function (result) { if (result.isError) { _this.privSynthesisTurn.onAuthCompleted(true, result.error); throw new Error(result.error); } else { _this.privSynthesisTurn.onAuthCompleted(false); } var connection = _this.privConnectionFactory.create(_this.privSynthesizerConfig, result.result, _this.privConnectionId); // Attach to the underlying event. No need to hold onto the detach pointers as in the event the connection goes away, // it'll stop sending events. connection.events.attach(function (event) { _this.connectionEvents.onEvent(event); }); return connection.open().onSuccessContinueWithPromise(function (response) { if (response.statusCode === 200) { _this.privSynthesisTurn.onPreConnectionStart(_this.privAuthFetchEventId, _this.privConnectionId); _this.privSynthesisTurn.onConnectionEstablishCompleted(response.statusCode); return Exports_1.PromiseHelper.fromResult(connection); } else if (response.statusCode === 403 && !isUnAuthorized) { return _this.connectImpl(true); } else { _this.privSynthesisTurn.onConnectionEstablishCompleted(response.statusCode, response.reason); return Exports_1.PromiseHelper.fromError("Unable to contact server. StatusCode: " + response.statusCode + ", " + _this.privSynthesizerConfig.parameters.getProperty(Exports_2.PropertyId.SpeechServiceConnection_Endpoint) + " Reason: " + response.reason); } }); }); return this.privConnectionPromise; }; // Takes an established websocket connection to the endpoint and sends speech configuration information. SynthesisAdapterBase.prototype.configureConnection = function () { var _this = this; if (this.configConnectionOverride !== undefined) { return this.configConnectionOverride(); } if (this.privConnectionConfigurationPromise) { if (this.privConnectionConfigurationPromise.result().isCompleted && (this.privConnectionConfigurationPromise.result().isError || this.privConnectionConfigurationPromise.result().result.state() === Exports_1.ConnectionState.Disconnected)) { this.privConnectionConfigurationPromise = null; return this.configureConnection(); } else { return this.privConnectionConfigurationPromise; } } this.privConnectionConfigurationPromise = this.connectImpl().onSuccessContinueWithPromise(function (connection) { return _this.sendSpeechServiceConfig(connection, _this.privSynthesizerConfig.SpeechServiceConfig.serialize()) .onSuccessContinueWith(function (_) { return connection; }); }); return this.privConnectionConfigurationPromise; }; SynthesisAdapterBase.telemetryDataEnabled = true; return SynthesisAdapterBase; }()); exports.SynthesisAdapterBase = SynthesisAdapterBase; //# sourceMappingURL=SynthesisAdapterBase.js.map