openvidu-testapp: refactor TrackComponent

pull/848/head
pabloFuente 2024-10-04 13:25:44 +02:00
parent 4354561d5a
commit 0ce0e2acde
7 changed files with 98 additions and 120 deletions

View File

@ -1,5 +1,5 @@
<div class="parent-div">
<audio #audioElement [id]="elementRefId" [ngClass]="getTrackOrigin()"></audio>
<audio #mediaElement [id]="finalElementRefId" [ngClass]="getTrackOrigin()"></audio>
<span>{{trackPublication.source}}</span>
<div class="bottom-div">
<button *ngIf="localParticipant" (click)="muteUnmuteAudio()" class="audio-btn" matTooltip="Mute/Unmute audio"

View File

@ -1,60 +1,22 @@
import { Component, ElementRef, Input, ViewChild } from '@angular/core';
import { LocalTrack, AudioTrack, AudioCaptureOptions } from 'livekit-client';
import { Component } from '@angular/core';
import { LocalTrack } from 'livekit-client';
import { TrackComponent } from '../track/track.component';
@Component({
selector: 'app-audio-track',
templateUrl: './audio-track.component.html',
styleUrls: ['./audio-track.component.css']
styleUrls: ['./audio-track.component.css'],
})
export class AudioTrackComponent extends TrackComponent {
@ViewChild('audioElement') elementRef: ElementRef;
elementRefId: string = '';
muteAudioIcon: string = 'mic';
private _audioTrack: AudioTrack | undefined;
private audioCaptureOptions: AudioCaptureOptions;
@Input() set audioTrack(audioTrack: AudioTrack | undefined) {
this._audioTrack = audioTrack;
this.track = this._audioTrack;
this.setupTrackEventListeners();
let id = '';
id = `${this.getTrackOrigin()}--audio--${this._audioTrack?.source}--${this._audioTrack?.sid}`;
if (this._audioTrack?.sid !== this._audioTrack?.mediaStreamID) {
id += `--${this._audioTrack?.mediaStreamID}`;
}
id = id.replace(/[^0-9a-z-A-Z_-]+/g, '');
this.elementRefId = id;
if (this.elementRef && !this.localParticipant) {
this._audioTrack?.attach(this.elementRef.nativeElement);
}
}
ngAfterViewInit() {
if (!this.localParticipant) {
this._audioTrack?.attach(this.elementRef.nativeElement);
}
}
ngOnDestroy() {
this._audioTrack?.detach(this.elementRef.nativeElement);
}
async muteUnmuteAudio() {
if (this._audioTrack?.isMuted) {
if (this._track?.isMuted) {
this.muteAudioIcon = 'mic';
await (this._audioTrack as LocalTrack).unmute();
await (this._track as LocalTrack).unmute();
} else {
this.muteAudioIcon = 'mic_off';
await (this._audioTrack as LocalTrack).mute();
await (this._track as LocalTrack).mute();
}
}
}

View File

@ -51,13 +51,11 @@
</div>
<div class="audio-tracks-container">
<app-audio-track *ngFor="let trackPublication of participant.audioTrackPublications| keyvalue"
[trackPublication]="trackPublication.value" [audioTrack]="trackPublication.value.audioTrack"
[localParticipant]="localParticipant" [index]="index"
(newTrackEvent)="events.push($event)"></app-audio-track>
[index]="index" [trackPublication]="trackPublication.value" [track]="trackPublication.value.audioTrack"
[localParticipant]="localParticipant" (newTrackEvent)="events.push($event)"></app-audio-track>
</div>
<app-video-track *ngFor="let trackPublication of participant.videoTrackPublications | keyvalue ; index as i"
[trackPublication]="trackPublication.value" [videoTrack]="trackPublication.value.videoTrack"
[localParticipant]="localParticipant" [index]="index"
(newTrackEvent)="events.push($event)" [attr.id]="'user-' + index + '-' + participant.identity + '-video-' + i"></app-video-track>
<app-video-track *ngFor="let trackPublication of participant.videoTrackPublications | keyvalue"
[index]="index" [trackPublication]="trackPublication.value" [track]="trackPublication.value.videoTrack"
[localParticipant]="localParticipant" (newTrackEvent)="events.push($event)"></app-video-track>
</div>
</div>

View File

@ -1,4 +1,11 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import {
Component,
ElementRef,
EventEmitter,
Input,
Output,
ViewChild,
} from '@angular/core';
import {
TrackPublication,
LocalParticipant,
@ -9,6 +16,8 @@ import {
TrackEventCallbacks,
LocalTrackPublication,
RemoteTrackPublication,
AudioTrack,
VideoTrack,
} from 'livekit-client';
import {
TestAppEvent,
@ -35,18 +44,62 @@ export class TrackComponent {
@Input()
localParticipant: LocalParticipant | undefined;
@Input()
index: number;
protected finalElementRefId: string = '';
private indexId: string;
private trackId: string;
protected track: Track | undefined;
protected _track: Track | undefined;
@ViewChild('mediaElement') protected elementRef: ElementRef;
trackSubscribed: boolean = true;
trackEnabled: boolean = true;
constructor(protected testFeedService: TestFeedService) {}
@Input() set index(index: number) {
this.indexId = index.toString();
this.finalElementRefId = `participant-${this.indexId}-${this.trackId}`;
}
@Input() set track(track: AudioTrack | VideoTrack | undefined) {
this._track = track;
this.setupTrackEventListeners();
this.trackId = `-${this.getTrackOrigin()}--${this._track?.kind}--${
this._track?.source
}--${this._track?.sid}`;
if (this._track?.sid !== this._track?.mediaStreamID) {
this.trackId += `--${this._track?.mediaStreamID}`;
}
this.trackId = this.trackId.replace(/[^0-9a-z-A-Z_-]+/g, '');
this.finalElementRefId = `participant-${this.indexId}-${this.trackId}`;
this.attachTrack();
}
ngAfterViewInit() {
this.attachTrack();
}
ngOnDestroy() {
if (this.elementRef) {
this._track?.detach(this.elementRef.nativeElement);
}
}
private attachTrack() {
if (
this.elementRef &&
(this._track?.kind === Track.Kind.Video ||
(this._track?.kind === Track.Kind.Audio && !this.localParticipant))
) {
this._track.attach(this.elementRef.nativeElement);
}
}
protected async unpublishTrack() {
await this.localParticipant?.unpublishTrack(this.track as LocalTrack);
await this.localParticipant?.unpublishTrack(this._track as LocalTrack);
}
protected async toggleSubscribeTrack() {
@ -68,13 +121,13 @@ export class TrackComponent {
let callbacks: TrackEventCallbacks;
let events: TrackEvent;
this.track
this._track
?.on(TrackEvent.Message, () => {
this.newTrackEvent.emit({
eventType: TrackEvent.Message,
eventCategory: 'TrackEvent',
eventContent: {},
eventDescription: this.track!.source,
eventDescription: this._track!.source,
});
})
.on(TrackEvent.Muted, () => {
@ -82,7 +135,7 @@ export class TrackComponent {
eventType: TrackEvent.Muted,
eventCategory: 'TrackEvent',
eventContent: {},
eventDescription: this.track!.source,
eventDescription: this._track!.source,
});
})
.on(TrackEvent.Unmuted, () => {
@ -90,7 +143,7 @@ export class TrackComponent {
eventType: TrackEvent.Unmuted,
eventCategory: 'TrackEvent',
eventContent: {},
eventDescription: this.track!.source,
eventDescription: this._track!.source,
});
})
.on(TrackEvent.AudioSilenceDetected, () => {
@ -98,7 +151,7 @@ export class TrackComponent {
eventType: TrackEvent.AudioSilenceDetected,
eventCategory: 'TrackEvent',
eventContent: {},
eventDescription: this.track!.source,
eventDescription: this._track!.source,
});
})
.on(TrackEvent.Restarted, () => {
@ -106,7 +159,7 @@ export class TrackComponent {
eventType: TrackEvent.Restarted,
eventCategory: 'TrackEvent',
eventContent: {},
eventDescription: this.track!.source,
eventDescription: this._track!.source,
});
})
.on(TrackEvent.Ended, () => {
@ -114,23 +167,23 @@ export class TrackComponent {
eventType: TrackEvent.Ended,
eventCategory: 'TrackEvent',
eventContent: {},
eventDescription: this.track!.source,
eventDescription: this._track!.source,
});
})
.on(TrackEvent.VisibilityChanged, (visible: boolean) => {
this.newTrackEvent.emit({
eventType: TrackEvent.VisibilityChanged,
eventCategory: 'TrackEvent',
eventContent: { visible, track: this.track },
eventDescription: `${this.track!.source} is visible: ${visible}`,
eventContent: { visible, track: this._track },
eventDescription: `${this._track!.source} is visible: ${visible}`,
});
})
.on(TrackEvent.VideoDimensionsChanged, (dimensions: Track.Dimensions) => {
this.newTrackEvent.emit({
eventType: TrackEvent.VideoDimensionsChanged,
eventCategory: 'TrackEvent',
eventContent: { dimensions, track: this.track },
eventDescription: `${this.track?.source} ${JSON.stringify(
eventContent: { dimensions, track: this._track },
eventDescription: `${this._track?.source} ${JSON.stringify(
dimensions
)}`,
});
@ -140,7 +193,7 @@ export class TrackComponent {
eventType: TrackEvent.UpstreamPaused,
eventCategory: 'TrackEvent',
eventContent: {},
eventDescription: this.track!.source,
eventDescription: this._track!.source,
});
})
.on(TrackEvent.UpstreamResumed, () => {
@ -148,16 +201,16 @@ export class TrackComponent {
eventType: TrackEvent.UpstreamResumed,
eventCategory: 'TrackEvent',
eventContent: {},
eventDescription: this.track!.source,
eventDescription: this._track!.source,
});
});
}
protected getTrackOrigin(): string {
let origin: string;
if (this.track instanceof RemoteTrack) {
if (this._track instanceof RemoteTrack) {
origin = 'remote';
} else if (this.track instanceof LocalTrack) {
} else if (this._track instanceof LocalTrack) {
origin = 'local';
} else {
origin = 'unknown';

View File

@ -10,7 +10,7 @@ import { AudioTrack, VideoTrack } from 'livekit-client';
@Component({
selector: 'app-table-video',
template: `
<video #videoElement [id]="videoId" autoplay playsinline></video>
<video #mediaElement [id]="videoId" autoplay playsinline></video>
`,
styles: [
`
@ -21,7 +21,7 @@ import { AudioTrack, VideoTrack } from 'livekit-client';
],
})
export class TableVideoComponent implements AfterViewInit {
@ViewChild('videoElement') elementRef: ElementRef;
@ViewChild('mediaElement') elementRef: ElementRef;
@Input() videoId: string;

View File

@ -1,5 +1,5 @@
<div class="parent-div">
<video #videoElement [id]="elementRefId" [ngClass]="getTrackOrigin()"></video>
<video #mediaElement [id]="finalElementRefId" [ngClass]="getTrackOrigin()"></video>
<div class="bottom-div">
<button *ngIf="localParticipant" (click)="muteUnmuteVideo()" class="video-btn mute-unmute-video" matTooltip="Mute/Unmute video"
matTooltipClass="custom-tooltip">

View File

@ -1,10 +1,7 @@
import { Component, ElementRef, Input, ViewChild } from '@angular/core';
import { Component } from '@angular/core';
import {
LocalTrack,
VideoTrack,
VideoCaptureOptions,
ScreenShareCaptureOptions,
RemoteTrack,
RemoteTrackPublication,
VideoQuality,
} from 'livekit-client';
@ -19,36 +16,10 @@ import { InfoDialogComponent } from '../dialogs/info-dialog/info-dialog.componen
styleUrls: ['./video-track.component.css'],
})
export class VideoTrackComponent extends TrackComponent {
@ViewChild('videoElement') elementRef: ElementRef;
elementRefId: string = '';
muteVideoIcon: string = 'videocam';
blurIcon: string = 'blur_on';
private _videoTrack: VideoTrack | undefined;
maxVideoQuality: string;
@Input() set videoTrack(videoTrack: VideoTrack | undefined) {
this._videoTrack = videoTrack;
this.track = this._videoTrack;
this.setupTrackEventListeners();
let id = '';
id = `${this.getTrackOrigin()}--video--${this._videoTrack?.source}--${
this._videoTrack?.sid
}`;
if (this._videoTrack?.sid !== this._videoTrack?.mediaStreamID) {
id += `--${this._videoTrack?.mediaStreamID}`;
}
id = id.replace(/[^0-9a-z-A-Z_-]+/g, '');
this.elementRefId = id;
if (this.elementRef) {
this._videoTrack?.attach(this.elementRef.nativeElement);
}
}
constructor(
protected override testFeedService: TestFeedService,
private dialog: MatDialog
@ -56,21 +27,13 @@ export class VideoTrackComponent extends TrackComponent {
super(testFeedService);
}
ngAfterViewInit() {
this._videoTrack?.attach(this.elementRef.nativeElement);
}
ngOnDestroy() {
this._videoTrack?.detach(this.elementRef.nativeElement);
}
async muteUnmuteVideo() {
if (this._videoTrack?.isMuted) {
if (this._track?.isMuted) {
this.muteVideoIcon = 'videocam';
await (this._videoTrack as LocalTrack).unmute();
await (this._track as LocalTrack).unmute();
} else {
this.muteVideoIcon = 'videocam_off';
await (this._videoTrack as LocalTrack).mute();
await (this._track as LocalTrack).mute();
}
}
@ -97,7 +60,7 @@ export class VideoTrackComponent extends TrackComponent {
openInfoDialog() {
const updateFunction = async (): Promise<string> => {
const videoLayers: any[] = [];
let stats = await this._videoTrack?.getRTCStatsReport();
let stats = await (this._track! as VideoTrack).getRTCStatsReport();
stats?.forEach((report) => {
if (report.type === 'outbound-rtp' || report.type === 'inbound-rtp') {
videoLayers.push({
@ -108,6 +71,8 @@ export class VideoTrackComponent extends TrackComponent {
frameWidth: report.frameWidth,
frameHeight: report.frameHeight,
framesPerSecond: report.framesPerSecond,
bytesReceived: report.bytesReceived,
bytesSent: report.bytesSent,
});
}
});
@ -116,7 +81,7 @@ export class VideoTrackComponent extends TrackComponent {
this.dialog.open(InfoDialogComponent, {
data: {
title: 'Video Track Layers Info',
subtitle: this.elementRefId,
subtitle: this.finalElementRefId,
updateFunction,
},
});
@ -124,10 +89,10 @@ export class VideoTrackComponent extends TrackComponent {
async blur() {
if (this.blurIcon == 'blur_on') {
// await (this._videoTrack! as LocalVideoTrack).setProcessor(BackgroundBlur());
// await (this._track! as LocalVideoTrack).setProcessor(BackgroundBlur());
this.blurIcon = 'blur_off';
} else {
// await (this._videoTrack! as LocalVideoTrack).stopProcessor();
// await (this._track! as LocalVideoTrack).stopProcessor();
this.blurIcon = 'blur_on';
}
}