From 2aec4b9fabd3afd4191bad61de5c58eff7a8be37 Mon Sep 17 00:00:00 2001 From: Carlos Santos <4a.santos@gmail.com> Date: Mon, 24 Oct 2022 17:08:32 +0200 Subject: [PATCH] openvidu-components: Added captions --- openvidu-components-angular/package.json | 2 +- .../captions/captions.component.css | 205 ++- .../captions/captions.component.html | 58 +- .../captions/captions.component.spec.ts | 12 +- .../components/captions/captions.component.ts | 1574 ++--------------- .../components/layout/layout.component.css | 4 +- .../components/layout/layout.component.html | 4 +- .../lib/components/layout/layout.component.ts | 18 +- .../settings-panel.component.html | 12 +- .../settings-panel.component.ts | 10 +- .../components/session/session.component.ts | 51 +- .../captions.component.css} | 0 .../captions.component.html} | 13 +- .../captions/captions.component.spec.ts | 24 + .../settings/captions/captions.component.ts | 47 + .../subtitles/subtitles.component.spec.ts | 25 - .../settings/subtitles/subtitles.component.ts | 44 - .../components/toolbar/toolbar.component.html | 12 +- .../components/toolbar/toolbar.component.ts | 24 +- .../videoconference.component.css | 2 +- .../videoconference.component.ts | 12 +- .../directives/api/api.directive.module.ts | 27 +- .../lib/directives/api/internals.directive.ts | 2 +- .../lib/directives/api/toolbar.directive.ts | 9 +- .../api/videoconference.directive.ts | 70 +- .../openvidu-angular/src/lib/lang/cn.json | 6 +- .../openvidu-angular/src/lib/lang/de.json | 6 +- .../openvidu-angular/src/lib/lang/en.json | 6 +- .../openvidu-angular/src/lib/lang/es.json | 6 +- .../openvidu-angular/src/lib/lang/fr.json | 6 +- .../openvidu-angular/src/lib/lang/hi.json | 6 +- .../openvidu-angular/src/lib/lang/it.json | 6 +- .../openvidu-angular/src/lib/lang/ja.json | 6 +- .../openvidu-angular/src/lib/lang/nl.json | 6 +- .../openvidu-angular/src/lib/lang/pt.json | 6 +- .../src/lib/models/caption.model.ts | 10 + .../src/lib/models/panel.model.ts | 2 +- .../src/lib/models/storage.model.ts | 5 +- .../src/lib/openvidu-angular.module.ts | 76 +- .../services/caption/caption.service.spec.ts | 16 + .../lib/services/caption/caption.service.ts | 47 + .../config/openvidu-angular.config.service.ts | 6 +- .../lib/services/document/document.service.ts | 12 +- .../src/lib/services/layout/layout.service.ts | 29 +- .../lib/services/storage/storage.service.ts | 10 +- .../services/translate/translate.service.ts | 8 +- 46 files changed, 751 insertions(+), 1791 deletions(-) rename openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/{subtitles/subtitles.component.css => captions/captions.component.css} (100%) rename openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/{subtitles/subtitles.component.html => captions/captions.component.html} (60%) create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.spec.ts create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.ts delete mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.spec.ts delete mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.ts create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/models/caption.model.ts create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/services/caption/caption.service.spec.ts create mode 100644 openvidu-components-angular/projects/openvidu-angular/src/lib/services/caption/caption.service.ts diff --git a/openvidu-components-angular/package.json b/openvidu-components-angular/package.json index 5aa3748b..264eb9b9 100644 --- a/openvidu-components-angular/package.json +++ b/openvidu-components-angular/package.json @@ -11,7 +11,7 @@ "@angular/platform-browser-dynamic": "13.3.9", "@angular/router": "13.3.9", "autolinker": "3.14.3", - "lorem-ipsum": "^2.0.8", + "openvidu-browser": "file:openvidu-browser-2.23.0.tgz", "openvidu-browser": "2.23.0", "rxjs": "7.5.6", "tslib": "2.3.1", 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 70db1dc4..6e302e3b 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 @@ -1,78 +1,193 @@ -.subtitles-container { +.captions-container { /* padding: 5px; */ display: flex; - height: var(--ov-captions-height, 200px); + height: var(--ov-captions-height, 230px); margin: 0px 10px; } -.subtitles-offset { - height: var(--ov-captions-height, 200px); +.captions-offset { + height: var(--ov-captions-height, 230px); width: 15%; text-align: center; } -.subtitles-main-container { - flex-grow: 1; - align-self: center; - margin-left: 15px; - max-height: var(--ov-captions-height, 200px); - width: 70%; - overflow: hidden; +.captions-offset-xl { + width: 25% !important; } -/* .subtitles-offset + .subtitles-offset { - margin-left: 2%; -} */ -#subtitle-settings-btn { +.captions-center-container { + flex-grow: 1; + align-self: center; + /* margin-left: 15px; */ + max-height: var(--ov-captions-height, 230px); + width: 70%; + overflow: hidden; + + height: var(--ov-captions-height, 230px); + padding: 0px 10vw 0px; +} + + +/* +* Screen XL +*/ +.captions-center-container.screen-xl { + padding: 0px 14vw; +} + +.captions-center-container.screen-xl .caption-event>span { + font-size: 22px; +} + +.captions-center-container.screen-xl #speaker { + font-size: 16px; +} + +/* captions div*/ +.captions-center-container.screen-xl.events-one .caption-event { + max-height: 140px; +} + +.captions-center-container.screen-xl.events-two .caption-event { + max-height: 69px; +} + +.captions-center-container.screen-xl.events-three .caption-event { + max-height: 35px; +} + + +/* +* Screen MD +*/ +.captions-center-container.screen-md .caption-event>span { + font-size: 20px; +} + +.captions-center-container.screen-md #speaker { + font-size: 14px; +} + +/* captions div*/ +.captions-center-container.screen-md.events-one .caption-event { + max-height: 140px; +} + +.captions-center-container.screen-md.events-two .caption-event { + max-height: 69px; +} + +.captions-center-container.screen-md.events-three .caption-event { + max-height: 35px; +} + +/* +* Screen SM +*/ + +.captions-center-container.screen-sm { + padding: 0px 2vw; +} +.captions-center-container.screen-sm .caption-event>span { + font-size: 20px; +} + +.captions-center-container.screen-sm #speaker { + font-size: 12px; +} + +/* captions div*/ + +.captions-center-container.screen-sm.events-one .caption-event { + max-height: 127px; +} + +.captions-center-container.screen-sm.events-two .caption-event { + max-height: 64px; +} + +.captions-center-container.screen-sm.events-three .caption-event { + max-height: 33px; +} + +/* +* Screen XS +*/ + +.captions-center-container.screen-xs { + padding: 0px 2vw 0px; +} + +.captions-center-container.screen-xs .caption-event>span { + font-size: 20px; +} +.captions-center-container.screen-xs #speaker { + font-size: 12px; +} + +/* captions div*/ +.captions-center-container.screen-xs.events-one .caption-event { + max-height: 130px; +} + +.captions-center-container.screen-xs.events-two .caption-event { + max-height: 69px; +} + +.captions-center-container.screen-xs.events-three .caption-event { + max-height: 35px; +} + +.captions-center-container .going-to-disappear{ + max-height: 30px !important; +} + + + +#caption-settings-btn { color: var(--ov-text-color); background-color: var(--ov-secondary-color); } -#subtitle-settings-icon { +#caption-settings-icon { font-size: 15px; height: 15px; width: 15px; padding-right: 5px; } -#author { - margin-bottom: 3px; +#speaker { + margin-bottom: 2px; font-weight: bold; + /* padding: 5px; */ + margin-left: -5px; + width: fit-content; } -#subtitle-text, -#author { +.captions-center-container .element { + margin: 8px 0px; +} + +.caption-event { + /* background-color: beige; */ + overflow: auto; + pointer-events: none; +} + + +.caption-text, +#speaker { color: var(--ov-text-color); - font-family: "Roboto",arial,sans-serif + font-family: 'Roboto', arial, sans-serif; } -.subtitles-main-container .element { - margin: 5px; -} -#subtitle-text { +.caption-text { background-color: var(--ov-logo-background-color); padding: 4.5px; line-height: 1.6; word-break: break-word; } -.big-text { - font-size: 22px; -} -.medium-text { - font-size: 20px; -} -.small-text { - font-size: 18px; -} -.extra-small-text { - font-size: 16px; -} -.big-author { - font-size: 16px; -} -.medium-author { - font-size: 14px; -} -.small-author { - font-size: 12px; + +::-webkit-scrollbar { + display: none; } 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 dc0ec828..b550a523 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 @@ -1,36 +1,40 @@ -
-
-
-
-
-

- {{ item.author }} ({{item.text.length}}) +

+
+

+ {{ caption.nickname }}

- - {{ item.text }} + {{ caption.text }} +
-
-
+
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.spec.ts index 4c6d1353..b73851b6 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.spec.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/captions/captions.component.spec.ts @@ -1,20 +1,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { SubtitlesComponent } from './subtitles.component'; +import { CaptionsComponent } from './captions.component'; -describe('SubtitlesComponent', () => { - let component: SubtitlesComponent; - let fixture: ComponentFixture; +describe('CaptionsComponent', () => { + let component: CaptionsComponent; + let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ SubtitlesComponent ] + declarations: [ CaptionsComponent ] }) .compileComponents(); }); beforeEach(() => { - fixture = TestBed.createComponent(SubtitlesComponent); + fixture = TestBed.createComponent(CaptionsComponent); component = fixture.componentInstance; fixture.detectChanges(); }); 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 c938f2db..e5888420 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 @@ -4,18 +4,18 @@ import { Component, ElementRef, OnInit, - QueryList, - ViewChild, - ViewChildren + QueryList, ViewChildren } from '@angular/core'; -import { BehaviorSubject, Observable, Subscription } from 'rxjs'; -import { PanelSettingsOptions, PanelType } from '../../models/panel.model'; +import { Subscription } from 'rxjs'; import { PanelEvent, PanelService } from '../../services/panel/panel.service'; -import { DocumentService } from '../../services/document/document.service'; -import { MediaChange } from '@angular/flex-layout'; -//TODO: Remove when speech to text is integrated -// import { LoremIpsum } from 'lorem-ipsum'; +import { animate, style, transition, trigger } from '@angular/animations'; +import { Session, SpeechToTextEvent } from 'openvidu-browser'; +import { CaptionModel } from '../../models/caption.model'; +import { PanelSettingsOptions, PanelType } from '../../models/panel.model'; +import { CaptionService } from '../../services/caption/caption.service'; +import { OpenViduService } from '../../services/openvidu/openvidu.service'; +import { ParticipantService } from '../../services/participant/participant.service'; /** * @internal @@ -24,1349 +24,54 @@ import { MediaChange } from '@angular/flex-layout'; selector: 'ov-captions', templateUrl: './captions.component.html', styleUrls: ['./captions.component.css'], + animations: [ + trigger('captionAnimation', [ + transition(':enter', [style({ opacity: 0 }), animate('50ms ease-in', style({ opacity: 1 }))]) + // transition(':leave', [style({ opacity: 1 }), animate('10ms ease-out', style({ opacity: 0 }))]) + ]) + ], changeDetection: ChangeDetectionStrategy.OnPush }) export class CaptionsComponent implements OnInit { - @ViewChild('textContainer') textContainer: ElementRef; + scrollContainer: QueryList; + + @ViewChildren('captionEventElement') + set captionEventRef(captionEventsRef: QueryList) { + setTimeout(() => { + if (captionEventsRef) { + this.scrollContainer = captionEventsRef; + } + }, 0); + } - @ViewChildren('captionElement') captionElementsRef: QueryList; - /** - * @ignore - */ - subtitleText: string; - /** - * @ignore - */ - screenSize: string; - /** - * @ignore - */ settingsPanelOpened: boolean; + + captionEvents: CaptionModel[] = []; + + session: Session; + + private deleteTimeout: NodeJS.Timeout; + + private DELETE_TIMEOUT = 5 * 1000; + private MAX_EVENTS_LIMIT = 3; + private captionLanguageSubscription: Subscription; + private captionLangSelected: { name: string; ISO: string }; private screenSizeSub: Subscription; private panelTogglingSubscription: Subscription; - interval: NodeJS.Timer; - fakeEvent: Observable<{ connectionId: string; partial: string; text?: string }>; - - captionElements: { connectionId: string; author: string; text: string }[] = []; - - //TODO: Remove when speech to text is integrated - private sample = [ - { connectionId: '1', partial: 'frente' }, - { connectionId: '1', partial: 'friends' }, - { connectionId: '1', partial: 'friends' }, - { connectionId: '1', partial: 'friends estilizado' }, - { connectionId: '1', partial: 'friends estilizado' }, - { connectionId: '1', partial: 'friends estilizado' }, - { connectionId: '1', partial: 'friends estilizado' }, - { connectionId: '1', partial: 'friends estilizado efe' }, - { connectionId: '1', partial: 'friends estilizado efe' }, - { connectionId: '1', partial: 'friends estilizado efe erre' }, - { connectionId: '1', partial: 'friends estilizado efe erre' }, - { connectionId: '1', partial: 'friends estilizado efe erre' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y he' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y he' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y he' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y he' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en de' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en de' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en de' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en de' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida como' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida como' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida como' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa' }, - { connectionId: '1', partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa' }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense crear productos' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense crear productos' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense crear productos' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por mayor' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por mayor' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por mayor' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por mark' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por mark' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y la' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y la' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y la' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y la' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y la' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz cree' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz cree' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz cree' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz cree' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz cree' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz creen se' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz creen se' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz creen se' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz creen se' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz creen se' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz creen se' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz creen se' - }, - { - connectionId: '1', - partial: - 'friends estilizado efe el rey y en ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense creado y producida por marta kaufman y lápiz creen se' - }, - { - connectionId: '1', - text: 'friends estilizado efe erre y ene de ese también conocida en hispanoamérica como amigos y en españa como colegas durante la temporada uno es una serie de televisión estadounidense y producida por marta kaufman y la creen se emitió' - }, - { connectionId: '2', partial: 'la' }, - { connectionId: '2', partial: 'primera vez en' }, - { connectionId: '2', partial: 'primera vez en' }, - { connectionId: '2', partial: 'a veces vendidos' }, - { connectionId: '2', partial: 'a veces vendidos' }, - { connectionId: '2', partial: 'a veces vendidos' }, - { connectionId: '2', partial: 'a veces vendidos' }, - { connectionId: '2', partial: 'a veces vendidos' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la academia' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la academia' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la academia' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena de' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena de' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en eventos' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en eventos' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena de veces y' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena de veces y' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena de veces y' }, - { - connectionId: '2', - partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena de veces y términos y' - }, - { - connectionId: '2', - partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena de veces y términos y' - }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de' }, - { connectionId: '2', partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de' }, - { - connectionId: '2', - partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil' - }, - { - connectionId: '2', - partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil' - }, - { - connectionId: '2', - partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil' - }, - { - connectionId: '2', - partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil' - }, - { - connectionId: '2', - partial: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatrocientos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatrocientos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatrocientos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro las' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro las' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que recibieron' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que recibieron' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que recibieron' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que recibieron matarnos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que recibieron matarnos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york sucede en' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york sucede en' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto unos como' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto unos como' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto unos como' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la actualidad y' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la actualidad y' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la actualidad y' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo considerable' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo considerable' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo considerable' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo considerable' - }, - { - connectionId: '2', - partial: - 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena en términos de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que residen en oaxaca nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo considerable' - }, - { - connectionId: '2', - text: 'a veces vendidos de septiembre de mil novecientos noventa y cuatro por la cadena de veces y terminó en seis de mayo de dos mil cuatro la serie trata sobre la vida de un grupo de amigos que en baja tan nueva york suceden tanto buenos como malos momentos pero con una crítica cómica los hechos más trascendentales de la autoridad inmediatamente después del éxito de su país el programa comenzó su difusión por todo el mundo considerable resultados' - } - ]; - - captionsHeight = 0; - - constructor(private documentService: DocumentService, private panelService: PanelService, private cd: ChangeDetectorRef) {} + constructor( + private panelService: PanelService, + private openviduService: OpenViduService, + private participantService: ParticipantService, + private captionService: CaptionService, + private cd: ChangeDetectorRef + ) {} ngOnInit(): void { - this.subscribeToScreenSize(); + this.captionLangSelected = this.captionService.getLangSelected(); + this.session = this.openviduService.getWebcamSession(); + + this.subscribeToCaptionLanguage(); this.subscribeToPanelToggling(); this.subscribeToTranscription(); } @@ -1374,147 +79,106 @@ export class CaptionsComponent implements OnInit { ngOnDestroy() { if (this.screenSizeSub) this.screenSizeSub.unsubscribe(); if (this.panelTogglingSubscription) this.panelTogglingSubscription.unsubscribe(); - //TODO: Unsubscribe to openvidu-browser subtitle event - clearInterval(this.interval); + this.session.off('speechToTextMessage'); + this.captionEvents = []; } onSettingsCliked() { - this.panelService.togglePanel(PanelType.SETTINGS, PanelSettingsOptions.SUBTITLES); + this.panelService.togglePanel(PanelType.SETTINGS, PanelSettingsOptions.CAPTIONS); } private subscribeToTranscription() { - //TODO: Subscribe to openvidu-browser subtitle event - this.startFakeEventWithSample(); - this.fakeEvent.subscribe((event) => { - const text = !!event.text ? event.text : event.partial; - this.updateCaption(event.connectionId, text); + this.session.on('speechToTextMessage', (event: SpeechToTextEvent) => { + 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); this.cd.markForCheck(); - this.scrollToBottom(); }); } - private updateCaption(connectionId: string, text: string) { - //TODO: Remove when speech to text is integrated - const nicknames = new Map(); - nicknames.set('1', 'Pepe'); - nicknames.set('2', 'Mario'); - nicknames.set('3', 'Luis'); - nicknames.set('4', 'Juan'); - nicknames.set('5', 'INTERUPCION'); - // TODO End delete + private updateCaption(caption: CaptionModel): void { + let captionEventsCopy = [...this.captionEvents]; + let eventsNumber = captionEventsCopy.length; - let newCaptionElements = [...this.captionElements]; - const newItem = { connectionId, author: nicknames.get(connectionId), text }; + if (eventsNumber === this.MAX_EVENTS_LIMIT) { + captionEventsCopy.shift(); + eventsNumber--; + } - if (newCaptionElements?.length > 0) { - let lastItem = newCaptionElements[newCaptionElements.length - 1]; - if (lastItem.connectionId === connectionId) { - //Last author and new author are the same. Updating the caption - lastItem.text = text; - } else { - // const lastIntervention = newCaptionElements.find((item) => item.connectionId === connectionId); - // if (!!lastIntervention) { - // // The author is in the captionElements array - // // adding only the new words after its intervention. - // const splittedText = newItem.text.split(lastIntervention?.text)[1]; - // newItem.text = !!splittedText ? splittedText : newItem.text; - // } - newCaptionElements.push(newItem); - } + if (eventsNumber === 0) { + captionEventsCopy.push(caption); } else { - newCaptionElements.push(newItem); - } + const lastCaption: CaptionModel = captionEventsCopy.slice(-1)[0]; + const sameAuthorAsAbove: boolean = lastCaption.connectionId === caption.connectionId; + const allEventsAreSameSpeaker = captionEventsCopy.every((e) => e.connectionId === caption.connectionId); - this.adjustCaptionsToContainer(newCaptionElements); - } - private adjustCaptionsToContainer(newCaptionElements: { connectionId: string; author: string; text: string }[]) { - this.captionsHeight = 0; - // TODO: the height is being calculated for old data - // it should be calculated with the new caption elements - this.captionElementsRef?.forEach((item: ElementRef) => { - this.captionsHeight += item.nativeElement.offsetHeight; - }); - - - if (newCaptionElements?.length > 3) { - // Maximum elements exceeded. Delete first element. - newCaptionElements.shift(); - } else if (this.captionsHeight > 240) { - if (newCaptionElements?.length === 3) { - // Maximum height exceeded. Delete first element. - newCaptionElements.shift(); - } else if (newCaptionElements?.length === 2 || newCaptionElements?.length === 1) { - newCaptionElements[0].text = newCaptionElements[0].text.slice(100); - if (newCaptionElements[0].text.length < 100) { - newCaptionElements.shift(); + if (sameAuthorAsAbove) { + if (lastCaption.type === 'recognized') { + if (eventsNumber === 2 && allEventsAreSameSpeaker) { + captionEventsCopy.shift(); + clearInterval(this.deleteTimeout); + } + captionEventsCopy.push(caption); + this.deleteEventAfterDelay(this.DELETE_TIMEOUT); + } else { + lastCaption.text = caption.text; + lastCaption.type = caption.type; } + } else { + // TODO: Test when STT is able to work with multiple streams + if (eventsNumber === 2) { + captionEventsCopy.shift(); + clearInterval(this.deleteTimeout); + } + captionEventsCopy.push(caption); + this.deleteEventAfterDelay(this.DELETE_TIMEOUT); } } - this.captionElements = [...newCaptionElements]; + this.captionEvents = [...captionEventsCopy]; + this.scrollToBottom(); } - //TODO: Remove when speech to text is integrated - private startFakeEventWithSample() { - let index = 0; - let event = <{ connectionId: string; partial: string; text?: string }>this.sample[index]; - const fakeEventBS = >new BehaviorSubject(event); - this.fakeEvent = fakeEventBS.asObservable(); + private deleteEventAfterDelay(timeout: number) { + this.deleteTimeout = setTimeout(() => { + this.captionEvents.shift(); + this.cd.markForCheck(); + }, timeout); + } - const eventLoop = () => { - return setInterval(() => { - event = <{ connectionId: string; partial: string; text?: string }>this.sample[index]; - index++; - - fakeEventBS.next(event); - if (!this.sample[index]) { - clearInterval(this.interval); - index = 0; - } - }, 180); - }; - - this.interval = eventLoop(); - - //TODO: Simulating an speech event - //TODO: Remove when speech to text is integrated - // setInterval(() => { - // clearInterval(this.interval); - // const lorem = new LoremIpsum(); - // let times = 5; - // let partial = 'BLA BLA BLA '; - // const interval2 = setInterval(() => { - // fakeEventBS.next({ connectionId: '5', partial }); - // partial += lorem.generateWords(2); - // if (times <= 0) { - // fakeEventBS.next({ connectionId: '5', partial, text: partial }); - // clearInterval(interval2); - // this.interval = eventLoop(); - // } - // times--; - // }, 400); - // }, 6000); + private subscribeToCaptionLanguage() { + this.captionLanguageSubscription = this.captionService.captionLangObs.subscribe((lang) => { + this.captionLangSelected = lang; + this.cd.markForCheck(); + }); } private subscribeToPanelToggling() { this.panelTogglingSubscription = this.panelService.panelOpenedObs.subscribe((ev: PanelEvent) => { this.settingsPanelOpened = ev.opened; - this.cd.markForCheck(); - }); - } - - private subscribeToScreenSize() { - this.screenSizeSub = this.documentService.screenSizeObs.subscribe((change: MediaChange[]) => { - this.screenSize = change[0].mqAlias; - console.log(this.screenSize); - this.cd.markForCheck(); + setTimeout(() => this.cd.markForCheck(), 300); }); } private scrollToBottom(): void { - // setTimeout(() => { - try { - this.textContainer.nativeElement.scrollTop = this.textContainer.nativeElement.scrollHeight; - } catch (err) {} - // }, 20); + setTimeout(() => { + try { + this.scrollContainer.forEach((el: ElementRef) => { + el.nativeElement.scroll({ + top: this.scrollContainer.first.nativeElement.scrollHeight, + left: 0 + // behavior: 'smooth' + }); + }); + } catch (err) {} + }, 20); } } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.css index f7289445..2b7f25b1 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.css +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.css @@ -5,8 +5,8 @@ .container { height: 100%; } -.withSubtitles { - height: calc(100% - var(--ov-captions-height, 200px)) !important; +.withCaptions { + height: calc(100% - var(--ov-captions-height, 250px)) !important; } .layout { diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.html index d666ebac..0ba43776 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.html +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.html @@ -1,4 +1,4 @@ -
+
@@ -14,5 +14,5 @@
- +
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.ts index d93b71ae..a6c95724 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/layout/layout.component.ts @@ -11,10 +11,10 @@ import { ViewContainerRef } from '@angular/core'; import { Subscription } from 'rxjs'; -import { ParticipantService } from '../../services/participant/participant.service'; +import { StreamDirective } from '../../directives/template/openvidu-angular.directive'; import { ParticipantAbstractModel } from '../../models/participant.model'; import { LayoutService } from '../../services/layout/layout.service'; -import { StreamDirective } from '../../directives/template/openvidu-angular.directive'; +import { ParticipantService } from '../../services/participant/participant.service'; /** * @@ -82,11 +82,11 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { /** * @ignore */ - subtitlesEnabled = true; + captionsEnabled = true; private localParticipantSubs: Subscription; private remoteParticipantsSubs: Subscription; - private subtitlesSubs: Subscription; + private captionsSubs: Subscription; /** * @ignore @@ -95,7 +95,7 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { ngOnInit(): void { this.subscribeToParticipants(); - this.subscribeToSubtitles(); + this.subscribeToCaptions(); } ngAfterViewInit() { @@ -107,13 +107,13 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit { this.remoteParticipants = []; if (this.localParticipantSubs) this.localParticipantSubs.unsubscribe(); if (this.remoteParticipantsSubs) this.remoteParticipantsSubs.unsubscribe(); - if (this.subtitlesSubs) this.subtitlesSubs.unsubscribe(); + if (this.captionsSubs) this.captionsSubs.unsubscribe(); this.layoutService.clear(); } - private subscribeToSubtitles() { - this.subtitlesSubs = this.layoutService.subtitlesTogglingObs.subscribe((value: boolean) => { - this.subtitlesEnabled = value; + private subscribeToCaptions() { + this.captionsSubs = this.layoutService.captionsTogglingObs.subscribe((value: boolean) => { + this.captionsEnabled = value; this.cd.markForCheck(); this.layoutService.update(); }); diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/settings-panel/settings-panel.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/settings-panel/settings-panel.component.html index 591f4804..93bf0b7a 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/settings-panel/settings-panel.component.html +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/settings-panel/settings-panel.component.html @@ -22,14 +22,14 @@
{{ 'PANEL.SETTINGS.AUDIO' | translate }}
closed_caption -
{{ 'PANEL.SETTINGS.SUBTITLE' | translate }}
+
{{ 'PANEL.SETTINGS.CAPTIONS' | translate }}
@@ -47,7 +47,7 @@
- + diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/settings-panel/settings-panel.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/settings-panel/settings-panel.component.ts index ea666aae..24536ef0 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/settings-panel/settings-panel.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/panel/settings-panel/settings-panel.component.ts @@ -15,8 +15,8 @@ import { PanelEvent, PanelService } from '../../../services/panel/panel.service' export class SettingsPanelComponent implements OnInit { settingsOptions: typeof PanelSettingsOptions = PanelSettingsOptions; selectedOption: PanelSettingsOptions = PanelSettingsOptions.GENERAL; - showSubtitles: boolean = true; - private subtitlesSubs: Subscription; + showCaptions: boolean = true; + private captionsSubs: Subscription; panelSubscription: Subscription; constructor(private panelService: PanelService, private libService: OpenViduAngularConfigService) {} ngOnInit() { @@ -25,7 +25,7 @@ export class SettingsPanelComponent implements OnInit { } ngOnDestroy() { - if (this.subtitlesSubs) this.subtitlesSubs.unsubscribe(); + if (this.captionsSubs) this.captionsSubs.unsubscribe(); } close() { @@ -36,8 +36,8 @@ export class SettingsPanelComponent implements OnInit { } private subscribeToDirectives() { - this.subtitlesSubs = this.libService.subtitlesButtonObs.subscribe((value: boolean) => { - this.showSubtitles = value; + this.captionsSubs = this.libService.captionsButtonObs.subscribe((value: boolean) => { + this.showCaptions = value; }); } 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 f2d85b7a..83224137 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 @@ -1,5 +1,7 @@ import { - ChangeDetectionStrategy, ChangeDetectorRef, Component, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, ContentChild, ElementRef, EventEmitter, @@ -12,8 +14,12 @@ import { } from '@angular/core'; import { ConnectionEvent, - RecordingEvent, Session, SessionDisconnectedEvent, StreamEvent, - StreamPropertyChangedEvent, Subscriber + RecordingEvent, + Session, + SessionDisconnectedEvent, + StreamEvent, + StreamPropertyChangedEvent, + Subscriber } from 'openvidu-browser'; import { ILogger } from '../../models/logger.model'; @@ -26,6 +32,7 @@ import { SidenavMode } from '../../models/layout.model'; import { PanelType } from '../../models/panel.model'; import { Signal } from '../../models/signal.model'; import { ActionService } from '../../services/action/action.service'; +import { CaptionService } from '../../services/caption/caption.service'; import { ChatService } from '../../services/chat/chat.service'; import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service'; import { LayoutService } from '../../services/layout/layout.service'; @@ -46,11 +53,7 @@ import { TranslateService } from '../../services/translate/translate.service'; selector: 'ov-session', templateUrl: './session.component.html', styleUrls: ['./session.component.css'], - animations: [ - trigger('sessionAnimation', [ - transition(':enter', [style({ opacity: 0 }), animate('400ms', style({ opacity: 1 }))]), - ]) - ], + animations: [trigger('sessionAnimation', [transition(':enter', [style({ opacity: 0 }), animate('400ms', style({ opacity: 1 }))])])], changeDetection: ChangeDetectionStrategy.OnPush }) export class SessionComponent implements OnInit { @@ -77,6 +80,7 @@ export class SessionComponent implements OnInit { protected layoutWidthSubscription: Subscription; protected updateLayoutInterval: NodeJS.Timer; + private captionLanguageSubscription: Subscription; protected log: ILogger; @@ -92,6 +96,7 @@ export class SessionComponent implements OnInit { protected panelService: PanelService, private recordingService: RecordingService, private translateService: TranslateService, + private captionService: CaptionService, private platformService: PlatformService, private cd: ChangeDetectorRef ) { @@ -153,6 +158,7 @@ export class SessionComponent implements OnInit { } this.session = this.openviduService.getWebcamSession(); this.sessionScreen = this.openviduService.getScreenSession(); + this.subscribeToCaptionLanguage(); this.subscribeToConnectionCreatedAndDestroyed(); this.subscribeToStreamCreated(); this.subscribeToStreamDestroyed(); @@ -284,7 +290,7 @@ export class SessionComponent implements OnInit { } private subscribeToStreamCreated() { - this.session.on('streamCreated', (event: StreamEvent) => { + this.session.on('streamCreated', async (event: StreamEvent) => { const connectionId = event.stream?.connection?.connectionId; const data = event.stream?.connection?.data; @@ -293,14 +299,39 @@ export class SessionComponent implements OnInit { const subscriber: Subscriber = this.session.subscribe(event.stream, undefined); this.participantService.addRemoteConnection(connectionId, data, subscriber); // this.oVSessionService.sendNicknameSignal(event.stream.connection); + try { + await this.session.subscribeToSpeechToText(event.stream, this.captionService.getLangSelected().ISO); + } catch (error) { + this.log.e('Error subscribing from STT: ', error); + } } }); } private subscribeToStreamDestroyed() { - this.session.on('streamDestroyed', (event: StreamEvent) => { + this.session.on('streamDestroyed', async (event: StreamEvent) => { const connectionId = event.stream.connection.connectionId; this.participantService.removeConnectionByConnectionId(connectionId); + try { + await this.session.unsubscribeFromSpeechToText(event.stream); + } catch (error) { + this.log.e('Error unsubscribing from STT: ', error); + } + }); + } + + private subscribeToCaptionLanguage() { + this.captionLanguageSubscription = this.captionService.captionLangObs.subscribe(async (lang) => { + // 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()) { + try { + await this.session.unsubscribeFromSpeechToText(participant.getCameraConnection().streamManager.stream); + await this.session.subscribeToSpeechToText(participant.getCameraConnection().streamManager.stream, lang.ISO); + } catch (error) { + this.log.e('Error re-subscribing to STT: ', error); + } + } }); } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.css similarity index 100% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.css rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.css diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.html similarity index 60% rename from openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.html rename to openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.html index e246b6ab..b2af9884 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.html +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.html @@ -1,21 +1,18 @@ -
{{ 'PANEL.SETTINGS.SUBTITLE' | translate }}
- +
{{ 'PANEL.SETTINGS.CAPTIONS' | translate }}
+
{{ 'PANEL.SETTINGS.LANGUAGE' | translate }}:
-
- - - diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.spec.ts new file mode 100644 index 00000000..827a8013 --- /dev/null +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CaptionsSettingComponent } from './captions.component'; + +describe('CaptionsSettingComponent', () => { + let component: CaptionsSettingComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CaptionsSettingComponent] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CaptionsSettingComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.ts new file mode 100644 index 00000000..0f77c2fc --- /dev/null +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/captions/captions.component.ts @@ -0,0 +1,47 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Subscription } from 'rxjs'; +import { CaptionService } from '../../../services/caption/caption.service'; +import { LayoutService } from '../../../services/layout/layout.service'; + +/** + * @internal + */ +@Component({ + selector: 'ov-captions-settings', + templateUrl: './captions.component.html', + styleUrls: ['./captions.component.css'] +}) +export class CaptionsSettingComponent implements OnInit, OnDestroy { + captionsEnabled: boolean; + languagesAvailable: { name: string; ISO: string }[] = []; + captionsSubscription: Subscription; + langSelected: string; + + constructor(private layoutService: LayoutService, private captionService: CaptionService) {} + + ngOnInit(): void { + this.subscribeToCaptions(); + this.langSelected = this.captionService.getLangSelected().name; + this.languagesAvailable = this.captionService.getCaptionLanguages(); + } + + ngOnDestroy() { + if (this.captionsSubscription) this.captionsSubscription.unsubscribe(); + } + + onLangSelected(lang: { name: string; ISO: string }) { + this.langSelected = lang.name; + this.captionService.setLanguage(lang.ISO); + } + + toggleCaptions() { + this.layoutService.toggleCaptions(); + } + + private subscribeToCaptions() { + this.captionsSubscription = this.layoutService.captionsTogglingObs.subscribe((value: boolean) => { + this.captionsEnabled = value; + // this.cd.markForCheck(); + }); + } +} diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.spec.ts deleted file mode 100644 index 4c6d1353..00000000 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { SubtitlesComponent } from './subtitles.component'; - -describe('SubtitlesComponent', () => { - let component: SubtitlesComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ SubtitlesComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(SubtitlesComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.ts deleted file mode 100644 index 715b2800..00000000 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/subtitles/subtitles.component.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { Subscription } from 'rxjs'; -import { LayoutService } from '../../../services/layout/layout.service'; - - -/** - * @internal - */ -@Component({ - selector: 'ov-subtitles-settings', - templateUrl: './subtitles.component.html', - styleUrls: ['./subtitles.component.css'] -}) -export class SubtitlesSettingComponent implements OnInit, OnDestroy { - subtitlesEnabled: boolean; - languagesAvailable = []; - subtitlesSubs: Subscription; - langSelected: string = 'English'; - - constructor(private layoutService: LayoutService) {} - - ngOnInit(): void { - this.subscribeToSubtitles(); - } - - ngOnDestroy() { - if (this.subtitlesSubs) this.subtitlesSubs.unsubscribe(); - } - - onLangSelected(lang: string) { - this.langSelected = lang; - } - - toggleSubtitles() { - this.layoutService.toggleSubtitles(); - } - - private subscribeToSubtitles() { - this.subtitlesSubs = this.layoutService.subtitlesTogglingObs.subscribe((value: boolean) => { - this.subtitlesEnabled = value; - // this.cd.markForCheck(); - }); - } -} diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.html index 98737a6b..0c7e5f1a 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.html +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.html @@ -103,17 +103,17 @@ {{ 'TOOLBAR.BACKGROUND' | translate }} - + diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts index c37cddf6..66f702a6 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/toolbar/toolbar.component.ts @@ -308,12 +308,12 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { /** * @ignore */ - showSubtitlesButton: boolean = true; + showCaptionsButton: boolean = true; /** * @ignore */ - subtitlesEnabled: boolean; + captionsEnabled: boolean; /** * @ignore @@ -362,7 +362,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { private displaySessionNameSub: Subscription; private screenSizeSub: Subscription; private settingsButtonSub: Subscription; - private subtitlesSubs: Subscription; + private captionsSubs: Subscription; private currentWindowHeight = window.innerHeight; /** @@ -425,7 +425,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { this.subscribeToChatMessages(); this.subscribeToRecordingStatus(); this.subscribeToScreenSize(); - this.subscribeToSubtitlesToggling(); + this.subscribeToCaptionsToggling(); } ngAfterViewInit() { @@ -453,7 +453,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { if (this.recordingSubscription) this.recordingSubscription.unsubscribe(); if (this.screenSizeSub) this.screenSizeSub.unsubscribe(); if (this.settingsButtonSub) this.settingsButtonSub.unsubscribe(); - if (this.subtitlesSubs) this.subtitlesSubs.unsubscribe(); + if (this.captionsSubs) this.captionsSubs.unsubscribe(); } /** @@ -547,8 +547,8 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { /** * @ignore */ - toggleSubtitles() { - this.layoutService.toggleSubtitles(); + toggleCaptions() { + this.layoutService.toggleCaptions(); } /** @@ -697,8 +697,8 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { this.showSessionName = value; this.cd.markForCheck(); }); - this.subtitlesSubs = this.libService.subtitlesButtonObs.subscribe((value: boolean) => { - this.showSubtitlesButton = value; + this.captionsSubs = this.libService.captionsButtonObs.subscribe((value: boolean) => { + this.showCaptionsButton = value; this.cd.markForCheck(); }); } @@ -710,9 +710,9 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit { }); } - private subscribeToSubtitlesToggling() { - this.subtitlesSubs = this.layoutService.subtitlesTogglingObs.subscribe((value: boolean) => { - this.subtitlesEnabled = value; + private subscribeToCaptionsToggling() { + this.captionsSubs = this.layoutService.captionsTogglingObs.subscribe((value: boolean) => { + this.captionsEnabled = value; this.cd.markForCheck(); }); } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.css b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.css index bb53cbdc..92035d1e 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.css +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.css @@ -27,5 +27,5 @@ /* Private css variables */ #call-container { - --ov-captions-height: 250px; + --ov-captions-height: 230px; } \ No newline at end of file diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts index 81c50228..c0e61891 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts @@ -56,12 +56,14 @@ import { TranslateService } from '../../services/translate/translate.service'; * | :----------------------------: | :-------: | :---------------------------------------------: | * | **minimal** | `boolean` | {@link MinimalDirective} | * | **lang** | `string` | {@link LangDirective} | + * | **captionsLang** | `string` | {@link CaptionsLangDirective} | * | **prejoin** | `boolean` | {@link PrejoinDirective} | * | **participantName** | `string` | {@link ParticipantNameDirective} | * | **videoMuted** | `boolean` | {@link VideoMutedDirective} | * | **audioMuted** | `boolean` | {@link AudioMutedDirective} | * | **toolbarScreenshareButton** | `boolean` | {@link ToolbarScreenshareButtonDirective} | * | **toolbarFullscreenButton** | `boolean` | {@link ToolbarFullscreenButtonDirective} | + * | **toolbarCaptionsButton** | `boolean` | {@link ToolbarCaptionsButtonDirective} | * | **toolbarBackgroundEffectsButton** | `boolean` | {@link ToolbarBackgroundEffectsButtonDirective} | * | **toolbarLeaveButton** | `boolean` | {@link ToolbarLeaveButtonDirective} | * | **toolbarChatPanelButton** | `boolean` | {@link ToolbarChatPanelButtonDirective} | @@ -457,8 +459,8 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni const publisher = await this.openviduService.initDefaultPublisher(); if (publisher) { - publisher.once('accessDenied', (e: any) => { - this.handlePublisherError(e); + publisher.once('accessDenied', async (e: any) => { + await this.handlePublisherError(e); resolve(); }); publisher.once('accessAllowed', async () => { @@ -662,20 +664,20 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni this.onSessionCreated.emit(session); } - private handlePublisherError(e: any): Promise { + private async handlePublisherError(e: any): Promise { let message: string = ''; console.log('ERROR!', e); if (e.name === OpenViduErrorName.DEVICE_ALREADY_IN_USE) { this.log.w('Video device already in use. Disabling video device...'); // Allow access to the room with only mic if camera device is already in use this.deviceSrv.disableVideoDevices(); - return this.initwebcamPublisher(); + return await this.initwebcamPublisher(); } if (e.name === OpenViduErrorName.DEVICE_ACCESS_DENIED) { message = this.translateService.translate('ERRORS.MEDIA_ACCESS'); this.deviceSrv.disableVideoDevices(); this.deviceSrv.disableAudioDevices(); - return this.initwebcamPublisher(); + return await this.initwebcamPublisher(); } else if (e.name === OpenViduErrorName.NO_INPUT_SOURCE_SET) { message = this.translateService.translate('ERRORS.DEVICE_NOT_FOUND'); } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/api.directive.module.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/api.directive.module.ts index 1e0e3daf..55d7370f 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/api.directive.module.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/api.directive.module.ts @@ -5,37 +5,39 @@ import { LogoDirective } from './internals.directive'; import { ParticipantPanelItemMuteButtonDirective } from './participant-panel-item.directive'; import { RecordingActivityRecordingErrorDirective, RecordingActivityRecordingsListDirective } from './recording-activity.directive'; import { - StreamDisplayParticipantNameDirective, StreamDisplayAudioDetectionDirective, + StreamDisplayParticipantNameDirective, StreamSettingsButtonDirective } from './stream.directive'; import { - ToolbarScreenshareButtonDirective, + ToolbarActivitiesPanelButtonDirective, + ToolbarBackgroundEffectsButtonDirective, + ToolbarCaptionsButtonDirective, + ToolbarChatPanelButtonDirective, + ToolbarDisplayLogoDirective, + ToolbarDisplaySessionNameDirective, ToolbarFullscreenButtonDirective, ToolbarLeaveButtonDirective, ToolbarParticipantsPanelButtonDirective, - ToolbarChatPanelButtonDirective, - ToolbarDisplaySessionNameDirective, - ToolbarDisplayLogoDirective, - ToolbarActivitiesPanelButtonDirective, - ToolbarBackgroundEffectsButtonDirective, ToolbarRecordingButtonDirective, - ToolbarSettingsButtonDirective, - ToolbarCaptionsButtonDirective + ToolbarScreenshareButtonDirective, + ToolbarSettingsButtonDirective } from './toolbar.directive'; import { AudioMutedDirective, + CaptionsLangDirective, + LangDirective, MinimalDirective, - PrejoinDirective, - VideoMutedDirective, ParticipantNameDirective, - LangDirective + PrejoinDirective, + VideoMutedDirective } from './videoconference.directive'; @NgModule({ declarations: [ MinimalDirective, LangDirective, + CaptionsLangDirective, PrejoinDirective, VideoMutedDirective, AudioMutedDirective, @@ -66,6 +68,7 @@ import { exports: [ MinimalDirective, LangDirective, + CaptionsLangDirective, PrejoinDirective, VideoMutedDirective, AudioMutedDirective, diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/internals.directive.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/internals.directive.ts index 18156714..b5253103 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/internals.directive.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/internals.directive.ts @@ -6,7 +6,7 @@ import { Directive, ElementRef, HostListener, Input } from '@angular/core'; * Load default OpenVidu logo if custom one is not exist * @internal */ - @Directive({ +@Directive({ selector: 'img[ovLogo]' }) export class LogoDirective { diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/toolbar.directive.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/toolbar.directive.ts index de5ce0f8..98abaaa7 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/toolbar.directive.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/toolbar.directive.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnDestroy } from '@angular/core'; +import { AfterViewInit, Directive, ElementRef, Input, OnDestroy } from '@angular/core'; import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service'; /** @@ -256,9 +256,6 @@ export class ToolbarBackgroundEffectsButtonDirective implements AfterViewInit, O * And it also can be used in the {@link ToolbarComponent}. * @example * - * - * TODO: Make it public when speech to text is integrated - * @internal */ @Directive({ selector: 'ov-videoconference[toolbarCaptionsButton], ov-toolbar[captionsButton]' @@ -298,8 +295,8 @@ export class ToolbarCaptionsButtonDirective implements AfterViewInit, OnDestroy } private update(value: boolean) { - if (this.libService.subtitlesButton.getValue() !== value) { - this.libService.subtitlesButton.next(value); + if (this.libService.captionsButton.getValue() !== value) { + this.libService.captionsButton.next(value); } } } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/videoconference.directive.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/videoconference.directive.ts index a905bea0..55036d09 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/videoconference.directive.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/videoconference.directive.ts @@ -1,7 +1,9 @@ -import { Directive, Input, ElementRef, OnDestroy, OnInit } from '@angular/core'; +import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { CaptionService } from '../../services/caption/caption.service'; import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service'; import { TranslateService } from '../../services/translate/translate.service'; + /** * The **minimal** directive applies a minimal UI hiding all controls except for cam and mic. * @@ -53,7 +55,7 @@ export class MinimalDirective implements OnDestroy { } /** - * The **lang** directive allows et the UI language to a default language. + * The **lang** directive allows set the UI language to a default language. * * It is only available for {@link VideoconferenceComponent}. * @@ -113,6 +115,70 @@ export class LangDirective implements OnDestroy { } } +/** + * The **captions-lang** directive allows specify the language of room's members + * + * It is only available for {@link VideoconferenceComponent}. + * + * It must be a valid [BCP-47](https://tools.ietf.org/html/bcp47) language tag like "en-US" or "es-ES". + * + * + * **Default:** English `en-US` + * + * **Available:** + * + * * English: `en-US` + * * Spanish: `es-ES` + * * German: `de-DE` + * * French: `fr-FR` + * * Chinese: `zh-CN` + * * Hindi: `hi-IN` + * * Italian: `it-IT` + * * Japanese: `jp-JP` + * * Portuguese: `pt-PT` + * + * @example + * + */ + @Directive({ + selector: 'ov-videoconference[captionsLang]' +}) +export class CaptionsLangDirective implements OnDestroy { + /** + * @ignore + */ + @Input() set captionsLang(value: string) { + this.update(value); + } + + /** + * @ignore + */ + constructor(public elementRef: ElementRef, private captionService: CaptionService) {} + + /** + * @ignore + */ + ngOnDestroy(): void { + this.clear(); + } + + /** + * @ignore + */ + clear() { + this.update('en-US'); + } + + /** + * @ignore + */ + update(value: string) { + this.captionService.setLanguage(value); + } +} + + /** * The **participantName** directive sets the participant name. It can be useful for aplications which doesn't need the prejoin page. * diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/cn.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/cn.json index 5c2f6bf4..af3c82c3 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/cn.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/cn.json @@ -34,8 +34,8 @@ "MORE_OPTIONS":"更多选项", "FULLSCREEN":"全屏", "EXIT_FULLSCREEN": "退出全屏", - "ENABLE_SUBTITLES": "启用字幕", - "DISABLE_SUBTITLES": "禁用字幕", + "ENABLE_CAPTIONS": "启用字幕", + "DISABLE_CAPTIONS": "禁用字幕", "BACKGROUND":"背景效果", "START_RECORDING": "开始录音", "STOP_RECORDING": "停止录制", @@ -73,7 +73,7 @@ "VIDEO": "视频", "AUDIO": "声音的", "LANGUAGE": "语", - "SUBTITLE": "字幕" + "CAPTIONS": "字幕" }, "BACKGROUND": { "TITLE": "背景效果", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/de.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/de.json index a2347467..cf03eb57 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/de.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/de.json @@ -34,8 +34,8 @@ "MORE_OPTIONS": "Weitere Optionen", "FULLSCREEN": "Vollbild", "EXIT_FULLSCREEN": "Vollbildmodus beenden", - "ENABLE_SUBTITLES": "Untertitel aktivieren", - "DISABLE_SUBTITLES": "Untertitel deaktivieren", + "ENABLE_CAPTIONS": "Untertitel aktivieren", + "DISABLE_CAPTIONS": "Untertitel deaktivieren", "BACKGROUND": "Hintergrund-Effekte", "START_RECORDING": "Aufzeichnung starten", "STOP_RECORDING": "Aufzeichnung stoppen", @@ -73,7 +73,7 @@ "VIDEO": "Video", "AUDIO": "Audio", "LANGUAGE": "Sprache", - "SUBTITLE": "Untertitel" + "CAPTIONS": "Untertitel" }, "BACKGROUND": { "TITLE": "Hintergrund-Effekte", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/en.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/en.json index 37b9bf19..ecf0df81 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/en.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/en.json @@ -35,8 +35,8 @@ "MORE_OPTIONS": "More options", "FULLSCREEN": "Fullscreen", "EXIT_FULLSCREEN": "Exit fullscreen", - "ENABLE_SUBTITLES": "Enable subtitles", - "DISABLE_SUBTITLES": "Disable subtitles", + "ENABLE_CAPTIONS": "Enable captions", + "DISABLE_CAPTIONS": "Disable captions", "BACKGROUND": "Background effects", "START_RECORDING": "Start recording", "STOP_RECORDING": "Stop recording", @@ -74,7 +74,7 @@ "VIDEO": "Video", "AUDIO": "Audio", "LANGUAGE": "Language", - "SUBTITLE": "Subtitles" + "CAPTIONS": "Captions" }, "BACKGROUND": { "TITLE": "Background effects", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/es.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/es.json index 89083587..2b6d9123 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/es.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/es.json @@ -34,8 +34,8 @@ "MORE_OPTIONS": "Más opciones", "EXIT_FULLSCREEN": "Quitar pantalla completa", "FULLSCREEN": "Pantalla completa", - "ENABLE_SUBTITLES": "Activar subtítulos", - "DISABLE_SUBTITLES": "Desactivar subtítulos", + "ENABLE_CAPTIONS": "Activar subtítulos", + "DISABLE_CAPTIONS": "Desactivar subtítulos", "BACKGROUND": "Efectos de fondo", "START_RECORDING": "Iniciar grabación", "STOP_RECORDING": "Detener grabación", @@ -73,7 +73,7 @@ "VIDEO": "Video", "AUDIO": "Audio", "LANGUAGE": "Idioma", - "SUBTITLE": "Subtítulos" + "CAPTIONS": "Subtítulos" }, "BACKGROUND": { "TITLE": "Efectos de fondo", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/fr.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/fr.json index 13e17cd1..b2f88fb9 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/fr.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/fr.json @@ -34,8 +34,8 @@ "MORE_OPTIONS": "Plus d'options", "FULLSCREEN": "Plein écran", "EXIT_FULLSCREEN": "Quitter le plein écran", - "ENABLE_SUBTITLES": "Activer les sous-titres", - "DISABLE_SUBTITLES": "Désactiver les sous-titres", + "ENABLE_CAPTIONS": "Activer les sous-titres", + "DISABLE_CAPTIONS": "Désactiver les sous-titres", "BACKGROUND": "Effets de fond", "START_RECORDING": "démarrer l'enregistrement", "STOP_RECORDING": "Arrêter l'enregistrement", @@ -73,7 +73,7 @@ "VIDEO": "Vidéo", "AUDIO": "l'audio", "LANGUAGE": "Langue", - "SUBTITLE": "Les sous-titres" + "CAPTIONS": "Les sous-titres" }, "BACKGROUND": { "TITLE": "Effets de fond", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/hi.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/hi.json index 9b9ad590..a59d0d7d 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/hi.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/hi.json @@ -34,8 +34,8 @@ "MORE_OPTIONS": "अधिक विकल्प", "FULLSCREEN": "पूर्ण स्क्रीन", "EXIT_FULLSCREEN": "पूर्ण स्क्रीन से बाहर निकलें", - "ENABLE_SUBTITLES": "उपशीर्षक सक्षम करें", - "DISABLE_SUBTITLES": "उपशीर्षक अक्षम करें", + "ENABLE_CAPTIONS": "उपशीर्षक सक्षम करें", + "DISABLE_CAPTIONS": "उपशीर्षक अक्षम करें", "BACKGROUND": "पृष्ठभूमि प्रभाव", "START_RECORDING": "रिकॉर्डिंग प्रारंभ करें", "STOP_RECORDING": "रिकॉर्डिंग रोकें", @@ -73,7 +73,7 @@ "VIDEO": "वीडियो", "AUDIO": "ऑडियो", "LANGUAGE": "भाषा", - "SUBTITLE": "उपशीर्षक" + "CAPTIONS": "उपशीर्षक" }, "BACKGROUND": { "TITLE": "पृष्ठभूमि प्रभाव", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/it.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/it.json index a12c423b..bbc75713 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/it.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/it.json @@ -34,8 +34,8 @@ "MORE_OPTIONS": "Altre opzioni", "FULLSCREEN": "Schermo intero", "EXIT_FULLSCREEN": "Esci dallo schermo intero", - "ENABLE_SUBTITLES": "Abilita i sottotitoli", - "DISABLE_SUBTITLES": "Disabilita i sottotitoli", + "ENABLE_CAPTIONS": "Abilita i sottotitoli", + "DISABLE_CAPTIONS": "Disabilita i sottotitoli", "BACKGROUND": "Effetti di sfondo", "START_RECORDING": "Avvia registrazione", "STOP_RECORDING": "Interrompi registrazione", @@ -73,7 +73,7 @@ "VIDEO": "video", "AUDIO": "Audio", "LANGUAGE":"Lingua", - "SUBTITLE": "Sottotitoli" + "CAPTIONS": "Sottotitoli" }, "BACKGROUND": { "TITLE": "Effetti di sfondo", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/ja.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/ja.json index 1dbe11c3..64fa201f 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/ja.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/ja.json @@ -34,8 +34,8 @@ "MORE_OPTIONS": "その他のオプション", "FULLSCREEN": "フルスクリーン", "EXIT_FULLSCREEN": "フルスクリーンを終了する", - "ENABLE_SUBTITLES": "字幕を有効にする", - "DISABLE_SUBTITLES": "字幕を無効にする", + "ENABLE_CAPTIONS": "字幕を有効にする", + "DISABLE_CAPTIONS": "字幕を無効にする", "BACKGROUND": "背景効果", "START_RECORDING": "録画開始", "STOP_RECORDING": "録画の停止", @@ -73,7 +73,7 @@ "VIDEO": "ビデオ", "AUDIO": "オーディオ", "LANGUAGE":"言語", - "SUBTITLE": "字幕" + "CAPTIONS": "字幕" }, "BACKGROUND": { "TITLE": "背景効果", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/nl.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/nl.json index 18ad397e..1008ea89 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/nl.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/nl.json @@ -34,8 +34,8 @@ "MORE_OPTIONS": "Meer opties", "FULLSCREEN": "Volledig scherm", "EXIT_FULLSCREEN": "Volledig scherm verlaten", - "ENABLE_SUBTITLES": "Ondertiteling inschakelen", - "DISABLE_SUBTITLES": "Ondertiteling uitschakelen", + "ENABLE_CAPTIONS": "Ondertiteling inschakelen", + "DISABLE_CAPTIONS": "Ondertiteling uitschakelen", "BACKGROUND": "Achtergrondeffecten", "START_RECORDING": "Start opname", "STOP_RECORDING": "Stop opname", @@ -73,7 +73,7 @@ "VIDEO": "Video", "AUDIO": "Audio", "LANGUAGE":"Taal", - "SUBTITLE": "Ondertitels" + "CAPTIONS": "Ondertitels" }, "BACKGROUND": { "TITLE": "Achtergrondeffecten", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/pt.json b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/pt.json index eac46ac1..ba8c69e0 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/pt.json +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/lang/pt.json @@ -34,8 +34,8 @@ "MORE_OPTIONS": "Mais opções", "FULLSCREEN": "Tela cheia", "EXIT_FULLSCREEN": "Sair da tela cheia", - "ENABLE_SUBTITLES": "Ativar legendas", - "DISABLE_SUBTITLES": "Desativar legendas", + "ENABLE_CAPTIONS": "Ativar legendas", + "DISABLE_CAPTIONS": "Desativar legendas", "BACKGROUND": "Efeitos de fundo", "START_RECORDING": "Iniciar_gravação", "STOP_RECORDING": "Parar de gravar", @@ -73,7 +73,7 @@ "VIDEO": "Vídeo", "AUDIO": "Áudio", "LANGUAGE":"Linguagem", - "SUBTITLE": "Legendas" + "CAPTIONS": "Legendas" }, "BACKGROUND": { "TITLE": "Efeitos de fundo", diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/models/caption.model.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/models/caption.model.ts new file mode 100644 index 00000000..64d9a723 --- /dev/null +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/models/caption.model.ts @@ -0,0 +1,10 @@ + +export interface CaptionModel { + + connectionId: string; + nickname: string; + color: string; + type: 'recognizing' | 'recognized'; + text: string; +} + diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/models/panel.model.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/models/panel.model.ts index 2382ce05..9082c65c 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/models/panel.model.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/models/panel.model.ts @@ -11,5 +11,5 @@ export enum PanelSettingsOptions { GENERAL = 'general', AUDIO = 'audio', VIDEO = 'video', - SUBTITLES = 'subtitles' + CAPTIONS = 'captions' } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/models/storage.model.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/models/storage.model.ts index 706439a4..199e7556 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/models/storage.model.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/models/storage.model.ts @@ -7,5 +7,6 @@ export enum Storage { AUDIO_DEVICE = 'openviduCallAudioDevice', AUDIO_MUTED = 'openviduCallAudioMuted', VIDEO_MUTED = 'openviduCallVideoMuted', - LANG = "openviduCallLang" -} \ No newline at end of file + LANG = 'openviduCallLang', + CAPTION_LANG = 'openviduCallCaptionLang' +} diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/openvidu-angular.module.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/openvidu-angular.module.ts index 6e81bbed..ad4431c6 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/openvidu-angular.module.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/openvidu-angular.module.ts @@ -1,66 +1,66 @@ +import { OverlayContainer } from '@angular/cdk/overlay'; +import { CommonModule } from '@angular/common'; +import { HttpClientModule } from '@angular/common/http'; +import { ModuleWithProviders, NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { RouterModule } from '@angular/router'; -import { CommonModule } from '@angular/common'; -import { ModuleWithProviders, NgModule } from '@angular/core'; -import { HttpClientModule } from '@angular/common/http'; -import { OverlayContainer } from '@angular/cdk/overlay'; -import { ToolbarComponent } from './components/toolbar/toolbar.component'; -import { VideoComponent } from './components/video/video.component'; -import { ChatPanelComponent } from './components/panel/chat-panel/chat-panel.component'; -import { SessionComponent } from './components/session/session.component'; -import { LayoutComponent } from './components/layout/layout.component'; -import { StreamComponent } from './components/stream/stream.component'; +import { DeleteDialogComponent } from './components/dialogs/delete-recording.component'; import { DialogTemplateComponent } from './components/dialogs/dialog.component'; import { RecordingDialogComponent } from './components/dialogs/recording-dialog.component'; -import { DeleteDialogComponent } from './components/dialogs/delete-recording.component'; +import { LayoutComponent } from './components/layout/layout.component'; +import { ChatPanelComponent } from './components/panel/chat-panel/chat-panel.component'; +import { SessionComponent } from './components/session/session.component'; +import { StreamComponent } from './components/stream/stream.component'; +import { ToolbarComponent } from './components/toolbar/toolbar.component'; +import { VideoComponent } from './components/video/video.component'; import { LinkifyPipe } from './pipes/linkify.pipe'; -import { TranslatePipe } from './pipes/translate.pipe'; -import { StreamTypesEnabledPipe, ParticipantStreamsPipe } from './pipes/participant.pipe'; +import { ParticipantStreamsPipe, StreamTypesEnabledPipe } from './pipes/participant.pipe'; import { DurationFromSecondsPipe, SearchByStringPropertyPipe, ThumbnailFromUrlPipe } from './pipes/recording.pipe'; +import { TranslatePipe } from './pipes/translate.pipe'; -import { OpenViduAngularConfig } from './config/openvidu-angular.config'; import { CdkOverlayContainer } from './config/custom-cdk-overlay'; -import { DeviceService } from './services/device/device.service'; -import { LoggerService } from './services/logger/logger.service'; -import { PlatformService } from './services/platform/platform.service'; -import { StorageService } from './services/storage/storage.service'; -import { TokenService } from './services/token/token.service'; -import { OpenViduAngularConfigService } from './services/config/openvidu-angular.config.service'; -import { OpenViduService } from './services/openvidu/openvidu.service'; +import { OpenViduAngularConfig } from './config/openvidu-angular.config'; import { ActionService } from './services/action/action.service'; import { ChatService } from './services/chat/chat.service'; +import { OpenViduAngularConfigService } from './services/config/openvidu-angular.config.service'; +import { DeviceService } from './services/device/device.service'; import { DocumentService } from './services/document/document.service'; import { LayoutService } from './services/layout/layout.service'; +import { LoggerService } from './services/logger/logger.service'; +import { OpenViduService } from './services/openvidu/openvidu.service'; import { PanelService } from './services/panel/panel.service'; import { ParticipantService } from './services/participant/participant.service'; +import { PlatformService } from './services/platform/platform.service'; import { RecordingService } from './services/recording/recording.service'; +import { StorageService } from './services/storage/storage.service'; +import { TokenService } from './services/token/token.service'; +import { AudioWaveComponent } from './components/audio-wave/audio-wave.component'; +import { PanelComponent } from './components/panel/panel.component'; import { ParticipantPanelItemComponent } from './components/panel/participants-panel/participant-panel-item/participant-panel-item.component'; import { ParticipantsPanelComponent } from './components/panel/participants-panel/participants-panel/participants-panel.component'; -import { VideoconferenceComponent } from './components/videoconference/videoconference.component'; -import { PanelComponent } from './components/panel/panel.component'; -import { AudioWaveComponent } from './components/audio-wave/audio-wave.component'; import { PreJoinComponent } from './components/pre-join/pre-join.component'; +import { VideoconferenceComponent } from './components/videoconference/videoconference.component'; -import { AvatarProfileComponent } from './components/avatar-profile/avatar-profile.component'; -import { OpenViduAngularDirectiveModule } from './directives/template/openvidu-angular.directive.module'; -import { ApiDirectiveModule } from './directives/api/api.directive.module'; -import { BackgroundEffectsPanelComponent } from './components/panel/background-effects-panel/background-effects-panel.component'; -import { SettingsPanelComponent } from './components/panel/settings-panel/settings-panel.component'; -import { ActivitiesPanelComponent } from './components/panel/activities-panel/activities-panel.component'; -import { RecordingActivityComponent } from './components/panel/activities-panel/recording-activity-panel/recording-activity.component'; import { AdminDashboardComponent } from './admin/dashboard/dashboard.component'; import { AdminLoginComponent } from './admin/login/login.component'; -import { AppMaterialModule } from './openvidu-angular.material.module'; -import { VideoDevicesComponent } from './components/settings/video-devices/video-devices.component'; -import { AudioDevicesComponent } from './components/settings/audio-devices/audio-devices.component'; -import { NicknameInputComponent } from './components/settings/nickname-input/nickname-input.component'; -import { LangSelectorComponent } from './components/settings/lang-selector/lang-selector.component'; -import { SubtitlesSettingComponent } from './components/settings/subtitles/subtitles.component'; +import { AvatarProfileComponent } from './components/avatar-profile/avatar-profile.component'; import { CaptionsComponent } from './components/captions/captions.component'; +import { ActivitiesPanelComponent } from './components/panel/activities-panel/activities-panel.component'; +import { RecordingActivityComponent } from './components/panel/activities-panel/recording-activity-panel/recording-activity.component'; +import { BackgroundEffectsPanelComponent } from './components/panel/background-effects-panel/background-effects-panel.component'; +import { SettingsPanelComponent } from './components/panel/settings-panel/settings-panel.component'; +import { AudioDevicesComponent } from './components/settings/audio-devices/audio-devices.component'; +import { CaptionsSettingComponent } from './components/settings/captions/captions.component'; +import { LangSelectorComponent } from './components/settings/lang-selector/lang-selector.component'; +import { NicknameInputComponent } from './components/settings/nickname-input/nickname-input.component'; +import { VideoDevicesComponent } from './components/settings/video-devices/video-devices.component'; import { CustomBreakPointsProvider, CustomLayoutExtensionDirective } from './config/custom-flexlayout-breakpoints'; +import { ApiDirectiveModule } from './directives/api/api.directive.module'; +import { OpenViduAngularDirectiveModule } from './directives/template/openvidu-angular.directive.module'; +import { AppMaterialModule } from './openvidu-angular.material.module'; const publicComponents = [ AdminDashboardComponent, @@ -92,7 +92,7 @@ const privateComponents = [ NicknameInputComponent, LangSelectorComponent, RecordingActivityComponent, - SubtitlesSettingComponent + CaptionsSettingComponent ]; @NgModule({ diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/caption/caption.service.spec.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/caption/caption.service.spec.ts new file mode 100644 index 00000000..9b330264 --- /dev/null +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/caption/caption.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { CaptionService } from './caption.service'; + +describe('CaptionService', () => { + let service: CaptionService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(CaptionService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/caption/caption.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/caption/caption.service.ts new file mode 100644 index 00000000..7a6a2594 --- /dev/null +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/caption/caption.service.ts @@ -0,0 +1,47 @@ +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; +import { StorageService } from '../storage/storage.service'; + +/** + * @internal + */ +@Injectable({ + providedIn: 'root' +}) +export class CaptionService { + private langTitles = [ + { name: 'English', ISO: 'en-US' }, + { name: 'Español', ISO: 'es-ES' }, + { name: 'Deutsch', ISO: 'de-DE' }, + { name: 'Français', ISO: 'fr-FR' }, + { name: '中国', ISO: 'zh-CN' }, + { name: 'हिन्दी', ISO: 'hi-IN' }, + { name: 'Italiano', ISO: 'it-IT' }, + { name: 'やまと', ISO: 'jp-JP' }, + { name: 'Português', ISO: 'pt-PT' } + ]; + captionLangSelected: { name: string; ISO: string }; + captionLangObs: Observable<{ name: string; ISO: string }>; + private _captionLangObs: Subject<{ name: string; ISO: string }> = new Subject(); + + + constructor(private storageService: StorageService) { + this.captionLangObs = this._captionLangObs.asObservable(); + } + + setLanguage(lang: string) { + if (this.langTitles.some((l) => l.ISO === lang)) { + this.captionLangSelected = this.langTitles.find((l) => l.ISO === lang); + this._captionLangObs.next(this.captionLangSelected); + this.storageService.setCaptionLang(lang); + } + } + + getLangSelected(): { name: string; ISO: string } { + return this.captionLangSelected || this.langTitles[0]; + } + + getCaptionLanguages(): { name: string; ISO: string }[] { + return this.langTitles; + } +} diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/config/openvidu-angular.config.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/config/openvidu-angular.config.service.ts index 8b7b50b0..0801e7be 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/config/openvidu-angular.config.service.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/config/openvidu-angular.config.service.ts @@ -28,8 +28,8 @@ export class OpenViduAngularConfigService { fullscreenButton = >new BehaviorSubject(true); fullscreenButtonObs: Observable; - subtitlesButton = >new BehaviorSubject(true); - subtitlesButtonObs: Observable; + captionsButton = >new BehaviorSubject(true); + captionsButtonObs: Observable; toolbarSettingsButton = >new BehaviorSubject(true); toolbarSettingsButtonObs: Observable; @@ -95,7 +95,7 @@ export class OpenViduAngularConfigService { this.displayLogoObs = this.displayLogo.asObservable(); this.recordingButtonObs = this.recordingButton.asObservable(); this.toolbarSettingsButtonObs = this.toolbarSettingsButton.asObservable(); - this.subtitlesButtonObs = this.subtitlesButton.asObservable(); + this.captionsButtonObs = this.captionsButton.asObservable(); //Stream observables this.displayParticipantNameObs = this.displayParticipantName.asObservable(); this.displayAudioDetectionObs = this.displayAudioDetection.asObservable(); diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/document/document.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/document/document.service.ts index 2f89f8d4..10484fd2 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/document/document.service.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/document/document.service.ts @@ -13,17 +13,7 @@ export class DocumentService { screenSizeObs: Observable; constructor(private media: MediaObserver) { - this.screenSizeObs= this.media.asObservable(); - } - - getHTMLElementByClassName(element: HTMLElement, className: string): HTMLElement { - while (!!element && element !== document.body) { - if (element.className.includes(className)) { - return element; - } - element = element.parentElement; - } - return null; + this.screenSizeObs = this.media.asObservable(); } toggleFullscreen(elementId: string) { diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/layout/layout.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/layout/layout.service.ts index e4544402..c4e460b8 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/layout/layout.service.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/layout/layout.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { LayoutAlignment, LayoutClass, OpenViduLayout, OpenViduLayoutOptions } from '../../models/layout.model'; -import { DocumentService } from '../document/document.service'; /** * @internal @@ -10,26 +9,24 @@ import { DocumentService } from '../document/document.service'; providedIn: 'root' }) export class LayoutService { - layoutContainer: HTMLElement | null = null; layoutWidthObs: Observable; - subtitlesTogglingObs: Observable; + captionsTogglingObs: Observable; private layoutWidth: BehaviorSubject = new BehaviorSubject(0); private openviduLayout: OpenViduLayout; private openviduLayoutOptions: OpenViduLayoutOptions; - private subtitlesToggling: BehaviorSubject = new BehaviorSubject(false); + private captionsToggling: BehaviorSubject = new BehaviorSubject(false); - - constructor(private documentService: DocumentService) { + constructor() { this.layoutWidthObs = this.layoutWidth.asObservable(); - this.subtitlesTogglingObs = this.subtitlesToggling.asObservable(); + this.captionsTogglingObs = this.captionsToggling.asObservable(); } initialize(container: HTMLElement) { this.layoutContainer = container; this.openviduLayout = new OpenViduLayout(); this.openviduLayoutOptions = this.getOptions(); - if(this.layoutContainer){ + if (this.layoutContainer) { this.openviduLayout.initLayoutContainer(this.layoutContainer, this.openviduLayoutOptions); } this.sendLayoutWidthEvent(); @@ -66,8 +63,8 @@ export class LayoutService { return options; } - toggleSubtitles() { - this.subtitlesToggling.next(!this.subtitlesToggling.getValue()); + toggleCaptions() { + this.captionsToggling.next(!this.captionsToggling.getValue()); } update(timeout: number = null) { @@ -93,7 +90,7 @@ export class LayoutService { } private sendLayoutWidthEvent() { - const sidenavLayoutElement = this.documentService.getHTMLElementByClassName( + const sidenavLayoutElement = this.getHTMLElementByClassName( this.openviduLayout?.getLayoutContainer(), LayoutClass.SIDENAV_CONTAINER ); @@ -101,4 +98,14 @@ export class LayoutService { this.layoutWidth.next(sidenavLayoutElement.clientWidth); } } + + private getHTMLElementByClassName(element: HTMLElement | null, className: string): HTMLElement | null { + while (!!element && element !== document.body) { + if (element.className.includes(className)) { + return element; + } + element = element.parentElement; + } + return null; + } } diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/storage/storage.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/storage/storage.service.ts index 3ed8762c..3e58b8c6 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/storage/storage.service.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/storage/storage.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { ILogger } from '../../models/logger.model'; -import { LoggerService } from '../logger/logger.service'; import { Storage } from '../../models/storage.model'; +import { LoggerService } from '../logger/logger.service'; /** * @internal @@ -62,6 +62,14 @@ export class StorageService { return this.get(Storage.LANG); } + setCaptionLang(lang: string){ + this.set(Storage.CAPTION_LANG, lang); + } + + getCaptionsLang(): string { + return this.get(Storage.CAPTION_LANG); + } + private set(key: string, item: any) { const value = JSON.stringify({ item: item }); // this.log.d('Storing on localStorage "' + key + '" with value "' + value + '"'); diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/translate/translate.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/translate/translate.service.ts index e5d0a221..cf593edc 100644 --- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/translate/translate.service.ts +++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/translate/translate.service.ts @@ -1,12 +1,12 @@ import { Injectable } from '@angular/core'; +import * as cn from '../../lang/cn.json'; +import * as de from '../../lang/de.json'; import * as en from '../../lang/en.json'; import * as es from '../../lang/es.json'; -import * as de from '../../lang/de.json'; import * as fr from '../../lang/fr.json'; -import * as cn from '../../lang/cn.json'; import * as hi from '../../lang/hi.json'; -import * as ja from '../../lang/ja.json'; import * as it from '../../lang/it.json'; +import * as ja from '../../lang/ja.json'; import * as nl from '../../lang/nl.json'; import * as pt from '../../lang/pt.json'; import { StorageService } from '../storage/storage.service'; @@ -36,7 +36,7 @@ export class TranslateService { constructor(private storageService: StorageService) { const iso = this.storageService.getLang() || 'en'; - this.langSelected = this.langTitles.find((lang) => lang.ISO === iso); + this.langSelected = this.langTitles.find((lang) => lang.ISO === iso) || this.langTitles[0]; this.currentLang = this.availableLanguages[this.langSelected.ISO]; }