mirror of https://github.com/OpenVidu/openvidu.git
openvidu-components: Added reconnection when STT disconnected
parent
a1d040e61a
commit
0b7fefd906
|
@ -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
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
</button>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="isSttReady"
|
||||
class="captions-center-container"
|
||||
[ngClass]="{
|
||||
'events-one': captionEvents.length === 1,
|
||||
|
@ -35,6 +36,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!isSttReady" class="captions-center-container error-container">
|
||||
<mat-spinner [diameter]="20"></mat-spinner>
|
||||
<span>{{'ERRORS.SST_CONNECTION' | translate}}</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div *ngIf="captionsContainer.offsetWidth >= 600 && !settingsPanelOpened" class="captions-offset"></div>
|
||||
</div>
|
||||
|
|
|
@ -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<void> {
|
||||
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,6 +94,7 @@ export class CaptionsComponent implements OnInit {
|
|||
|
||||
private subscribeToTranscription() {
|
||||
this.session.on('speechToTextMessage', (event: SpeechToTextEvent) => {
|
||||
if(!!event.text) {
|
||||
clearInterval(this.deleteAllTimeout);
|
||||
const { connectionId, data } = event.connection;
|
||||
const nickname: string = this.participantService.getNicknameFromConnectionData(data);
|
||||
|
@ -111,6 +111,7 @@ export class CaptionsComponent implements OnInit {
|
|||
// 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;
|
||||
|
|
|
@ -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.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,15 +359,13 @@ 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) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<div id="lang-section">
|
||||
<mat-list-item>
|
||||
<div mat-line>{{ 'PANEL.SETTINGS.LANGUAGE' | translate }}</div>
|
||||
<button mat-flat-button [matMenuTriggerFor]="menu" class="lang-button">
|
||||
<button mat-flat-button [matMenuTriggerFor]="menu" [disabled]="!isSttReady" class="lang-button">
|
||||
<span>{{ langSelected }}</span>
|
||||
<mat-icon>expand_more</mat-icon>
|
||||
</button>
|
||||
|
|
|
@ -13,25 +13,30 @@ import { OpenViduService } from '../../../services/openvidu/openvidu.service';
|
|||
styleUrls: ['./captions.component.css']
|
||||
})
|
||||
export class CaptionsSettingComponent implements OnInit, OnDestroy {
|
||||
isSttReady: boolean = true;
|
||||
captionsEnabled: boolean;
|
||||
languagesAvailable: { name: string; ISO: string }[] = [];
|
||||
captionsSubscription: Subscription;
|
||||
langSelected: string;
|
||||
isOpenViduPro: boolean = false;
|
||||
private captionsStatusSubs: Subscription;
|
||||
private sttStatusSubs: Subscription;
|
||||
|
||||
|
||||
constructor(private layoutService: LayoutService, private captionService: CaptionService, private openviduService: OpenViduService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.isOpenViduPro = this.openviduService.isOpenViduPro();
|
||||
if (this.isOpenViduPro) {
|
||||
this.subscribeToCaptions();
|
||||
this.subscribeToSttStatus();
|
||||
this.subscribeToCaptionsStatus();
|
||||
this.langSelected = this.captionService.getLangSelected().name;
|
||||
this.languagesAvailable = this.captionService.getCaptionLanguages();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.captionsSubscription) this.captionsSubscription.unsubscribe();
|
||||
if (this.captionsStatusSubs) this.captionsStatusSubs.unsubscribe();
|
||||
if (this.sttStatusSubs) this.sttStatusSubs.unsubscribe();
|
||||
}
|
||||
|
||||
onLangSelected(lang: { name: string; ISO: string }) {
|
||||
|
@ -43,8 +48,14 @@ export class CaptionsSettingComponent implements OnInit, OnDestroy {
|
|||
this.layoutService.toggleCaptions();
|
||||
}
|
||||
|
||||
private subscribeToCaptions() {
|
||||
this.captionsSubscription = this.layoutService.captionsTogglingObs.subscribe((value: boolean) => {
|
||||
private subscribeToSttStatus(){
|
||||
this.sttStatusSubs = this.openviduService.isSttReadyObs.subscribe((ready: boolean) => {
|
||||
this.isSttReady = ready;
|
||||
});
|
||||
}
|
||||
|
||||
private subscribeToCaptionsStatus() {
|
||||
this.captionsStatusSubs = this.layoutService.captionsTogglingObs.subscribe((value: boolean) => {
|
||||
this.captionsEnabled = value;
|
||||
// this.cd.markForCheck();
|
||||
});
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "分享屏幕出错",
|
||||
"SCREEN_SUPPORT": "您的浏览器不支持屏幕共享",
|
||||
"MEDIA_ACCESS": "不允许访问媒体设备",
|
||||
"DEVICE_NOT_FOUND": "没有找到视频或音频设备 请至少连接一个"
|
||||
"DEVICE_NOT_FOUND": "没有找到视频或音频设备 请至少连接一个",
|
||||
"SST_CONNECTION": "连接丢失。正在重新连接到语音到文本服务"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "Fehler beim Teilen des Bildschirms",
|
||||
"SCREEN_SUPPORT": "Ihr Browser unterstützt keine Bildschirmfreigabe",
|
||||
"MEDIA_ACCESS": "Der Zugriff auf Mediengeräte war nicht erlaubt.",
|
||||
"DEVICE_NOT_FOUND": "Es wurden keine Video- oder Audiogeräte gefunden. Bitte schließen Sie mindestens eines an."
|
||||
"DEVICE_NOT_FOUND": "Es wurden keine Video- oder Audiogeräte gefunden. Bitte schließen Sie mindestens eines an.",
|
||||
"SST_CONNECTION": "Verbindung verloren. Wiederverbindung zum Sprach zu Text Service..."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
"SCREEN_SHARING": "Error sharing screen",
|
||||
"SCREEN_SUPPORT": "Your browser does not support screen sharing",
|
||||
"MEDIA_ACCESS": "Access to media devices was not allowed.",
|
||||
"DEVICE_NOT_FOUND": "No video or audio devices have been found. Please, connect at least one."
|
||||
"DEVICE_NOT_FOUND": "No video or audio devices have been found. Please, connect at least one.",
|
||||
"SST_CONNECTION": "Connection lost. Reconnecting to the speech to text service ..."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "Hubo un error compartiendo pantalla",
|
||||
"SCREEN_SUPPORT": "Tu navegador no soporta la pantalla compartida",
|
||||
"MEDIA_ACCESS": "No se ha podido acceder a tus dispositivos",
|
||||
"DEVICE_NOT_FOUND": "No se han encontrado dispositivos de audio o video. Por favor, conecta al menos uno."
|
||||
"DEVICE_NOT_FOUND": "No se han encontrado dispositivos de audio o video. Por favor, conecta al menos uno.",
|
||||
"SST_CONNECTION": "Conexión perdida. Reconectando al servicio de transcripción a texto..."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "Erreur de partage d'écran",
|
||||
"SCREEN_SUPPORT": "Votre navigateur ne prend pas en charge le partage d'écran",
|
||||
"MEDIA_ACCESS": "L'accès aux périphériques médias n'a pas été autorisé",
|
||||
"DEVICE_NOT_FOUND": "Aucun périphérique vidéo ou audio n'a été trouvé. Veuillez en connecter au moins un."
|
||||
"DEVICE_NOT_FOUND": "Aucun périphérique vidéo ou audio n'a été trouvé. Veuillez en connecter au moins un.",
|
||||
"SST_CONNECTION": "Connexion perdue. Reconnexion au service de reconnaissance vocale..."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "स्क्रीन साझा करने में त्रुटि",
|
||||
"SCREEN_SUPPORT": "आपका ब्राउज़र स्क्रीन साझाकरण का समर्थन नहीं करता",
|
||||
"MEDIA_ACCESS": "मीडिया उपकरणों तक पहुंच की अनुमति नहीं थी।",
|
||||
"DEVICE_NOT_FOUND": "कोई वीडियो या ऑडियो डिवाइस नहीं मिला। कृपया, कम से कम एक कनेक्ट करें।"
|
||||
"DEVICE_NOT_FOUND": "कोई वीडियो या ऑडियो डिवाइस नहीं मिला। कृपया, कम से कम एक कनेक्ट करें।",
|
||||
"SST_CONNECTION": "खोया तार। लेख सेवा से लिप्यंतरण से पुन: कनेक्ट हो रहा है..."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "Errore nella condivisione dello schermo",
|
||||
"SCREEN_SUPPORT": "Il browser non supporta la condivisione dello schermo",
|
||||
"MEDIA_ACCESS": "L'accesso ai dispositivi multimediali non è stato consentito",
|
||||
"DEVICE_NOT_FOUND": "Non sono stati trovati dispositivi video o audio. Si prega di collegarne almeno uno"
|
||||
"DEVICE_NOT_FOUND": "Non sono stati trovati dispositivi video o audio. Si prega di collegarne almeno uno",
|
||||
"SST_CONNECTION": "Connessione persa. Riconnessione al servizio di conversione testo da audio in corso..."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "画面共有にエラーが発生しました",
|
||||
"SCREEN_SUPPORT": "お使いのブラウザは画面共有に対応していません",
|
||||
"MEDIA_ACCESS": "メディアデバイスへのアクセスが許可されませんでした",
|
||||
"DEVICE_NOT_FOUND": "ビデオまたはオーディオデバイスが見つかりませんでした 最低1台は接続してください"
|
||||
"DEVICE_NOT_FOUND": "ビデオまたはオーディオデバイスが見つかりませんでした 最低1台は接続してください",
|
||||
"SST_CONNECTION": "接続が失われました。音声からテキストへの変換サービスに再接続しています"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "Fout bij het delen van het scherm",
|
||||
"SCREEN_SUPPORT": "Uw browser ondersteunt het delen van schermen niet",
|
||||
"MEDIA_ACCESS": "Toegang tot media-apparaten was niet toegestaan.",
|
||||
"DEVICE_NOT_FOUND": "Er zijn geen video- of audioapparaten gevonden. Sluit er alstublieft ten minste één aan."
|
||||
"DEVICE_NOT_FOUND": "Er zijn geen video- of audioapparaten gevonden. Sluit er alstublieft ten minste één aan.",
|
||||
"SST_CONNECTION": "Verbinding verbroken. Opnieuw verbinden met de spraak-naar-tekstservice..."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"SCREEN_SHARING": "ecrã_partilha de erros",
|
||||
"SCREEN_SUPPORT": "O seu browser não suporta a partilha de ecrãs",
|
||||
"MEDIA_ACCESS": "Não foi permitido o acesso a dispositivos de media",
|
||||
"DEVICE_NOT_FOUND": "Nenhum dispositivo de vídeo ou áudio foi encontrado. Por favor, ligue pelo menos um"
|
||||
"DEVICE_NOT_FOUND": "Nenhum dispositivo de vídeo ou áudio foi encontrado. Por favor, ligue pelo menos um",
|
||||
"SST_CONNECTION": "Conexão perdida. Reconectando ao serviço de texto de voz..."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export class CaptionService {
|
|||
];
|
||||
captionLangSelected: { name: string; ISO: string } = { name: 'English', ISO: 'en-US' };
|
||||
captionLangObs: Observable<{ name: string; ISO: string }>;
|
||||
private _captionLangObs: Subject<{ name: string; ISO: string }> = new Subject();
|
||||
private _captionLang: Subject<{ name: string; ISO: string }> = new Subject();
|
||||
private captionsEnabled: boolean = false;
|
||||
|
||||
constructor(private storageService: StorageService) {
|
||||
|
@ -33,7 +33,7 @@ export class CaptionService {
|
|||
} else {
|
||||
this.captionLangSelected = this.langs[0];
|
||||
}
|
||||
this.captionLangObs = this._captionLangObs.asObservable();
|
||||
this.captionLangObs = this._captionLang.asObservable();
|
||||
}
|
||||
|
||||
setCaptionsEnabled(value: boolean) {
|
||||
|
@ -49,7 +49,7 @@ export class CaptionService {
|
|||
if (!!newLang && newLang.ISO !== this.captionLangSelected.ISO) {
|
||||
this.captionLangSelected = newLang;
|
||||
this.storageService.setCaptionLang(lang);
|
||||
this._captionLangObs.next(this.captionLangSelected);
|
||||
this._captionLang.next(this.captionLangSelected);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@ import {
|
|||
Publisher,
|
||||
PublisherProperties,
|
||||
Session,
|
||||
SignalOptions
|
||||
SignalOptions,
|
||||
Stream
|
||||
} from 'openvidu-browser';
|
||||
|
||||
import { LoggerService } from '../logger/logger.service';
|
||||
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { CameraType } from '../../models/device.model';
|
||||
import { ILogger } from '../../models/logger.model';
|
||||
import { OpenViduEdition } from '../../models/openvidu.model';
|
||||
|
@ -26,6 +28,7 @@ import { PlatformService } from '../platform/platform.service';
|
|||
providedIn: 'root'
|
||||
})
|
||||
export class OpenViduService {
|
||||
isSttReadyObs: Observable<boolean>;
|
||||
private ovEdition: OpenViduEdition;
|
||||
private webcamToken = '';
|
||||
private screenToken = '';
|
||||
|
@ -35,6 +38,9 @@ export class OpenViduService {
|
|||
protected screenSession: Session;
|
||||
protected videoSource = undefined;
|
||||
protected audioSource = undefined;
|
||||
private STT_TIMEOUT_MS = 2 * 1000;
|
||||
private sttReconnectionTimeout: NodeJS.Timeout;
|
||||
private _isSttReady: BehaviorSubject<boolean> = new BehaviorSubject(true);
|
||||
protected log: ILogger;
|
||||
|
||||
/**
|
||||
|
@ -48,6 +54,7 @@ export class OpenViduService {
|
|||
protected deviceService: DeviceService
|
||||
) {
|
||||
this.log = this.loggerSrv.get('OpenViduService');
|
||||
this.isSttReadyObs = this._isSttReady.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -170,6 +177,25 @@ export class OpenViduService {
|
|||
return !!this.screenSession.capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Whether the STT service is ready or not
|
||||
* This will be `false` when the app receives a SPEECH_TO_TEXT_DISCONNECTED exception
|
||||
* and it cannot subscribe to STT
|
||||
*/
|
||||
isSttReady(): boolean {
|
||||
return this._isSttReady.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setSTTReady(value: boolean): void {
|
||||
if (this._isSttReady.getValue() !== value) {
|
||||
this._isSttReady.next(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
@ -210,7 +236,7 @@ export class OpenViduService {
|
|||
* @internal
|
||||
* Initialize a publisher checking devices saved on storage or if participant have devices available.
|
||||
*/
|
||||
async initDefaultPublisher(): Promise<Publisher> {
|
||||
async initDefaultPublisher(): Promise<Publisher | undefined> {
|
||||
const hasVideoDevices = this.deviceService.hasVideoDeviceAvailable();
|
||||
const hasAudioDevices = this.deviceService.hasAudioDeviceAvailable();
|
||||
const isVideoActive = !this.deviceService.isVideoMuted();
|
||||
|
@ -487,19 +513,67 @@ export class OpenViduService {
|
|||
}
|
||||
}
|
||||
|
||||
// private destroyPublisher(publisher: Publisher): void {
|
||||
// if (!!publisher) {
|
||||
// if (publisher.stream.getWebRtcPeer()) {
|
||||
// publisher.stream.disposeWebRtcPeer();
|
||||
// }
|
||||
// publisher.stream.disposeMediaStream();
|
||||
// if (publisher.id === this.participantService.getMyCameraPublisher().id) {
|
||||
// this.participantService.setMyCameraPublisher(publisher);
|
||||
// } else if (publisher.id === this.participantService.getMyScreenPublisher().id) {
|
||||
// this.participantService.setMyScreenPublisher(publisher);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
/**
|
||||
* @internal
|
||||
* Subscribe all `CAMERA` stream types to speech-to-text
|
||||
* It will retry the subscription each `STT_TIMEOUT_MS`
|
||||
*
|
||||
* @param lang The language of the Stream's audio track.
|
||||
*/
|
||||
async subscribeRemotesToSTT(lang: string): Promise<void> {
|
||||
const remoteParticipants = this.participantService.getRemoteParticipants();
|
||||
let successNumber = 0;
|
||||
|
||||
for (const p of remoteParticipants) {
|
||||
const stream = p.getCameraConnection()?.streamManager?.stream;
|
||||
if (stream) {
|
||||
try {
|
||||
await this.subscribeStreamToStt(stream, lang);
|
||||
successNumber++;
|
||||
} catch (error) {
|
||||
this.log.e(`Error subscribing ${stream.streamId} to STT:`, error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setSTTReady(successNumber === remoteParticipants.length);
|
||||
if (!this.isSttReady()) {
|
||||
this.log.w('STT is not ready. Retrying subscription...');
|
||||
this.sttReconnectionTimeout = setTimeout(this.subscribeRemotesToSTT.bind(this, lang), this.STT_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Subscribe a stream to speech-to-text
|
||||
* @param stream
|
||||
* @param lang
|
||||
*/
|
||||
async subscribeStreamToStt(stream: Stream, lang: string): Promise<void> {
|
||||
await this.getWebcamSession().subscribeToSpeechToText(stream, lang);
|
||||
this.log.d(`Subscribed stream ${stream.streamId} to STT with ${lang} language.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Unsubscribe to all `CAMERA` stream types to speech-to-text if STT is up(ready)
|
||||
*/
|
||||
async unsubscribeRemotesFromSTT(): Promise<void> {
|
||||
clearTimeout(this.sttReconnectionTimeout);
|
||||
if (this.isSttReady()) {
|
||||
for (const p of this.participantService.getRemoteParticipants()) {
|
||||
const stream = p.getCameraConnection().streamManager.stream;
|
||||
if (stream) {
|
||||
try {
|
||||
await this.getWebcamSession().unsubscribeFromSpeechToText(stream);
|
||||
} catch (error) {
|
||||
this.log.e(`Error unsubscribing ${stream.streamId} from STT:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async createMediaStream(pp: PublisherProperties): Promise<MediaStream> {
|
||||
let mediaStream: MediaStream;
|
||||
|
|
Loading…
Reference in New Issue