diff --git a/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.css b/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.css
index 1c48718c..0743aa8f 100644
--- a/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.css
+++ b/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.css
@@ -33,7 +33,7 @@ mat-dialog-content button {
color: rgba(0, 0, 0, 0.54);
font-weight: 400;
margin-bottom: 5px;
- margin-top: 13px
+ margin-top: 13px;
}
.inner-text-input {
@@ -82,7 +82,7 @@ mat-checkbox ::ng-deep .mdc-checkbox__background {
min-width: 22%;
}
-.egress-output-container>mat-checkbox {
+.egress-output-container > mat-checkbox {
width: 100%;
margin-bottom: 7px;
}
@@ -120,4 +120,16 @@ mat-chip-row {
.room-composite-options mat-checkbox {
margin-left: 7px;
-}
\ No newline at end of file
+}
+
+.ingress-options {
+ margin-bottom: 7px;
+}
+
+#ingress-simulcast {
+ margin-right: 6px;
+}
+
+#ingress-video-codec-select {
+ margin-right: 6px;
+}
diff --git a/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.html
index f2280846..bb92d642 100644
--- a/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.html
+++ b/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.html
@@ -163,9 +163,10 @@
-
-
+
+
+
+
+ With audio
+ With video
+
+ Simulcast
+
+
+
+ Codec
+
+
+ {{codec.viewValue}}
+
+
+
+
+
+
+ Preset
+
+
+ {{preset.viewValue}}
+
+
+
+
+
+
diff --git a/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.ts
index cb14d42f..c84ecd25 100644
--- a/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.ts
+++ b/openvidu-testapp/src/app/components/dialogs/room-api-dialog/room-api-dialog.component.ts
@@ -3,307 +3,384 @@ import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { Component, Inject, inject } from '@angular/core';
import { MatChipInputEvent } from '@angular/material/chips';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { VideoCodec } from '@livekit/protocol';
import { LocalParticipant } from 'livekit-client';
-import { DirectFileOutput, EgressClient, EncodedFileOutput, EncodedFileType, EncodedOutputs, IngressInfo, IngressInput, Room, RoomCompositeOptions, RoomServiceClient, SegmentedFileOutput, SegmentedFileProtocol, StreamOutput, StreamProtocol } from 'livekit-server-sdk';
+import {
+ DirectFileOutput,
+ EgressClient,
+ EncodedFileOutput,
+ EncodedFileType,
+ EncodedOutputs,
+ IngressInfo,
+ IngressInput,
+ IngressVideoEncodingPreset,
+ Room,
+ RoomCompositeOptions,
+ RoomServiceClient,
+ SegmentedFileOutput,
+ SegmentedFileProtocol,
+ StreamOutput,
+ StreamProtocol,
+} from 'livekit-server-sdk';
import { RoomApiService } from 'src/app/services/room-api.service';
@Component({
- selector: 'app-room-api-dialog',
- templateUrl: './room-api-dialog.component.html',
- styleUrls: ['./room-api-dialog.component.css']
+ selector: 'app-room-api-dialog',
+ templateUrl: './room-api-dialog.component.html',
+ styleUrls: ['./room-api-dialog.component.css'],
})
export class RoomApiDialogComponent {
+ room: Room;
+ localParticipant: LocalParticipant;
+ roomServiceClient: RoomServiceClient;
+ egressClient: EgressClient;
- room: Room;
- localParticipant: LocalParticipant;
- roomServiceClient: RoomServiceClient;
- egressClient: EgressClient;
+ apiRoomName: string;
+ apiParticipantIdentity: string;
+ apiTrackSid: string;
+ muteTrack: boolean = true;
- apiRoomName: string;
- apiParticipantIdentity: string;
- apiTrackSid: string;
- muteTrack: boolean = true;
+ egressRoomName: string;
+ egressId: string;
+ audioTrackId: string;
+ videoTrackId: string;
- egressRoomName: string;
- egressId: string;
- audioTrackId: string;
- videoTrackId: string;
+ ROOM_COMPOSITE_LAYOUTS = ['grid', 'speaker', 'single-speaker'];
+ roomCompositeLayoutSelected: string = 'grid';
+ roomCompositeAudioOnly: boolean = false;
+ roomCompositeVideoOnly: boolean = false;
- ROOM_COMPOSITE_LAYOUTS = ['grid', 'speaker', 'single-speaker'];
- roomCompositeLayoutSelected: string = 'grid';
- roomCompositeAudioOnly: boolean = false;
- roomCompositeVideoOnly: boolean = false;
+ fileOutputSelected: boolean = true;
+ streamOutputSelected: boolean = false;
+ s3Endpoint: string = 'http://localhost:9100'; // 'http://minio:9000'
+ rtmpUrls: string[] = ['rtmp://172.17.0.1:1936/live/'];
+ segmentOutputSelected: boolean = false;
+ segmentDuration: number = 6;
- fileOutputSelected: boolean = true;
- streamOutputSelected: boolean = false;
- s3Endpoint: string = 'http://localhost:9100'; // 'http://minio:9000'
- rtmpUrls: string[] = ['rtmp://172.17.0.1:1936/live/']
- segmentOutputSelected: boolean = false;
- segmentDuration: number = 6;
+ ingressRoomName: string;
+ ingressId: string;
+ inputTypeSelected: IngressInput = IngressInput.URL_INPUT;
+ ingressWithVideo: boolean = true;
+ ingressWithAudio: boolean = false;
+ ingressVideoCodecSelected: VideoCodec = VideoCodec.H264_BASELINE;
+ ingressSimulcast: boolean = true;
+ ingressVideoEncodingPresetSelected?: IngressVideoEncodingPreset = undefined;
- ingressRoomName: string;
- ingressId: string;
- inputTypeSelected: IngressInput = IngressInput.URL_INPUT;
- INGRESS_INPUT_TYPES: { value: IngressInput, viewValue: string }[] = [
- { value: IngressInput.URL_INPUT, viewValue: 'URL' },
- { value: IngressInput.RTMP_INPUT, viewValue: 'RTMP' },
- { value: IngressInput.WHIP_INPUT, viewValue: 'WHIP' },
- ];
+ response: string;
- response: string;
+ INGRESS_INPUT_TYPES: { value: IngressInput; viewValue: string }[] = [
+ { value: IngressInput.URL_INPUT, viewValue: 'URL' },
+ { value: IngressInput.RTMP_INPUT, viewValue: 'RTMP' },
+ { value: IngressInput.WHIP_INPUT, viewValue: 'WHIP' },
+ ];
+ INGRESS_VIDEO_CODECS: { value: VideoCodec; viewValue: string }[] = [
+ { value: VideoCodec.H264_BASELINE, viewValue: 'H264' },
+ { value: VideoCodec.VP8, viewValue: 'VP8' },
+ ];
+ INGRESS_VIDEO_ENCODING_PRESETS: {
+ value: IngressInput | undefined;
+ viewValue: string;
+ }[] = [{ value: undefined, viewValue: 'undefined' }].concat(
+ Object.keys(IngressVideoEncodingPreset)
+ .filter((key) => isNaN(Number(key)))
+ .map((key) => {
+ return {
+ value: IngressVideoEncodingPreset[key as any],
+ viewValue: key.toString(),
+ } as any;
+ })
+ );
- // s3Config = {
- // endpoint: this.s3Endpoint,
- // metadata: { "mytag": "myvalue" },
- // tagging: "mytagging"
- // };
+ // s3Config = {
+ // endpoint: this.s3Endpoint,
+ // metadata: { "mytag": "myvalue" },
+ // tagging: "mytagging"
+ // };
- announcer = inject(LiveAnnouncer);
- addOnBlur = true;
- readonly separatorKeysCodes = [ENTER, COMMA] as const;
+ announcer = inject(LiveAnnouncer);
+ addOnBlur = true;
+ readonly separatorKeysCodes = [ENTER, COMMA] as const;
- constructor(
- private roomApiService: RoomApiService,
- public dialogRef: MatDialogRef,
- @Inject(MAT_DIALOG_DATA) public data: any
- ) {
- this.room = data.room;
- this.localParticipant = data.localParticipant;
- this.apiRoomName = this.room?.name;
- this.apiParticipantIdentity = this.localParticipant?.identity;
- this.apiTrackSid = this.localParticipant?.videoTrackPublications.values().next().value?.trackSid!;
- this.egressRoomName = this.room?.name;
- this.audioTrackId = this.localParticipant?.audioTrackPublications.values().next().value?.trackSid!;
- this.videoTrackId = this.localParticipant?.videoTrackPublications.values().next().value?.trackSid!;
- this.ingressRoomName = this.room?.name;
+ constructor(
+ private roomApiService: RoomApiService,
+ public dialogRef: MatDialogRef,
+ @Inject(MAT_DIALOG_DATA) public data: any
+ ) {
+ this.room = data.room;
+ this.localParticipant = data.localParticipant;
+ this.apiRoomName = this.room?.name;
+ this.apiParticipantIdentity = this.localParticipant?.identity;
+ this.apiTrackSid = this.localParticipant?.videoTrackPublications
+ .values()
+ .next().value?.trackSid!;
+ this.egressRoomName = this.room?.name;
+ this.audioTrackId = this.localParticipant?.audioTrackPublications
+ .values()
+ .next().value?.trackSid!;
+ this.videoTrackId = this.localParticipant?.videoTrackPublications
+ .values()
+ .next().value?.trackSid!;
+ this.ingressRoomName = this.room?.name;
+ }
+
+ async listRooms() {
+ console.log('Listing rooms');
+ try {
+ const rooms = await this.roomApiService.listRooms();
+ this.response = JSON.stringify(rooms, null, 4);
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async listRooms() {
- console.log('Listing rooms');
- try {
- const rooms = await this.roomApiService.listRooms();
- this.response = JSON.stringify(rooms, null, 4);
- } catch (error: any) {
- this.response = error;
- }
+ async deleteRoom() {
+ console.log('Deleting room');
+ try {
+ await this.roomApiService.deleteRoom(this.apiRoomName);
+ this.response = 'Room deleted';
+ } catch (error: any) {
+ this.response = error;
+ console.log(JSON.stringify(error));
}
+ }
- async deleteRoom() {
- console.log('Deleting room');
- try {
- await this.roomApiService.deleteRoom(this.apiRoomName);
- this.response = 'Room deleted';
- } catch (error: any) {
- this.response = error;
- console.log(JSON.stringify(error));
- }
+ async deleteAllRooms() {
+ console.log('Deleting all rooms');
+ try {
+ const promises: Promise[] = [];
+ const rooms = await this.roomApiService.listRooms();
+ rooms.forEach((r) => {
+ promises.push(this.roomApiService.deleteRoom(r.name));
+ });
+ await Promise.all(promises);
+ this.response = 'Deleted ' + promises.length + ' rooms';
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async deleteAllRooms() {
- console.log('Deleting all rooms');
- try {
- const promises: Promise[] = [];
- const rooms = await this.roomApiService.listRooms();
- rooms.forEach(r => {
- promises.push(this.roomApiService.deleteRoom(r.name));
- });
- await Promise.all(promises);
- this.response = 'Deleted ' + promises.length + ' rooms';
- } catch (error: any) {
- this.response = error;
- }
+ async listParticipants() {
+ console.log('Listing participants');
+ try {
+ const participants = await this.roomApiService.listParticipants(
+ this.apiRoomName
+ );
+ this.response = JSON.stringify(participants, null, 4);
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async listParticipants() {
- console.log('Listing participants');
- try {
- const participants = await this.roomApiService.listParticipants(this.apiRoomName);
- this.response = JSON.stringify(participants, null, 4);
- } catch (error: any) {
- this.response = error;
- }
+ async getParticipant() {
+ console.log('Getting participant');
+ try {
+ const participant = await this.roomApiService.getParticipant(
+ this.apiRoomName,
+ this.apiParticipantIdentity
+ );
+ this.response = JSON.stringify(participant, null, 4);
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async getParticipant() {
- console.log('Getting participant');
- try {
- const participant = await this.roomApiService.getParticipant(this.apiRoomName, this.apiParticipantIdentity);
- this.response = JSON.stringify(participant, null, 4);
- } catch (error: any) {
- this.response = error;
- }
+ async removeParticipant() {
+ console.log('Removing participant');
+ try {
+ await this.roomApiService.removeParticipant(
+ this.apiRoomName,
+ this.apiParticipantIdentity
+ );
+ this.response = 'Participant removed';
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async removeParticipant() {
- console.log('Removing participant');
- try {
- await this.roomApiService.removeParticipant(this.apiRoomName, this.apiParticipantIdentity);
- this.response = 'Participant removed';
- } catch (error: any) {
- this.response = error;
- }
+ async mutePublishedTrack() {
+ console.log(`${this.muteTrack ? 'Muting' : 'Unmuting'} track`);
+ try {
+ await this.roomApiService.mutePublishedTrack(
+ this.apiRoomName,
+ this.apiParticipantIdentity,
+ this.apiTrackSid,
+ this.muteTrack
+ );
+ this.response = `Track ${this.muteTrack ? 'muted' : 'unmuted'}`;
+ this.muteTrack = !this.muteTrack;
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async mutePublishedTrack() {
- console.log(`${this.muteTrack ? 'Muting' : 'Unmuting'} track`);
- try {
- await this.roomApiService.mutePublishedTrack(this.apiRoomName, this.apiParticipantIdentity, this.apiTrackSid, this.muteTrack);
- this.response = `Track ${this.muteTrack ? 'muted' : 'unmuted'}`;
- this.muteTrack = !this.muteTrack;
- } catch (error: any) {
- this.response = error;
- }
+ async listEgress() {
+ console.log('Listing egress');
+ try {
+ const egress = await this.roomApiService.listEgress();
+ this.response = JSON.stringify(egress, null, 4);
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async listEgress() {
- console.log('Listing egress');
- try {
- const egress = await this.roomApiService.listEgress();
- this.response = JSON.stringify(egress, null, 4);
- } catch (error: any) {
- this.response = error;
- }
+ async startRoomCompositeEgress() {
+ console.log('Starting room composite egress');
+ try {
+ const encodedOutputs = this.getEncodedOutputs();
+ const roomCompositeOptions: RoomCompositeOptions = {
+ layout: this.roomCompositeLayoutSelected,
+ audioOnly: this.roomCompositeAudioOnly,
+ videoOnly: this.roomCompositeVideoOnly,
+ };
+ const egress = await this.roomApiService.startRoomCompositeEgress(
+ this.egressRoomName,
+ roomCompositeOptions,
+ encodedOutputs
+ );
+ this.response = JSON.stringify(egress, null, 4);
+ this.egressId = egress.egressId;
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async startRoomCompositeEgress() {
- console.log('Starting room composite egress');
- try {
- const encodedOutputs = this.getEncodedOutputs();
- const roomCompositeOptions: RoomCompositeOptions = {
- layout: this.roomCompositeLayoutSelected,
- audioOnly: this.roomCompositeAudioOnly,
- videoOnly: this.roomCompositeVideoOnly
- }
- const egress = await this.roomApiService.startRoomCompositeEgress(this.egressRoomName, roomCompositeOptions, encodedOutputs);
- this.response = JSON.stringify(egress, null, 4);
- this.egressId = egress.egressId;
- } catch (error: any) {
- this.response = error;
- }
+ async startTrackCompositeEgress() {
+ console.log('Starting track composite egress');
+ try {
+ const encodedOutputs = this.getEncodedOutputs();
+ const egress = await this.roomApiService.startTrackCompositeEgress(
+ this.egressRoomName,
+ this.audioTrackId,
+ this.videoTrackId,
+ encodedOutputs
+ );
+ this.response = JSON.stringify(egress, null, 4);
+ this.egressId = egress.egressId;
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async startTrackCompositeEgress() {
- console.log('Starting track composite egress');
- try {
- const encodedOutputs = this.getEncodedOutputs();
- const egress = await this.roomApiService.startTrackCompositeEgress(this.egressRoomName, this.audioTrackId, this.videoTrackId, encodedOutputs);
- this.response = JSON.stringify(egress, null, 4);
- this.egressId = egress.egressId;
- } catch (error: any) {
- this.response = error;
- }
+ async startTrackEgress() {
+ console.log('Starting track egress');
+ try {
+ const egress = await this.roomApiService.startTrackEgress(
+ this.egressRoomName,
+ !!this.audioTrackId ? this.audioTrackId : this.videoTrackId
+ );
+ this.response = JSON.stringify(egress, null, 4);
+ this.egressId = egress.egressId;
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async startTrackEgress() {
- console.log('Starting track egress');
- try {
- const egress = await this.roomApiService.startTrackEgress(this.egressRoomName, !!this.audioTrackId ? this.audioTrackId : this.videoTrackId);
- this.response = JSON.stringify(egress, null, 4);
- this.egressId = egress.egressId;
- } catch (error: any) {
- this.response = error;
- }
+ async stopEgress() {
+ console.log('Stopping egress');
+ try {
+ await this.roomApiService.stopEgress(this.egressId);
+ this.response = 'Egress stopped';
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async stopEgress() {
- console.log('Stopping egress');
- try {
- await this.roomApiService.stopEgress(this.egressId);
- this.response = 'Egress stopped';
- } catch (error: any) {
- this.response = error;
- }
+ async listIngress() {
+ console.log('Listing ingress');
+ try {
+ const ingress = await this.roomApiService.listIngress();
+ this.response = JSON.stringify(ingress, null, 4);
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async listIngress() {
- console.log('Listing ingress');
- try {
- const ingress = await this.roomApiService.listIngress();
- this.response = JSON.stringify(ingress, null, 4);
- } catch (error: any) {
- this.response = error;
- }
+ async createIngress() {
+ console.log('Creating ingress');
+ try {
+ const ingress = await this.roomApiService.createIngress(
+ this.ingressRoomName,
+ this.inputTypeSelected,
+ this.ingressWithAudio,
+ this.ingressWithVideo,
+ this.ingressVideoCodecSelected,
+ this.ingressSimulcast,
+ this.ingressVideoEncodingPresetSelected
+ );
+ this.response = JSON.stringify(ingress, null, 4);
+ this.ingressId = ingress.ingressId;
+ } catch (error: any) {
+ this.response = error;
+ console.warn(error);
+ console.warn(error.code);
+ console.warn(error.msg);
}
+ }
- async createIngress() {
- console.log('Creating ingress');
- try {
- const ingress = await this.roomApiService.createIngress(this.ingressRoomName, this.inputTypeSelected);
- this.response = JSON.stringify(ingress, null, 4);
- this.ingressId = ingress.ingressId;
- } catch (error: any) {
- this.response = error;
- console.warn(error);
- console.warn(error.code);
- console.warn(error.msg);
- }
+ async deleteIngress() {
+ console.log('Deleting ingress');
+ try {
+ await this.roomApiService.deleteIngress(this.ingressId);
+ this.response = 'Ingress deleted';
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async deleteIngress() {
- console.log('Deleting ingress');
- try {
- await this.roomApiService.deleteIngress(this.ingressId);
- this.response = 'Ingress deleted';
- } catch (error: any) {
- this.response = error;
- }
+ async deleteAllIngress() {
+ console.log('Deleting all ingress');
+ try {
+ const promises: Promise[] = [];
+ const ingresses = await this.roomApiService.listIngress();
+ ingresses.forEach((i) => {
+ promises.push(this.roomApiService.deleteIngress(i.ingressId));
+ });
+ await Promise.all(promises);
+ this.response = 'Deleted ' + promises.length + ' ingresses';
+ } catch (error: any) {
+ this.response = error;
}
+ }
- async deleteAllIngress() {
- console.log('Deleting all ingress');
- try {
- const promises: Promise[] = [];
- const ingresses = await this.roomApiService.listIngress();
- ingresses.forEach(i => {
- promises.push(this.roomApiService.deleteIngress(i.ingressId));
- });
- await Promise.all(promises);
- this.response = 'Deleted ' + promises.length + ' ingresses';
- } catch (error: any) {
- this.response = error;
- }
+ addRtmpUrl(event: MatChipInputEvent): void {
+ const value = (event.value || '').trim();
+ if (value) {
+ this.rtmpUrls.push(value);
}
+ event.chipInput!.clear();
+ }
- addRtmpUrl(event: MatChipInputEvent): void {
- const value = (event.value || '').trim();
- if (value) {
- this.rtmpUrls.push(value);
- }
- event.chipInput!.clear();
+ removeRtmpUrl(url: string): void {
+ const index = this.rtmpUrls.indexOf(url);
+ if (index >= 0) {
+ this.rtmpUrls.splice(index, 1);
+ this.announcer.announce(`Removed ${url}`);
}
+ }
- removeRtmpUrl(url: string): void {
- const index = this.rtmpUrls.indexOf(url);
- if (index >= 0) {
- this.rtmpUrls.splice(index, 1);
- this.announcer.announce(`Removed ${url}`);
- }
+ private getEncodedOutputs(): EncodedOutputs {
+ // this.s3Config.endpoint = this.s3Endpoint;
+ const encodedOutputs: EncodedOutputs = {};
+ if (this.fileOutputSelected) {
+ encodedOutputs.file = new EncodedFileOutput({
+ fileType: EncodedFileType.DEFAULT_FILETYPE,
+ filepath: 'room-composite-{room_id}-{room_name}-{time}',
+ });
}
-
- private getEncodedOutputs(): EncodedOutputs {
- // this.s3Config.endpoint = this.s3Endpoint;
- const encodedOutputs: EncodedOutputs = {};
- if (this.fileOutputSelected) {
- encodedOutputs.file = new EncodedFileOutput({
- fileType: EncodedFileType.DEFAULT_FILETYPE,
- filepath: 'room-composite-{room_id}-{room_name}-{time}',
- });
- }
- if (this.streamOutputSelected) {
- encodedOutputs.stream = new StreamOutput({
- urls: this.rtmpUrls,
- protocol: StreamProtocol.RTMP
- });
- }
- if (this.segmentOutputSelected) {
- encodedOutputs.segments = new SegmentedFileOutput({
- protocol: SegmentedFileProtocol.HLS_PROTOCOL,
- segmentDuration: this.segmentDuration,
- // s3: this.s3Config
- });
- }
- return encodedOutputs;
+ if (this.streamOutputSelected) {
+ encodedOutputs.stream = new StreamOutput({
+ urls: this.rtmpUrls,
+ protocol: StreamProtocol.RTMP,
+ });
}
-
+ if (this.segmentOutputSelected) {
+ encodedOutputs.segments = new SegmentedFileOutput({
+ protocol: SegmentedFileProtocol.HLS_PROTOCOL,
+ segmentDuration: this.segmentDuration,
+ // s3: this.s3Config
+ });
+ }
+ return encodedOutputs;
+ }
}
diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts
index 13814263..79dafe54 100644
--- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts
+++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts
@@ -80,11 +80,11 @@ export class OpenviduInstanceComponent {
autoSubscribe: false,
};
createLocalTracksOptions: CreateLocalTracksOptions = {
- audio: true,
+ audio: false,
video: {
resolution: {
- width: 640,
- height: 480,
+ width: 1920,
+ height: 1080,
frameRate: 30,
},
},
diff --git a/openvidu-testapp/src/app/services/room-api.service.ts b/openvidu-testapp/src/app/services/room-api.service.ts
index 538ce548..24a685f3 100644
--- a/openvidu-testapp/src/app/services/room-api.service.ts
+++ b/openvidu-testapp/src/app/services/room-api.service.ts
@@ -21,10 +21,15 @@ import {
RoomServiceClient,
TrackCompositeOptions,
TrackInfo,
- TrackSource,
VideoGrant,
} from 'livekit-server-sdk';
import { LivekitParamsService } from './livekit-params.service';
+import { VideoQuality } from 'livekit-client';
+import {
+ IngressVideoEncodingOptions,
+ VideoCodec,
+ VideoLayer,
+} from '@livekit/protocol';
@Injectable({
providedIn: 'root',
@@ -134,7 +139,8 @@ export class RoomApiService {
encodingOptions?: EncodingOptionsPreset | EncodingOptions
): Promise {
if (encodedOutputs.file) {
- encodedOutputs.file.filepath = 'RoomComposite-{room_id}-{room_name}-{time}';
+ encodedOutputs.file.filepath =
+ 'RoomComposite-{room_id}-{room_name}-{time}';
}
if (encodingOptions) {
roomCompositeOptions.encodingOptions = encodingOptions;
@@ -201,49 +207,78 @@ export class RoomApiService {
async createIngress(
room_name: string,
- input_type: IngressInput
+ input_type: IngressInput,
+ withAudio: boolean,
+ withVideo: boolean,
+ codec: VideoCodec,
+ simulcast: boolean,
+ preset?: IngressVideoEncodingPreset
): Promise {
- const ingressClient: IngressClient = new IngressClient(
- this.getRestUrl(),
- this.livekitParamsService.getParams().livekitApiKey,
- this.livekitParamsService.getParams().livekitApiSecret
- );
+ let url;
+ if (!withVideo) {
+ url =
+ 'https://s3.eu-west-1.amazonaws.com/public.openvidu.io/bbb_sunflower_1080p_60fps_normal_onlyaudio.mp3';
+ } else {
+ url = withAudio
+ ? 'https://s3.eu-west-1.amazonaws.com/public.openvidu.io/bbb_sunflower_1080p_60fps_normal.mp4'
+ : 'https://s3.eu-west-1.amazonaws.com/public.openvidu.io/bbb_sunflower_1080p_60fps_normal_noaudio.mp4';
+ }
let options: CreateIngressOptions = {
name: input_type + '-' + room_name,
roomName: room_name,
participantIdentity: 'IngressParticipantIdentity',
participantName: 'MyIngress',
participantMetadata: 'IngressParticipantMetadata',
- url: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4',
- // video: {
- // encodingOptions: {
- // video_codec: VideoCodec.VP8,
- // frame_rate: 30,
- // layers: [
- // {
- // quality: VideoQuality.HIGH,
- // width: 1920,
- // height: 1080,
- // bitrate: 4500000,
- // },
- // ],
- // },
- // } as any,
+ url,
video: {
- name: 'pelicula',
- source: TrackSource.SCREEN_SHARE,
encodingOptions: {
- case: 'preset',
- value:
- IngressVideoEncodingPreset.H264_540P_25FPS_2_LAYERS_HIGH_MOTION,
+ case: preset != undefined ? 'preset' : 'options',
+ value: {},
},
} as any,
- // audio: {
- // source: TrackSource.MICROPHONE,
- // preset: IngressAudioEncodingPreset.OPUS_MONO_64KBS,
- // } as any,
};
- const ingressInfo = await ingressClient.createIngress(input_type, options);
+ if (preset != undefined) {
+ options.video!.encodingOptions.value = preset;
+ } else {
+ const encodingOptions = options.video!.encodingOptions
+ .value! as IngressVideoEncodingOptions;
+ encodingOptions.videoCodec = codec;
+ encodingOptions.frameRate = 30;
+ let layers: VideoLayer[] = [];
+ if (simulcast) {
+ layers = [
+ {
+ quality: VideoQuality.HIGH,
+ width: 1920,
+ height: 1080,
+ },
+ {
+ quality: VideoQuality.MEDIUM,
+ width: 1280,
+ height: 720,
+ },
+ {
+ quality: VideoQuality.LOW,
+ width: 640,
+ height: 360,
+ },
+ ] as VideoLayer[];
+ } else {
+ layers = [
+ {
+ quality: VideoQuality.HIGH,
+ width: 1920,
+ height: 1080,
+ } as VideoLayer,
+ ];
+ }
+ encodingOptions.layers = layers;
+ }
+
+ const ingressInfo = await this.ingressClient.createIngress(
+ input_type,
+ options
+ );
return ingressInfo;
}