{"version":3,"sources":["src/common.speech/TranscriptionServiceRecognizer.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,YAAY,EACZ,WAAW,EAEd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,qBAAqB,EACrB,kBAAkB,EAQrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAMH,qBAAqB,EAGrB,qBAAqB,EACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAG7E,qBAAa,8BAA+B,SAAQ,qBAAqB;IAErE,OAAO,CAAC,yBAAyB,CAAwB;gBAGrD,cAAc,EAAE,eAAe,EAC/B,iBAAiB,EAAE,kBAAkB,EACrC,WAAW,EAAE,YAAY,EACzB,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,qBAAqB;IAMzB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;cAOzE,2BAA2B,CAAC,iBAAiB,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC;IA+HzG,SAAS,CAAC,iBAAiB,CACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,kBAAkB,EACtC,SAAS,EAAE,qBAAqB,EAChC,KAAK,EAAE,MAAM,GAAG,IAAI;cAwCR,0BAA0B,CAAC,UAAU,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IASlF,SAAS,CAAC,eAAe,eAAgB,WAAW;;UAAmC,OAAO,CAAC,IAAI,CAAC,CAYnG;IAED,OAAO,CAAC,wBAAwB;CAWnC","file":"TranscriptionServiceRecognizer.d.ts","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\r\n// Licensed under the MIT license.\r\n\r\nimport {\r\n    IAudioSource,\r\n    IConnection,\r\n    MessageType\r\n} from \"../common/Exports\";\r\nimport {\r\n    CancellationErrorCode,\r\n    CancellationReason,\r\n    ConversationTranscriptionCanceledEventArgs,\r\n    OutputFormat,\r\n    PropertyCollection,\r\n    PropertyId,\r\n    ResultReason,\r\n    SpeechRecognitionEventArgs,\r\n    SpeechRecognitionResult,\r\n} from \"../sdk/Exports\";\r\nimport { ConversationInfo } from \"../sdk/Transcription/Exports\";\r\nimport {\r\n    CancellationErrorCodePropertyName,\r\n    DetailedSpeechPhrase,\r\n    EnumTranslation,\r\n    OutputFormatPropertyName,\r\n    RecognitionStatus,\r\n    ServiceRecognizerBase,\r\n    SimpleSpeechPhrase,\r\n    SpeechHypothesis,\r\n    TranscriberRecognizer\r\n} from \"./Exports\";\r\nimport { IAuthentication } from \"./IAuthentication\";\r\nimport { IConnectionFactory } from \"./IConnectionFactory\";\r\nimport { RecognizerConfig } from \"./RecognizerConfig\";\r\nimport { SpeechConnectionMessage } from \"./SpeechConnectionMessage.Internal\";\r\n\r\n// tslint:disable-next-line:max-classes-per-file\r\nexport class TranscriptionServiceRecognizer extends ServiceRecognizerBase {\r\n\r\n    private privTranscriberRecognizer: TranscriberRecognizer;\r\n\r\n    public constructor(\r\n        authentication: IAuthentication,\r\n        connectionFactory: IConnectionFactory,\r\n        audioSource: IAudioSource,\r\n        recognizerConfig: RecognizerConfig,\r\n        transcriber: TranscriberRecognizer) {\r\n        super(authentication, connectionFactory, audioSource, recognizerConfig, transcriber);\r\n        this.privTranscriberRecognizer = transcriber;\r\n        this.sendPrePayloadJSONOverride = this.sendTranscriptionStartJSON;\r\n    }\r\n\r\n    public async sendSpeechEventAsync(info: ConversationInfo, command: string): Promise<void> {\r\n        if (!!this.privRequestSession.isRecognizing) {\r\n            const connection: IConnection = await this.fetchConnection();\r\n            await this.sendSpeechEvent(connection, this.createSpeechEventPayload(info, command));\r\n        }\r\n    }\r\n\r\n    protected async processTypeSpecificMessages(connectionMessage: SpeechConnectionMessage): Promise<boolean> {\r\n\r\n        let result: SpeechRecognitionResult;\r\n        const resultProps: PropertyCollection = new PropertyCollection();\r\n        resultProps.setProperty(PropertyId.SpeechServiceResponse_JsonResult, connectionMessage.textBody);\r\n        let processed: boolean = false;\r\n\r\n        switch (connectionMessage.path.toLowerCase()) {\r\n            case \"speech.hypothesis\":\r\n            case \"speech.fragment\":\r\n                const hypothesis: SpeechHypothesis = SpeechHypothesis.fromJSON(connectionMessage.textBody);\r\n                const offset: number = hypothesis.Offset + this.privRequestSession.currentTurnAudioOffset;\r\n\r\n                result = new SpeechRecognitionResult(\r\n                    this.privRequestSession.requestId,\r\n                    ResultReason.RecognizingSpeech,\r\n                    hypothesis.Text,\r\n                    hypothesis.Duration,\r\n                    offset,\r\n                    hypothesis.Language,\r\n                    hypothesis.LanguageDetectionConfidence,\r\n                    hypothesis.SpeakerId,\r\n                    undefined,\r\n                    connectionMessage.textBody,\r\n                    resultProps);\r\n\r\n                this.privRequestSession.onHypothesis(offset);\r\n\r\n                const ev = new SpeechRecognitionEventArgs(result, hypothesis.Duration, this.privRequestSession.sessionId);\r\n\r\n                if (!!this.privTranscriberRecognizer.recognizing) {\r\n                    try {\r\n                        this.privTranscriberRecognizer.recognizing(this.privTranscriberRecognizer, ev);\r\n                        /* tslint:disable:no-empty */\r\n                    } catch (error) {\r\n                        // Not going to let errors in the event handler\r\n                        // trip things up.\r\n                    }\r\n                }\r\n                processed = true;\r\n                break;\r\n            case \"speech.phrase\":\r\n                const simple: SimpleSpeechPhrase = SimpleSpeechPhrase.fromJSON(connectionMessage.textBody);\r\n                const resultReason: ResultReason = EnumTranslation.implTranslateRecognitionResult(simple.RecognitionStatus);\r\n\r\n                this.privRequestSession.onPhraseRecognized(this.privRequestSession.currentTurnAudioOffset + simple.Offset + simple.Duration);\r\n\r\n                if (ResultReason.Canceled === resultReason) {\r\n                    const cancelReason: CancellationReason = EnumTranslation.implTranslateCancelResult(simple.RecognitionStatus);\r\n                    const cancellationErrorCode: CancellationErrorCode = EnumTranslation.implTranslateCancelErrorCode(simple.RecognitionStatus);\r\n\r\n                    await this.cancelRecognitionLocal(\r\n                        cancelReason,\r\n                        cancellationErrorCode,\r\n                        EnumTranslation.implTranslateErrorDetails(cancellationErrorCode));\r\n\r\n                } else {\r\n                    if (!(this.privRequestSession.isSpeechEnded && resultReason === ResultReason.NoMatch && simple.RecognitionStatus !== RecognitionStatus.InitialSilenceTimeout)) {\r\n                        if (this.privRecognizerConfig.parameters.getProperty(OutputFormatPropertyName) === OutputFormat[OutputFormat.Simple]) {\r\n                            result = new SpeechRecognitionResult(\r\n                                this.privRequestSession.requestId,\r\n                                resultReason,\r\n                                simple.DisplayText,\r\n                                simple.Duration,\r\n                                simple.Offset + this.privRequestSession.currentTurnAudioOffset,\r\n                                simple.Language,\r\n                                simple.LanguageDetectionConfidence,\r\n                                simple.SpeakerId,\r\n                                undefined,\r\n                                connectionMessage.textBody,\r\n                                resultProps);\r\n                        } else {\r\n                            const detailed: DetailedSpeechPhrase = DetailedSpeechPhrase.fromJSON(connectionMessage.textBody);\r\n                            const totalOffset: number = detailed.Offset + this.privRequestSession.currentTurnAudioOffset;\r\n                            const offsetCorrectedJson: string = detailed.getJsonWithCorrectedOffsets(totalOffset);\r\n\r\n                            result = new SpeechRecognitionResult(\r\n                                this.privRequestSession.requestId,\r\n                                resultReason,\r\n                                detailed.Text,\r\n                                detailed.Duration,\r\n                                totalOffset,\r\n                                detailed.Language,\r\n                                detailed.LanguageDetectionConfidence,\r\n                                detailed.SpeakerId,\r\n                                undefined,\r\n                                offsetCorrectedJson,\r\n                                resultProps);\r\n                        }\r\n\r\n                        const event: SpeechRecognitionEventArgs = new SpeechRecognitionEventArgs(result, result.offset, this.privRequestSession.sessionId);\r\n\r\n                        if (!!this.privTranscriberRecognizer.recognized) {\r\n                            try {\r\n                                this.privTranscriberRecognizer.recognized(this.privTranscriberRecognizer, event);\r\n                                /* tslint:disable:no-empty */\r\n                            } catch (error) {\r\n                                // Not going to let errors in the event handler\r\n                                // trip things up.\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    if (!!this.privSuccessCallback) {\r\n                        try {\r\n                            this.privSuccessCallback(result);\r\n                        } catch (e) {\r\n                            if (!!this.privErrorCallback) {\r\n                                this.privErrorCallback(e);\r\n                            }\r\n                        }\r\n                        // Only invoke the call back once.\r\n                        // and if it's successful don't invoke the\r\n                        // error after that.\r\n                        this.privSuccessCallback = undefined;\r\n                        this.privErrorCallback = undefined;\r\n                    }\r\n                }\r\n                processed = true;\r\n                break;\r\n            default:\r\n                break;\r\n        }\r\n        return processed;\r\n    }\r\n\r\n    // Cancels recognition.\r\n    protected cancelRecognition(\r\n        sessionId: string,\r\n        requestId: string,\r\n        cancellationReason: CancellationReason,\r\n        errorCode: CancellationErrorCode,\r\n        error: string): void {\r\n\r\n        const properties: PropertyCollection = new PropertyCollection();\r\n        properties.setProperty(CancellationErrorCodePropertyName, CancellationErrorCode[errorCode]);\r\n\r\n        if (!!this.privTranscriberRecognizer.canceled) {\r\n            const cancelEvent: ConversationTranscriptionCanceledEventArgs = new ConversationTranscriptionCanceledEventArgs(\r\n                cancellationReason,\r\n                error,\r\n                errorCode,\r\n                undefined,\r\n                sessionId);\r\n            try {\r\n                this.privTranscriberRecognizer.canceled(this.privTranscriberRecognizer, cancelEvent);\r\n                /* tslint:disable:no-empty */\r\n            } catch { }\r\n        }\r\n\r\n        if (!!this.privSuccessCallback) {\r\n            const result: SpeechRecognitionResult = new SpeechRecognitionResult(\r\n                requestId,\r\n                ResultReason.Canceled,\r\n                undefined, // Text\r\n                undefined, // Duration\r\n                undefined, // Offset\r\n                undefined, // Language\r\n                undefined, // Language Detection Confidence\r\n                undefined, // Speaker Id\r\n                error,\r\n                undefined, // Json\r\n                properties);\r\n            try {\r\n                this.privSuccessCallback(result);\r\n                this.privSuccessCallback = undefined;\r\n                /* tslint:disable:no-empty */\r\n            } catch { }\r\n        }\r\n    }\r\n\r\n    // Encapsulated for derived service recognizers that need to send additional JSON\r\n    protected async sendTranscriptionStartJSON(connection: IConnection): Promise<void> {\r\n        await this.sendSpeechContext(connection);\r\n        const info: ConversationInfo = this.privTranscriberRecognizer.getConversationInfo();\r\n        const payload: { [id: string]: any } = this.createSpeechEventPayload(info, \"start\");\r\n        await this.sendSpeechEvent(connection, payload);\r\n        await this.sendWaveHeader(connection);\r\n        return;\r\n    }\r\n\r\n    protected sendSpeechEvent = (connection: IConnection, payload: { [id: string]: any }): Promise<void> => {\r\n        const speechEventJson = JSON.stringify(payload);\r\n\r\n        if (speechEventJson) {\r\n            return connection.send(new SpeechConnectionMessage(\r\n                MessageType.Text,\r\n                \"speech.event\",\r\n                this.privRequestSession.requestId,\r\n                \"application/json\",\r\n                speechEventJson));\r\n        }\r\n        return;\r\n    }\r\n\r\n    private createSpeechEventPayload(info: ConversationInfo, command: string): { [id: string]: any } {\r\n        const meeting: string = \"meeting\";\r\n        const eventDict: { [id: string]: any } = { id: meeting, name: command, meeting: info.conversationProperties };\r\n        const idString: string = \"id\";\r\n        const attendees: string = \"attendees\";\r\n        const record: string = \"record\";\r\n        eventDict[meeting][idString] = info.id;\r\n        eventDict[meeting][attendees] = info.participants;\r\n        eventDict[meeting][record] = info.conversationProperties.audiorecording === \"on\" ? \"true\" : \"false\";\r\n        return eventDict;\r\n    }\r\n}\r\n"]}