mirror of https://github.com/OpenVidu/openvidu.git
openvidu-testapp: broadcast
parent
8083e3b5cb
commit
4d2fa546cf
|
@ -1,10 +1,10 @@
|
||||||
<div id="rec-properties-div">
|
<div id="rec-properties-div">
|
||||||
<label class="label">Recording properties</label>
|
<label class="label">Recording properties</label>
|
||||||
<div>
|
<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">
|
<input matInput id="recording-name-field" placeholder="Recording name" [(ngModel)]="recordingProperties.name">
|
||||||
</mat-form-field>
|
</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-select id="rec-outputmode-select" placeholder="Output mode" [(ngModel)]="recordingProperties.outputMode">
|
||||||
<mat-option *ngFor="let enumerator of enumToArray(recMode)" [value]="enumerator">
|
<mat-option *ngFor="let enumerator of enumToArray(recMode)" [value]="enumerator">
|
||||||
<span [attr.id]="'option-' + enumerator">{{ enumerator }}</span>
|
<span [attr.id]="'option-' + enumerator">{{ enumerator }}</span>
|
||||||
|
@ -17,13 +17,14 @@
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="inner-text-input 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-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"
|
<mat-checkbox *ngIf="recordingProperties.outputMode === 'INDIVIDUAL'" id="rec-ignorefailedstreams-checkbox"
|
||||||
[(ngModel)]="recordingProperties.ignoreFailedStreams">Ignore failed streams</mat-checkbox>
|
[(ngModel)]="recordingProperties.ignoreFailedStreams">Ignore failed streams</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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-form-field class="inner-text-input" [style.fontSize.px]=14>
|
||||||
<mat-select placeholder="Recording layout" id="recording-layout-select"
|
<mat-select placeholder="Recording layout" id="recording-layout-select"
|
||||||
[(ngModel)]="recordingProperties.recordingLayout">
|
[(ngModel)]="recordingProperties.recordingLayout">
|
||||||
|
|
|
@ -8,6 +8,9 @@ import { Recording, RecordingLayout, RecordingProperties } from 'openvidu-node-c
|
||||||
})
|
})
|
||||||
export class RecordingPropertiesComponent {
|
export class RecordingPropertiesComponent {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
isBroadcast = false;
|
||||||
|
|
||||||
recMode = Recording.OutputMode;
|
recMode = Recording.OutputMode;
|
||||||
recLayouts = RecordingLayout;
|
recLayouts = RecordingLayout;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#response-text-area {
|
#response-text-area {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: #808080;
|
color: #808080;
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#response-text-area textarea {
|
#response-text-area textarea {
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
<button mat-button id="get-session-btn" (click)="fetchActiveConnections()">Fetch</button>
|
<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="list-sessions-btn" (click)="fetchActiveSessions()">Fetch all</button>
|
||||||
<button mat-button id="close-session-btn" (click)="closeSession()">Close this session</button>
|
<button mat-button id="close-session-btn" (click)="closeSession()">Close this session</button>
|
||||||
<mat-divider></mat-divider>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<label class="label">Connections/Streams</label>
|
<label class="label">Connections/Streams</label>
|
||||||
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
|
<mat-form-field class="inner-text-input" [style.fontSize.px]=14>
|
||||||
<input matInput id="connection-id-field" placeholder="connectionId" [(ngModel)]="connectionId">
|
<input matInput id="connection-id-field" placeholder="connectionId" [(ngModel)]="connectionId">
|
||||||
|
@ -33,7 +34,8 @@
|
||||||
<div>
|
<div>
|
||||||
<mat-form-field class="inner-text-input" [style.fontSize.px]=14 style="width:33%">
|
<mat-form-field class="inner-text-input" [style.fontSize.px]=14 style="width:33%">
|
||||||
<mat-label>Custom Ice Servers</mat-label>
|
<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">
|
<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>
|
<span [attr.id]="'num-ice-servers-' + i">{{ i }}</span>
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
@ -44,10 +46,12 @@
|
||||||
<input matInput id="ice-server-url-{{i}}" placeholder="url" type="text" [(ngModel)]="configuredIce.url">
|
<input matInput id="ice-server-url-{{i}}" placeholder="url" type="text" [(ngModel)]="configuredIce.url">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field style="width: 48%; padding-right: 2px">
|
<mat-form-field style="width: 48%; padding-right: 2px">
|
||||||
<input matInput id="ice-server-username-{{i}}" placeholder="username" type="text" [(ngModel)]="configuredIce.username">
|
<input matInput id="ice-server-username-{{i}}" placeholder="username" type="text"
|
||||||
|
[(ngModel)]="configuredIce.username">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field style="width: 48%; padding-left: 2px">
|
<mat-form-field style="width: 48%; padding-left: 2px">
|
||||||
<input matInput id="ice-server-credential-{{i}}" placeholder="credential" type="text" [(ngModel)]="configuredIce.credential">
|
<input matInput id="ice-server-credential-{{i}}" placeholder="credential" type="text"
|
||||||
|
[(ngModel)]="configuredIce.credential">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,9 +63,10 @@
|
||||||
[disabled]="!connectionId">Disconnect</button>
|
[disabled]="!connectionId">Disconnect</button>
|
||||||
<button mat-button id="force-unpublish-api-btn" (click)="forceUnpublish()"
|
<button mat-button id="force-unpublish-api-btn" (click)="forceUnpublish()"
|
||||||
[disabled]="!streamId">Unpublish</button>
|
[disabled]="!streamId">Unpublish</button>
|
||||||
<mat-divider></mat-divider>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<label class="label">Recordings</label>
|
<label class="label">Recordings</label>
|
||||||
<div>
|
<div>
|
||||||
<button mat-button id="list-recording-btn" (click)="listRecordings()">List recordings</button>
|
<button mat-button id="list-recording-btn" (click)="listRecordings()">List recordings</button>
|
||||||
|
@ -86,10 +91,32 @@
|
||||||
<button mat-button id="delete-recording-btn" (click)="deleteRecording()" [disabled]="!recordingId">Delete
|
<button mat-button id="delete-recording-btn" (click)="deleteRecording()" [disabled]="!recordingId">Delete
|
||||||
recording</button>
|
recording</button>
|
||||||
</div>
|
</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">
|
<mat-form-field id="response-text-area" appearance="fill">
|
||||||
<textarea id="api-response-text-area" [(ngModel)]="response" matInput readonly></textarea>
|
<textarea id="api-response-text-area" [(ngModel)]="response" matInput readonly></textarea>
|
||||||
<button mat-button id="clear-response-text-area-btn" (click)="response=''">Clear</button>
|
<button mat-button id="clear-response-text-area-btn" (click)="response=''">Clear</button>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
</mat-dialog-content>
|
</mat-dialog-content>
|
||||||
<mat-dialog-actions>
|
<mat-dialog-actions>
|
||||||
<button mat-button id="close-dialog-btn"
|
<button mat-button id="close-dialog-btn"
|
||||||
|
|
|
@ -19,13 +19,18 @@ export class SessionApiDialogComponent {
|
||||||
response: string;
|
response: string;
|
||||||
|
|
||||||
recordingProperties: RecordingProperties;
|
recordingProperties: RecordingProperties;
|
||||||
openviduRoles = OpenViduRole;
|
|
||||||
customLayout = '';
|
|
||||||
recPropertiesIcon = 'add_circle';
|
recPropertiesIcon = 'add_circle';
|
||||||
showRecProperties = false;
|
showRecProperties = false;
|
||||||
|
|
||||||
|
broadcastProperties: RecordingProperties;
|
||||||
|
broadcastPropertiesIcon = 'add_circle';
|
||||||
|
showBroadcastProperties = false;
|
||||||
|
broadcastUrl: string = 'rtmp://172.17.0.1/live';
|
||||||
|
|
||||||
numCustomIceServers = 0;
|
numCustomIceServers = 0;
|
||||||
configuredCustomIceServers = []
|
configuredCustomIceServers = []
|
||||||
|
|
||||||
|
openviduRoles = OpenViduRole;
|
||||||
connectionProperties: ConnectionProperties = {
|
connectionProperties: ConnectionProperties = {
|
||||||
record: true,
|
record: true,
|
||||||
role: OpenViduRole.PUBLISHER,
|
role: OpenViduRole.PUBLISHER,
|
||||||
|
@ -41,6 +46,10 @@ export class SessionApiDialogComponent {
|
||||||
if (!this.recordingProperties.mediaNode) {
|
if (!this.recordingProperties.mediaNode) {
|
||||||
this.recordingProperties.mediaNode = { id: '' };
|
this.recordingProperties.mediaNode = { id: '' };
|
||||||
}
|
}
|
||||||
|
this.broadcastProperties = data.broadcastProperties;
|
||||||
|
if (!this.broadcastProperties.mediaNode) {
|
||||||
|
this.broadcastProperties.mediaNode = { id: '' };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closeSession() {
|
closeSession() {
|
||||||
|
@ -241,6 +250,11 @@ export class SessionApiDialogComponent {
|
||||||
this.recPropertiesIcon = this.showRecProperties ? 'remove_circle' : 'add_circle';
|
this.recPropertiesIcon = this.showRecProperties ? 'remove_circle' : 'add_circle';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleBroadcastProperties() {
|
||||||
|
this.showBroadcastProperties = !this.showBroadcastProperties;
|
||||||
|
this.broadcastPropertiesIcon = this.showBroadcastProperties ? 'remove_circle' : 'add_circle';
|
||||||
|
}
|
||||||
|
|
||||||
changedNumIceServers(numIceServers: number) {
|
changedNumIceServers(numIceServers: number) {
|
||||||
// Save Previous Ice Servers
|
// Save Previous Ice Servers
|
||||||
let previousIceServers = [];
|
let previousIceServers = [];
|
||||||
|
@ -250,14 +264,44 @@ export class SessionApiDialogComponent {
|
||||||
|
|
||||||
// Fill empty ice servers
|
// Fill empty ice servers
|
||||||
this.configuredCustomIceServers = []
|
this.configuredCustomIceServers = []
|
||||||
for(let i = 1; i <= numIceServers; i++) {
|
for (let i = 1; i <= numIceServers; i++) {
|
||||||
this.configuredCustomIceServers.push({});
|
this.configuredCustomIceServers.push({});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add previous items
|
// 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];
|
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 + ']';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,9 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
// Recording options
|
// Recording options
|
||||||
recordingProperties: RecordingProperties;
|
recordingProperties: RecordingProperties;
|
||||||
|
|
||||||
|
// Broadcast options
|
||||||
|
broadcastProperties: RecordingProperties;
|
||||||
|
|
||||||
// OpenVidu Browser objects
|
// OpenVidu Browser objects
|
||||||
OV: OpenVidu;
|
OV: OpenVidu;
|
||||||
session: Session;
|
session: Session;
|
||||||
|
@ -292,7 +295,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
updateEventList(eventName: string, eventContent: string, event: Event) {
|
updateEventList(eventName: string, eventContent: string, event: Event) {
|
||||||
const eventInterface: OpenViduEvent = { eventName, eventContent, event };
|
const eventInterface: OpenViduEvent = { eventName, eventContent, event };
|
||||||
this.events.push(eventInterface);
|
this.events.push(eventInterface);
|
||||||
this.testFeedService.pushNewEvent({user: this.index, event});
|
this.testFeedService.pushNewEvent({ user: this.index, event });
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSubscribeTo(): void {
|
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),
|
openVidu: !!this.OV_NodeClient ? this.OV_NodeClient : new OpenViduAPI(this.openviduUrl, this.openviduSecret),
|
||||||
session: this.sessionAPI,
|
session: this.sessionAPI,
|
||||||
sessionId: !!this.session ? this.session.sessionId : this.sessionName,
|
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
|
disableClose: true
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue