openvidu-testapp: broadcast

pull/780/head
pabloFuente 2023-02-14 17:40:25 +01:00
parent 8083e3b5cb
commit 4d2fa546cf
6 changed files with 105 additions and 25 deletions

View File

@ -1,10 +1,10 @@
<div id="rec-properties-div">
<label class="label">Recording properties</label>
<div>
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
<mat-form-field *ngIf="!isBroadcast" class="inner-text-input" [style.fontSize.px]=14>
<input matInput id="recording-name-field" placeholder="Recording name" [(ngModel)]="recordingProperties.name">
</mat-form-field>
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
<mat-form-field *ngIf="!isBroadcast" class="inner-text-input" [style.fontSize.px]=14>
<mat-select id="rec-outputmode-select" placeholder="Output mode" [(ngModel)]="recordingProperties.outputMode">
<mat-option *ngFor="let enumerator of enumToArray(recMode)" [value]="enumerator">
<span [attr.id]="'option-' + enumerator">{{ enumerator }}</span>
@ -17,13 +17,14 @@
</mat-form-field>
<div class="inner-text-input mat-form-field">
<mat-checkbox id="rec-hasaudio-checkbox" [(ngModel)]="recordingProperties.hasAudio">Has audio</mat-checkbox>
<mat-checkbox id="rec-hasvideo-checkbox" [(ngModel)]="recordingProperties.hasVideo">Has video</mat-checkbox>
<mat-checkbox *ngIf="!isBroadcast" id="rec-hasvideo-checkbox" [(ngModel)]="recordingProperties.hasVideo">Has
video</mat-checkbox>
<mat-checkbox *ngIf="recordingProperties.outputMode === 'INDIVIDUAL'" id="rec-ignorefailedstreams-checkbox"
[(ngModel)]="recordingProperties.ignoreFailedStreams">Ignore failed streams</mat-checkbox>
</div>
</div>
<div
*ngIf="recordingProperties.hasVideo && (recordingProperties.outputMode === 'COMPOSED' || recordingProperties.outputMode === 'COMPOSED_QUICK_START')">
*ngIf="isBroadcast || (recordingProperties.hasVideo && (recordingProperties.outputMode === 'COMPOSED' || recordingProperties.outputMode === 'COMPOSED_QUICK_START'))">
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
<mat-select placeholder="Recording layout" id="recording-layout-select"
[(ngModel)]="recordingProperties.recordingLayout">
@ -50,4 +51,4 @@
[(ngModel)]="recordingProperties.shmSize">
</mat-form-field>
</div>
</div>
</div>

View File

@ -8,6 +8,9 @@ import { Recording, RecordingLayout, RecordingProperties } from 'openvidu-node-c
})
export class RecordingPropertiesComponent {
@Input()
isBroadcast = false;
recMode = Recording.OutputMode;
recLayouts = RecordingLayout;

View File

@ -1,6 +1,7 @@
#response-text-area {
width: 100%;
color: #808080;
margin-top: 10px;
}
#response-text-area textarea {

View File

