From 0b7fefd90688a2d65dd591a8288ac55744b9650c Mon Sep 17 00:00:00 2001
From: Carlos Santos <4a.santos@gmail.com>
Date: Fri, 18 Nov 2022 11:54:38 +0100
Subject: [PATCH] openvidu-components: Added reconnection when STT disconnected
---
.../captions/captions.component.css | 16 +++
.../captions/captions.component.html | 6 +
.../components/captions/captions.component.ts | 54 +++++----
.../components/session/session.component.ts | 49 ++++----
.../settings/captions/captions.component.html | 2 +-
.../settings/captions/captions.component.ts | 21 +++-
.../openvidu-angular/src/lib/lang/cn.json | 3 +-
.../openvidu-angular/src/lib/lang/de.json | 3 +-
.../openvidu-angular/src/lib/lang/en.json | 3 +-
.../openvidu-angular/src/lib/lang/es.json | 3 +-
.../openvidu-angular/src/lib/lang/fr.json | 3 +-
.../openvidu-angular/src/lib/lang/hi.json | 3 +-
.../openvidu-angular/src/lib/lang/it.json | 3 +-
.../openvidu-angular/src/lib/lang/ja.json | 3 +-
.../openvidu-angular/src/lib/lang/nl.json | 3 +-
.../openvidu-angular/src/lib/lang/pt.json | 3 +-
.../lib/services/caption/caption.service.ts | 6 +-
.../lib/services/openvidu/openvidu.service.ts | 106 +++++++++++++++---
18 files changed, 209 insertions(+), 81 deletions(-)
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.css
index 6e302e3b..c5ff384e 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.css
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.css
@@ -26,6 +26,22 @@
padding: 0px 10vw 0px;
}
+.error-container {
+ display: grid;
+ text-align: center;
+ color: var(--ov-text-color);
+ font-size: 18px;
+}
+
+mat-spinner {
+ position: relative;
+ top: 35%;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ margin: auto;
+}
+
/*
* Screen XL
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.html
index b550a523..acc0316e 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.html
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.html
@@ -10,6 +10,7 @@
+
+
+ {{'ERRORS.SST_CONNECTION' | translate}}
+
+
= 600 && !settingsPanelOpened" class="captions-offset">
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.ts
index 257c47db..816f21aa 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.ts
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.ts
@@ -42,6 +42,7 @@ export class CaptionsComponent implements OnInit {
captionEvents: CaptionModel[] = [];
session: Session;
+ isSttReady: boolean = true;
private deleteFirstTimeout: NodeJS.Timeout;
private deleteAllTimeout: NodeJS.Timeout;
@@ -52,6 +53,8 @@ export class CaptionsComponent implements OnInit {
private captionLangSelected: { name: string; ISO: string };
private screenSizeSub: Subscription;
private panelTogglingSubscription: Subscription;
+ private sttStatusSubscription: Subscription;
+
constructor(
private panelService: PanelService,
@@ -62,14 +65,12 @@ export class CaptionsComponent implements OnInit {
) {}
async ngOnInit(): Promise {
+ this.subscribeToSTTStatus();
this.captionService.setCaptionsEnabled(true);
this.captionLangSelected = this.captionService.getLangSelected();
this.session = this.openviduService.getWebcamSession();
- for (const p of this.participantService.getRemoteParticipants()) {
- const stream = p.getCameraConnection().streamManager.stream;
- await this.session.subscribeToSpeechToText(stream, this.captionLangSelected.ISO);
- }
+ await this.openviduService.subscribeRemotesToSTT(this.captionLangSelected.ISO);
this.subscribeToCaptionLanguage();
this.subscribeToPanelToggling();
@@ -77,16 +78,14 @@ export class CaptionsComponent implements OnInit {
}
async ngOnDestroy() {
+ await this.openviduService.unsubscribeRemotesFromSTT();
this.captionService.setCaptionsEnabled(false);
if (this.screenSizeSub) this.screenSizeSub.unsubscribe();
if (this.panelTogglingSubscription) this.panelTogglingSubscription.unsubscribe();
+ if(this.sttStatusSubscription) this.sttStatusSubscription.unsubscribe();
this.session.off('speechToTextMessage');
this.captionEvents = [];
- for (const p of this.participantService.getRemoteParticipants()) {
- const stream = p.getCameraConnection().streamManager.stream;
- await this.session.unsubscribeFromSpeechToText(stream);
- }
}
onSettingsCliked() {
@@ -95,22 +94,24 @@ export class CaptionsComponent implements OnInit {
private subscribeToTranscription() {
this.session.on('speechToTextMessage', (event: SpeechToTextEvent) => {
- clearInterval(this.deleteAllTimeout);
- const { connectionId, data } = event.connection;
- const nickname: string = this.participantService.getNicknameFromConnectionData(data);
- const color = this.participantService.getRemoteParticipantByConnectionId(connectionId)?.colorProfile || '';
+ if(!!event.text) {
+ clearInterval(this.deleteAllTimeout);
+ const { connectionId, data } = event.connection;
+ const nickname: string = this.participantService.getNicknameFromConnectionData(data);
+ const color = this.participantService.getRemoteParticipantByConnectionId(connectionId)?.colorProfile || '';
- const caption: CaptionModel = {
- connectionId,
- nickname,
- color,
- text: event.text,
- type: event.reason
- };
- this.updateCaption(caption);
- // Delete all events when there are no more events for a period of time
- this.deleteAllEventsAfterDelay(this.DELETE_TIMEOUT);
- this.cd.markForCheck();
+ const caption: CaptionModel = {
+ connectionId,
+ nickname,
+ color,
+ text: event.text,
+ type: event.reason
+ };
+ this.updateCaption(caption);
+ // Delete all events when there are no more events for a period of time
+ this.deleteAllEventsAfterDelay(this.DELETE_TIMEOUT);
+ this.cd.markForCheck();
+ }
});
}
private updateCaption(caption: CaptionModel): void {
@@ -187,6 +188,13 @@ export class CaptionsComponent implements OnInit {
}, timeout);
}
+ private subscribeToSTTStatus() {
+ this.sttStatusSubscription = this.openviduService.isSttReadyObs.subscribe((ready: boolean) => {
+ this.isSttReady = ready;
+ this.cd.markForCheck();
+ });
+ }
+
private subscribeToCaptionLanguage() {
this.captionLanguageSubscription = this.captionService.captionLangObs.subscribe((lang) => {
this.captionLangSelected = lang;
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.ts
index 03e169d3..d89afa3a 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.ts
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/session/session.component.ts
@@ -16,6 +16,7 @@ import {
import {
ConnectionEvent,
ExceptionEvent,
+ ExceptionEventName,
RecordingEvent,
Session,
SessionDisconnectedEvent,
@@ -84,6 +85,7 @@ export class SessionComponent implements OnInit, OnDestroy {
protected layoutWidthSubscription: Subscription;
protected updateLayoutInterval: NodeJS.Timer;
+ // private sttReconnectionInterval: NodeJS.Timer;
private captionLanguageSubscription: Subscription;
protected log: ILogger;
@@ -277,8 +279,15 @@ export class SessionComponent implements OnInit, OnDestroy {
}
private subscribeToOpenViduException() {
- this.session.on('exception', (event: ExceptionEvent) => {
- this.log.e(event.name, event.message);
+ this.session.on('exception', async (event: ExceptionEvent) => {
+ if (event.name === ExceptionEventName.SPEECH_TO_TEXT_DISCONNECTED) {
+ this.log.w(event.name, event.message);
+ this.openviduService.setSTTReady(false);
+ // Try to re-subscribe to STT
+ await this.openviduService.subscribeRemotesToSTT(this.captionService.getLangSelected().ISO);
+ } else {
+ this.log.e(event.name, event.message);
+ }
});
}
@@ -319,18 +328,23 @@ export class SessionComponent implements OnInit, OnDestroy {
const data = event.stream?.connection?.data;
const isCameraType: boolean = this.participantService.getTypeConnectionData(data) === VideoType.CAMERA;
const isRemoteConnection: boolean = !this.openviduService.isMyOwnConnection(connectionId);
+ const lang = this.captionService.getLangSelected().ISO;
if (isRemoteConnection) {
const subscriber: Subscriber = this.session.subscribe(event.stream, undefined);
this.participantService.addRemoteConnection(connectionId, data, subscriber);
// this.oVSessionService.sendNicknameSignal(event.stream.connection);
- if (this.captionService.areCaptionsEnabled() && isCameraType) {
- // Only subscribe to STT when stream is CAMERA type and it is a remote stream
+ if (this.openviduService.isSttReady() && this.captionService.areCaptionsEnabled() && isCameraType) {
+ // Only subscribe to STT when is ready and stream is CAMERA type and it is a remote stream
try {
- await this.session.subscribeToSpeechToText(event.stream, this.captionService.getLangSelected().ISO);
+ await this.openviduService.subscribeStreamToStt(event.stream, lang);
} catch (error) {
this.log.e('Error subscribing from STT: ', error);
+ // I assume the only reason of an STT error is a STT crash.
+ // It must be subscribed to all remotes again
+ // await this.openviduService.unsubscribeRemotesFromSTT();
+ await this.openviduService.subscribeRemotesToSTT(lang);
}
}
}
@@ -345,13 +359,11 @@ export class SessionComponent implements OnInit, OnDestroy {
const isCameraType: boolean = this.participantService.getTypeConnectionData(data) === VideoType.CAMERA;
this.participantService.removeConnectionByConnectionId(connectionId);
- if (isRemoteConnection) {
- if (this.captionService.areCaptionsEnabled() && isCameraType) {
- try {
- await this.session.unsubscribeFromSpeechToText(event.stream);
- } catch (error) {
- this.log.e('Error unsubscribing from STT: ', error);
- }
+ if (this.openviduService.isSttReady() && this.captionService.areCaptionsEnabled() && isRemoteConnection && isCameraType) {
+ try {
+ await this.session.unsubscribeFromSpeechToText(event.stream);
+ } catch (error) {
+ this.log.e('Error unsubscribing from STT: ', error);
}
}
});
@@ -362,17 +374,8 @@ export class SessionComponent implements OnInit, OnDestroy {
if (this.captionService.areCaptionsEnabled()) {
// Unsubscribe all streams from speech to text and re-subscribe with new language
this.log.d('Re-subscribe from STT because of language changed to ', lang.ISO);
- for (const participant of this.participantService.getRemoteParticipants()) {
- const streamManager = participant.getCameraConnection()?.streamManager;
- if (!!streamManager?.stream) {
- try {
- await this.session.unsubscribeFromSpeechToText(streamManager.stream);
- await this.session.subscribeToSpeechToText(streamManager.stream, lang.ISO);
- } catch (error) {
- this.log.e('Error re-subscribing to STT: ', error);
- }
- }
- }
+ await this.openviduService.unsubscribeRemotesFromSTT();
+ await this.openviduService.subscribeRemotesToSTT(lang.ISO);
}
});
}
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.html
index 78147dde..3f4f33b3 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.html
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.html
@@ -15,7 +15,7 @@
{{ 'PANEL.SETTINGS.LANGUAGE' | translate }}
-