diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/audiocaptions/AudioCaptionsApp2x.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/audiocaptions/AudioCaptionsApp2x.scala index 93abe8bdb9..987aa4a216 100644 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/audiocaptions/AudioCaptionsApp2x.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/audiocaptions/AudioCaptionsApp2x.scala @@ -4,6 +4,7 @@ import akka.actor.ActorContext class AudioCaptionsApp2x(implicit val context: ActorContext) extends UpdateTranscriptPubMsgHdlr + with TranscriptionProviderErrorMsgHdlr with AudioFloorChangedVoiceConfEvtMsgHdlr { } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/audiocaptions/TranscriptionProviderErrorMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/audiocaptions/TranscriptionProviderErrorMsgHdlr.scala new file mode 100644 index 0000000000..a652050822 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/audiocaptions/TranscriptionProviderErrorMsgHdlr.scala @@ -0,0 +1,27 @@ +package org.bigbluebutton.core.apps.audiocaptions + +import org.bigbluebutton.common2.msgs._ +import org.bigbluebutton.core.bus.MessageBus +import org.bigbluebutton.core.models.AudioCaptions +import org.bigbluebutton.core.running.LiveMeeting + +trait TranscriptionProviderErrorMsgHdlr { + this: AudioCaptionsApp2x => + + def handleTranscriptionProviderErrorMsg(msg: TranscriptionProviderErrorMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = { + val meetingId = liveMeeting.props.meetingProp.intId + + def broadcastEvent(userId: String, errorCode: String, errorMessage: String): Unit = { + val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, meetingId, "nodeJSapp") + val envelope = BbbCoreEnvelope(TranscriptionProviderErrorEvtMsg.NAME, routing) + val header = BbbClientMsgHeader(TranscriptionProviderErrorEvtMsg.NAME, meetingId, userId) + val body = TranscriptionProviderErrorEvtMsgBody(errorCode, errorMessage) + val event = TranscriptionProviderErrorEvtMsg(header, body) + val msgEvent = BbbCommonEnvCoreMsg(envelope, event) + + bus.outGW.send(msgEvent) + } + + broadcastEvent(msg.header.userId, msg.body.errorCode, msg.body.errorMessage) + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala index 72f6df7592..76e0995b3d 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala @@ -406,6 +406,8 @@ class ReceivedJsonMsgHandlerActor( // AudioCaptions case UpdateTranscriptPubMsg.NAME => routeGenericMsg[UpdateTranscriptPubMsg](envelope, jsonNode) + case TranscriptionProviderErrorMsg.NAME => + routeGenericMsg[TranscriptionProviderErrorMsg](envelope, jsonNode) // GroupChats case GetGroupChatsReqMsg.NAME => diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala index 19b482b0a2..aa84f65a01 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala @@ -583,6 +583,7 @@ class MeetingActor( // AudioCaptions case m: UpdateTranscriptPubMsg => audioCaptionsApp2x.handle(m, liveMeeting, msgBus) + case m: TranscriptionProviderErrorMsg => audioCaptionsApp2x.handleTranscriptionProviderErrorMsg(m, liveMeeting, msgBus) // GroupChat case m: CreateGroupChatReqMsg => diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/AudioCaptionsMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/AudioCaptionsMsgs.scala index 495f325f45..64e6f672cd 100644 --- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/AudioCaptionsMsgs.scala +++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/AudioCaptionsMsgs.scala @@ -1,5 +1,12 @@ package org.bigbluebutton.common2.msgs +object TranscriptionProviderErrorMsg { val NAME = "TranscriptionProviderErrorMsg" } +case class TranscriptionProviderErrorMsg(header: BbbClientMsgHeader, body: TranscriptionProviderErrorMsgBody) extends StandardMsg +case class TranscriptionProviderErrorMsgBody( + errorCode: String, + errorMessage: String, +) + // In messages object UpdateTranscriptPubMsg { val NAME = "UpdateTranscriptPubMsg" } case class UpdateTranscriptPubMsg(header: BbbClientMsgHeader, body: UpdateTranscriptPubMsgBody) extends StandardMsg @@ -14,6 +21,10 @@ case class UpdateTranscriptPubMsgBody( ) // Out messages +object TranscriptionProviderErrorEvtMsg { val NAME = "TranscriptionProviderErrorEvtMsg" } +case class TranscriptionProviderErrorEvtMsg(header: BbbClientMsgHeader, body: TranscriptionProviderErrorEvtMsgBody) extends BbbCoreMsg +case class TranscriptionProviderErrorEvtMsgBody(errorCode: String, errorMessage: String) + object TranscriptUpdatedEvtMsg { val NAME = "TranscriptUpdatedEvtMsg" } case class TranscriptUpdatedEvtMsg(header: BbbClientMsgHeader, body: TranscriptUpdatedEvtMsgBody) extends BbbCoreMsg case class TranscriptUpdatedEvtMsgBody(transcriptId: String, transcript: String, locale: String, result: Boolean) diff --git a/bbb-transcription-controller.placeholder.sh b/bbb-transcription-controller.placeholder.sh index b4c9a4c1c9..136d4a7c28 100755 --- a/bbb-transcription-controller.placeholder.sh +++ b/bbb-transcription-controller.placeholder.sh @@ -1 +1 @@ -git clone --branch v0.2.1 --depth 1 https://github.com/bigbluebutton/bbb-transcription-controller bbb-transcription-controller +git clone --branch v0.2.3 --depth 1 https://github.com/bigbluebutton/bbb-transcription-controller bbb-transcription-controller diff --git a/bigbluebutton-html5/imports/api/audio-captions/server/eventHandlers.js b/bigbluebutton-html5/imports/api/audio-captions/server/eventHandlers.js index 9a8e2f1a96..1ac7583062 100644 --- a/bigbluebutton-html5/imports/api/audio-captions/server/eventHandlers.js +++ b/bigbluebutton-html5/imports/api/audio-captions/server/eventHandlers.js @@ -1,4 +1,6 @@ import RedisPubSub from '/imports/startup/server/redis'; import handleTranscriptUpdated from '/imports/api/audio-captions/server/handlers/transcriptUpdated'; +import handleTranscriptionProviderError from '/imports/api/audio-captions/server/handlers/transcriptionProviderError'; RedisPubSub.on('TranscriptUpdatedEvtMsg', handleTranscriptUpdated); +RedisPubSub.on('TranscriptionProviderErrorEvtMsg', handleTranscriptionProviderError); diff --git a/bigbluebutton-html5/imports/api/audio-captions/server/handlers/transcriptionProviderError.js b/bigbluebutton-html5/imports/api/audio-captions/server/handlers/transcriptionProviderError.js new file mode 100644 index 0000000000..ab5c5ae964 --- /dev/null +++ b/bigbluebutton-html5/imports/api/audio-captions/server/handlers/transcriptionProviderError.js @@ -0,0 +1,38 @@ +import Users from '/imports/api/users'; +import Logger from '/imports/startup/server/logger'; + +export default async function handleTranscriptionProviderError({ header, body }) { + const { + meetingId, + userId, + } = header; + + const selector = { + meetingId, + userId, + }; + + const { + errorCode, + errorMessage, + } = body; + + const modifier = { + $set: { + transcriptionError: { + code: errorCode, + message: errorMessage, + }, + }, + }; + + try { + const numberAffected = await Users.updateAsync(selector, modifier); + + if (numberAffected) { + Logger.error(`Transcription error errorCode=${errorCode} errorMessage=${errorMessage} meetingId=${meetingId}`); + } + } catch (err) { + Logger.error(`Problem setting transcription error: ${err}`); + } +} diff --git a/bigbluebutton-html5/imports/ui/components/audio/captions/service.js b/bigbluebutton-html5/imports/ui/components/audio/captions/service.js index 2a85ba5b36..008852006b 100644 --- a/bigbluebutton-html5/imports/ui/components/audio/captions/service.js +++ b/bigbluebutton-html5/imports/ui/components/audio/captions/service.js @@ -4,7 +4,7 @@ import Auth from '/imports/ui/services/auth'; const CAPTIONS_CONFIG = Meteor.settings.public.captions; const CAPTIONS_ALWAYS_VISIBLE = Meteor.settings.public.app.audioCaptions.alwaysVisible; const CHARACTERS_PER_LINE = CAPTIONS_CONFIG.lineLimit; -const LINES_PER_MESSAGE = CAPTIONS_CONFIG.line; +const LINES_PER_MESSAGE = CAPTIONS_CONFIG.lines; const CAPTION_TIME = CAPTIONS_CONFIG.time; const CAPTION_LIMIT = CAPTIONS_CONFIG.captionLimit; @@ -29,7 +29,9 @@ function splitTranscript(obj) { } } - transcripts.push(result) + if (result.length) { + transcripts.push(result) + } transcripts.push(currentLine.trim()) return transcripts.map((t) => { return { ...obj, transcript: t} }); diff --git a/bigbluebutton-html5/imports/ui/components/audio/captions/speech/service.js b/bigbluebutton-html5/imports/ui/components/audio/captions/speech/service.js index f2fd6ddbad..66750d1078 100644 --- a/bigbluebutton-html5/imports/ui/components/audio/captions/speech/service.js +++ b/bigbluebutton-html5/imports/ui/components/audio/captions/speech/service.js @@ -59,10 +59,24 @@ const setSpeechLocale = (value) => { } }; +const setDefaultLocale = () => { + if (useFixedLocale() || localeAsDefaultSelected()) { + setSpeechLocale(getLocale()); + } else { + setSpeechLocale(navigator.language); + } +} + const useFixedLocale = () => isEnabled() && CONFIG.language.forceLocale; const initSpeechRecognition = () => { - if (!isEnabled() || !isWebSpeechApi()) return null; + if (!isEnabled()) return null; + + if (!isWebSpeechApi()) { + setDefaultLocale(); + return; + } + if (hasSpeechRecognitionSupport()) { // Effectivate getVoices setSpeechVoices(); @@ -70,11 +84,7 @@ const initSpeechRecognition = () => { speechRecognition.continuous = true; speechRecognition.interimResults = true; - if (useFixedLocale() || localeAsDefaultSelected()) { - setSpeechLocale(getLocale()); - } else { - setSpeechLocale(navigator.language); - } + setDefaultLocale(); return speechRecognition; } diff --git a/bigbluebutton-html5/imports/ui/components/captions/component.jsx b/bigbluebutton-html5/imports/ui/components/captions/component.jsx index 319ce3a403..b7ab128656 100644 --- a/bigbluebutton-html5/imports/ui/components/captions/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/captions/component.jsx @@ -92,7 +92,8 @@ const Captions = ({ 'aria-label': intl.formatMessage(intlMessages.hide), label: autoTranscription ? intl.formatMessage(intlMessages.title) : name, }} - customRightButton={Service.amICaptionsOwner(ownerId) ? ( + customRightButton={dictation ? ( + Service.amICaptionsOwner(ownerId) ? ( {dictating @@ -111,7 +111,7 @@ const Captions = ({ : intl.formatMessage(intlMessages.dictationOnDesc)} - ) : ( + ) : ( - )} + )) : null} />