@ -6,9 +6,10 @@
<button mat-button id="get-session-btn" (click)="fetchActiveConnections()">Fetch</button>
<button mat-button id="list-sessions-btn" (click)="fetchActiveSessions()">Fetch all</button>
<button mat-button id="close-session-btn" (click)="closeSession()">Close this session</button>
<mat-divider></mat-divider>
</div>
<mat-divider></mat-divider>
<label class="label">Connections/Streams</label>
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
<input matInput id="connection-id-field" placeholder="connectionId" [(ngModel)]="connectionId">
@ -33,22 +34,25 @@
<div>
<mat-form-field class="inner-text-input" [style.fontSize.px]=14 style="width:33%">
<mat-label>Custom Ice Servers</mat-label>
<mat-select [(ngModel)]="numCustomIceServers" id="num-ice-servers-select" (selectionChange)="changedNumIceServers(numCustomIceServers)">
<mat-select [(ngModel)]="numCustomIceServers" id="num-ice-servers-select"
(selectionChange)="changedNumIceServers(numCustomIceServers)">
<mat-option *ngFor="let i of [0,1,2,3,4,5,6,7,8,9,10]" [value]="i">
<span [attr.id]="'num-ice-servers-' + i">{{ i }}</span>
</mat-option>
</mat-select>
</mat-form-field>
<div id="manual-turn-div" *ngFor="let configuredIce of configuredCustomIceServers; let i = index">
<mat-form-field style="width: 100%">
<input matInput id="ice-server-url-{{i}}" placeholder="url" type="text" [(ngModel)]="configuredIce.url">
</mat-form-field>
<mat-form-field style="width: 48%; padding-right: 2px">
<input matInput id="ice-server-username-{{i}}" placeholder="username" type="text" [(ngModel)]="configuredIce.username">
</mat-form-field>
<mat-form-field style="width: 48%; padding-left: 2px">
<input matInput id="ice-server-credential-{{i}}" placeholder="credential" type="text" [(ngModel)]="configuredIce.credential">
</mat-form-field>
<div id="manual-turn-div" *ngFor="let configuredIce of configuredCustomIceServers; let i = index">
<mat-form-field style="width: 100%">
<input matInput id="ice-server-url-{{i}}" placeholder="url" type="text" [(ngModel)]="configuredIce.url">
</mat-form-field>
<mat-form-field style="width: 48%; padding-right: 2px">
<input matInput id="ice-server-username-{{i}}" placeholder="username" type="text"
[(ngModel)]="configuredIce.username">
</mat-form-field>
<mat-form-field style="width: 48%; padding-left: 2px">
<input matInput id="ice-server-credential-{{i}}" placeholder="credential" type="text"
[(ngModel)]="configuredIce.credential">
</mat-form-field>
</div>
</div>
<div>
@ -59,9 +63,10 @@
[disabled]="!connectionId">Disconnect</button>
<button mat-button id="force-unpublish-api-btn" (click)="forceUnpublish()"
[disabled]="!streamId">Unpublish</button>
<mat-divider></mat-divider>
</div>
<mat-divider></mat-divider>
<label class="label">Recordings</label>
<div>
<button mat-button id="list-recording-btn" (click)="listRecordings()">List recordings</button>
@ -86,13 +91,35 @@
<button mat-button id="delete-recording-btn" (click)="deleteRecording()" [disabled]="!recordingId">Delete
recording</button>
</div>
<mat-divider></mat-divider>
<label class="label">Broadcast</label>
<div>
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
<input matInput id="broadcasturl-id-field" placeholder="broadcastUrl" [(ngModel)]="broadcastUrl">
</mat-form-field>
<button mat-button id="start-broadcast-btn" (click)="startBroadcast()">Start broadcast</button>
<button mat-button id="stop-broadcast-btn" (click)="stopBroadcast()">Stop broadcast</button>
<button id="broadcast-properties-btn" mat-icon-button style="width: 24px; height: 24px; line-height: 24px;"
title="Broadcast properties" (click)="toggleBroadcastProperties()">
<mat-icon style="font-size: 18px; line-height: 18px; width: 18px; height: 18px"
aria-label="Broadcast properties">{{broadcastPropertiesIcon}}</mat-icon>
</button>
<app-recording-properties *ngIf="showBroadcastProperties" [isBroadcast]="true" [(recordingProperties)]="broadcastProperties">
</app-recording-properties>
</div>
<mat-divider></mat-divider>
<mat-form-field id="response-text-area" appearance="fill">
<textarea id="api-response-text-area" [(ngModel)]="response" matInput readonly></textarea>
<button mat-button id="clear-response-text-area-btn" (click)="response=''">Clear</button>
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button id="close-dialog-btn"
[mat-dialog-close]="{session: session, recordingProperties: recordingProperties}">CLOSE</button>
</mat-dialog-actions>
</div>
</div>

View File

@ -19,13 +19,18 @@ export class SessionApiDialogComponent {
response: string;
recordingProperties: RecordingProperties;
openviduRoles = OpenViduRole;
customLayout = '';
recPropertiesIcon = 'add_circle';
showRecProperties = false;
broadcastProperties: RecordingProperties;
broadcastPropertiesIcon = 'add_circle';
showBroadcastProperties = false;
broadcastUrl: string = 'rtmp://172.17.0.1/live';
numCustomIceServers = 0;
configuredCustomIceServers = []
openviduRoles = OpenViduRole;
connectionProperties: ConnectionProperties = {
record: true,
role: OpenViduRole.PUBLISHER,
@ -41,6 +46,10 @@ export class SessionApiDialogComponent {
if (!this.recordingProperties.mediaNode) {
this.recordingProperties.mediaNode = { id: '' };
}
this.broadcastProperties = data.broadcastProperties;
if (!this.broadcastProperties.mediaNode) {
this.broadcastProperties.mediaNode = { id: '' };
}
}
closeSession() {
@ -241,6 +250,11 @@ export class SessionApiDialogComponent {
this.recPropertiesIcon = this.showRecProperties ? 'remove_circle' : 'add_circle';
}
toggleBroadcastProperties() {
this.showBroadcastProperties = !this.showBroadcastProperties;
this.broadcastPropertiesIcon = this.showBroadcastProperties ? 'remove_circle' : 'add_circle';
}
changedNumIceServers(numIceServers: number) {
// Save Previous Ice Servers
let previousIceServers = [];
@ -250,14 +264,44 @@ export class SessionApiDialogComponent {
// Fill empty ice servers
this.configuredCustomIceServers = []
for(let i = 1; i <= numIceServers; i++) {
for (let i = 1; i <= numIceServers; i++) {
this.configuredCustomIceServers.push({});
}
// Add previous items
for(let i = 0; i < previousIceServers.length && i < this.configuredCustomIceServers.length; i++) {
for (let i = 0; i < previousIceServers.length && i < this.configuredCustomIceServers.length; i++) {
this.configuredCustomIceServers[0] = previousIceServers[0];
}
}
startBroadcast() {
console.log('Starting broadcast');
const finalBroadcastProperties = {
recordingLayout: this.broadcastProperties.recordingLayout,
customLayout: this.broadcastProperties.customLayout,
resolution: this.broadcastProperties.resolution,
frameRate: this.broadcastProperties.frameRate,
hasAudio: this.broadcastProperties.hasAudio,
shmSize: this.broadcastProperties.shmSize,
mediaNode: !this.broadcastProperties.mediaNode.id ? undefined : this.broadcastProperties.mediaNode
}
this.OV.startBroadcast(this.sessionId, this.broadcastUrl, finalBroadcastProperties)
.then(() => {
this.response = 'Broadcast started';
})
.catch(error => {
this.response = 'Error [' + error.message + ']';
});
}
stopBroadcast() {
this.OV.stopBroadcst(this.sessionId)
.then(() => {
this.response = 'Broadcast stopped';
})
.catch(error => {
this.response = 'Error [' + error.message + ']';
});
}
}

View File

@ -67,6 +67,9 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
// Recording options
recordingProperties: RecordingProperties;
// Broadcast options
broadcastProperties: RecordingProperties;
// OpenVidu Browser objects
OV: OpenVidu;
session: Session;
@ -292,7 +295,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
updateEventList(eventName: string, eventContent: string, event: Event) {
const eventInterface: OpenViduEvent = { eventName, eventContent, event };
this.events.push(eventInterface);
this.testFeedService.pushNewEvent({user: this.index, event});
this.testFeedService.pushNewEvent({ user: this.index, event });
}
toggleSubscribeTo(): void {
@ -698,7 +701,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
openVidu: !!this.OV_NodeClient ? this.OV_NodeClient : new OpenViduAPI(this.openviduUrl, this.openviduSecret),
session: this.sessionAPI,
sessionId: !!this.session ? this.session.sessionId : this.sessionName,
recordingProperties: !!this.recordingProperties ? this.recordingProperties : this.sessionProperties.defaultRecordingProperties
recordingProperties: !!this.recordingProperties ? this.recordingProperties : this.sessionProperties.defaultRecordingProperties,
broadcastProperties: !!this.broadcastProperties ? this.broadcastProperties : this.sessionProperties.defaultRecordingProperties
},
disableClose: true
});