openvidu-testapp: API REST page with SessionProperties. New API for openvidu-browser 2.0.0

pull/73/head
pabloFuente 2018-04-17 15:08:02 +02:00
parent 390ce2224e
commit d5eda724c5
5 changed files with 324 additions and 78 deletions

View File

@ -16,7 +16,7 @@
"core-js": "^2.4.1", "core-js": "^2.4.1",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"openvidu-browser": "1.9.0-beta-1", "openvidu-browser": "1.9.0-beta-1",
"openvidu-node-client": "1.7.0", "openvidu-node-client": "1.8.0",
"rxjs": "^5.4.2", "rxjs": "^5.4.2",
"zone.js": "^0.8.14" "zone.js": "^0.8.14"
}, },

View File

@ -209,37 +209,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
this.sendAudioChange = this.sendAudio; this.sendAudioChange = this.sendAudio;
this.sendVideoChange = this.sendVideo; this.sendVideoChange = this.sendVideo;
this.publisher = this.OV.initPublisher( // this.asyncInitPublisher();
'local-vid-' + this.session.connection.connectionId, this.syncInitPublisher();
{
audio: this.sendAudio,
video: this.sendVideo,
audioActive: this.activeAudio,
videoActive: this.activeVideo,
quality: 'MEDIUM',
screen: this.optionsVideo === 'screen' ? true : false
},
(err) => {
if (err) {
console.warn(err);
this.openviduError = err;
if (err.name === 'SCREEN_EXTENSION_NOT_INSTALLED') {
this.extensionDialog.open(ExtensionDialogComponent, {
data: { url: err.message },
disableClose: true,
width: '250px'
});
}
}
});
this.addPublisherEvents(this.publisher);
if (this.subscribeToRemote) {
this.publisher.subscribeToRemote();
}
this.session.publish(this.publisher);
} }
} else { } else {
@ -439,6 +410,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
console.log('Message succesfully sent'); console.log('Message succesfully sent');
} }
}); });
// this.initGrayVideo();
} }
recordPublisher(): void { recordPublisher(): void {
@ -533,7 +505,13 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
publishUnpublish(): void { publishUnpublish(): void {
if (this.unpublished) { if (this.unpublished) {
this.session.publish(this.publisher); this.session.publish(this.publisher)
.then(() => {
console.log(this.publisher);
})
.catch(e => {
console.error(e);
});
} else { } else {
this.session.unpublish(this.publisher); this.session.unpublish(this.publisher);
this.removeUserData(this.session.connection.connectionId); this.removeUserData(this.session.connection.connectionId);
@ -585,12 +563,13 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
this.publisher = this.OV.initPublisher( this.publisher = this.OV.initPublisher(
'local-vid-' + this.session.connection.connectionId, 'local-vid-' + this.session.connection.connectionId,
{ {
audio: this.sendAudioChange, audioSource: this.sendAudioChange ? undefined : false,
video: this.sendVideoChange, videoSource: this.sendVideoChange ? (screenChange ? 'screen' : undefined) : false,
audioActive: (!this.publisherChanged) ? true : !this.audioMuted, publishAudio: (!this.publisherChanged) ? true : !this.audioMuted,
videoActive: (!this.publisherChanged) ? true : !this.videoMuted, publishVideo: (!this.publisherChanged) ? true : !this.videoMuted,
quality: 'MEDIUM', resolution: '640x480',
screen: screenChange frameRate: 30,
insertMode: 'APPEND'
}, },
(err) => { (err) => {
if (err) { if (err) {
@ -621,10 +600,14 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
document.getElementById('record-btn-' + this.session.connection.connectionId + '-' + connectionId).remove(); document.getElementById('record-btn-' + this.session.connection.connectionId + '-' + connectionId).remove();
document.getElementById('pause-btn-' + this.session.connection.connectionId + '-' + connectionId).remove(); document.getElementById('pause-btn-' + this.session.connection.connectionId + '-' + connectionId).remove();
} else { } else {
subscriber = this.session.subscribe(subscriber.stream, 'remote-vid-' + this.session.connection.connectionId);
this.session.subscribeAsync(subscriber.stream, 'remote-vid-' + this.session.connection.connectionId)
.then(sub => {
subscriber = sub;
this.subscribers[connectionId].subscriber = subscriber; this.subscribers[connectionId].subscriber = subscriber;
subscriber.on('videoElementCreated', (e) => { subscriber.on('videoElementCreated', (e) => {
if (!subscriber.stream.getRecvVideo()) { if (!subscriber.stream.hasVideo) {
$(e.element).css({ 'background-color': '#4d4d4d' }); $(e.element).css({ 'background-color': '#4d4d4d' });
$(e.element).attr('poster', 'assets/images/volume.png'); $(e.element).attr('poster', 'assets/images/volume.png');
} }
@ -636,6 +619,29 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
this.appendSubscriberData(e.element, subscriber.stream.connection); this.appendSubscriberData(e.element, subscriber.stream.connection);
this.updateEventList('videoPlaying', e.element.id); this.updateEventList('videoPlaying', e.element.id);
}); });
})
.catch(err => {
console.error(err);
});
/*subscriber = this.session.subscribe(subscriber.stream, 'remote-vid-' + this.session.connection.connectionId);
this.subscribers[connectionId].subscriber = subscriber;
subscriber.on('videoElementCreated', (e) => {
if (!subscriber.stream.hasVideo) {
$(e.element).css({ 'background-color': '#4d4d4d' });
$(e.element).attr('poster', 'assets/images/volume.png');
}
this.subscribers[connectionId].videoElement = e.element;
this.updateEventList('videoElementCreated', e.element.id);
});
subscriber.on('videoPlaying', (e) => {
this.removeUserData(connectionId);
this.appendSubscriberData(e.element, subscriber.stream.connection);
this.updateEventList('videoPlaying', e.element.id);
});*/
} }
this.subscribers[connectionId].subbed = !this.subscribers[connectionId].subbed; this.subscribers[connectionId].subbed = !this.subscribers[connectionId].subbed;
} }
@ -646,30 +652,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
this.changeDetector.detectChanges(); this.changeDetector.detectChanges();
if (this.subscribeTo) { if (this.subscribeTo) {
const subscriber: Subscriber = session.subscribe(event.stream, 'remote-vid-' + session.connection.connectionId); // this.syncSubscribe(session, event);
this.subscribers[subscriber.stream.connection.connectionId] = { this.asyncSubscribe(session, event);
'subscriber': subscriber,
'subbed': true,
'recorder': undefined,
'recording': false,
'paused': false,
'videoElement': undefined
};
subscriber.on('videoElementCreated', (e) => {
if (!event.stream.getRecvVideo()) {
$(e.element).css({ 'background-color': '#4d4d4d' });
$(e.element).attr('poster', 'assets/images/volume.png');
}
this.subscribers[subscriber.stream.connection.connectionId].videoElement = e.element;
this.updateEventList('videoElementCreated', e.element.id);
});
subscriber.on('videoPlaying', (e) => {
this.appendSubscriberData(e.element, subscriber.stream.connection);
this.updateEventList('videoPlaying', e.element.id);
});
subscriber.on('videoElementDestroyed', (e) => {
this.updateEventList('videoElementDestroyed', '(Subscriber)');
});
} }
this.updateEventList('streamCreated', event.stream.connection.connectionId); this.updateEventList('streamCreated', event.stream.connection.connectionId);
}); });
@ -686,11 +670,23 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
}); });
session.on('sessionDisconnected', (event) => { session.on('sessionDisconnected', (event) => {
this.updateEventList('sessionDisconnected', 'No data'); this.updateEventList('sessionDisconnected', 'No data');
if (event.reason === 'networkDisconnect') {
this.session = null;
this.OV = null;
}
}); });
session.on('signal', (event) => { session.on('signal', (event) => {
this.updateEventList('signal', event.from.connectionId + '-' + event.data); this.updateEventList('signal', event.from.connectionId + '-' + event.data);
}); });
session.on('recordingStarted', (event) => {
this.updateEventList('recordingStarted', event.id);
});
session.on('recordingStopped', (event) => {
this.updateEventList('recordingStopped', event.id);
});
/*session.on('publisherStartSpeaking', (event) => { /*session.on('publisherStartSpeaking', (event) => {
console.log('Publisher start speaking'); console.log('Publisher start speaking');
console.log(event); console.log(event);
@ -724,6 +720,14 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
this.updateEventList('accessDenied', ''); this.updateEventList('accessDenied', '');
}); });
publisher.on('accessDialogOpened', (e) => {
this.updateEventList('accessDialogOpened', '');
});
publisher.on('accessDialogClosed', (e) => {
this.updateEventList('accessDialogClosed', '');
});
publisher.on('videoPlaying', (e) => { publisher.on('videoPlaying', (e) => {
this.appendPublisherData(e.element); this.appendPublisherData(e.element);
this.updateEventList('videoPlaying', e.element.id); this.updateEventList('videoPlaying', e.element.id);
@ -806,4 +810,192 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
} }
} }
syncInitPublisher() {
this.publisher = this.OV.initPublisher(
'local-vid-' + this.session.connection.connectionId,
{
audioSource: this.sendAudio ? undefined : false,
videoSource: this.sendVideo ? (this.optionsVideo === 'screen' ? 'screen' : undefined) : false,
publishAudio: this.activeAudio,
publishVideo: this.activeVideo,
resolution: '640x480',
frameRate: 30,
insertMode: 'APPEND'
},
(err) => {
if (err) {
console.warn(err);
this.openviduError = err;
if (err.name === 'SCREEN_EXTENSION_NOT_INSTALLED') {
this.extensionDialog.open(ExtensionDialogComponent, {
data: { url: err.message },
disableClose: true,
width: '250px'
});
}
}
});
this.addPublisherEvents(this.publisher);
if (this.subscribeToRemote) {
this.publisher.subscribeToRemote();
}
this.session.publish(this.publisher);
}
asyncInitPublisher() {
this.OV.initPublisherAsync(
'local-vid-' + this.session.connection.connectionId,
{
audioSource: this.sendAudio ? undefined : false,
videoSource: this.sendVideo ? (this.optionsVideo === 'screen' ? 'screen' : undefined) : false,
publishAudio: this.activeAudio,
publishVideo: this.activeVideo,
resolution: '640x480',
frameRate: 30,
insertMode: 'APPEND'
})
.then(publisher => {
this.publisher = publisher;
this.addPublisherEvents(this.publisher);
if (this.subscribeToRemote) {
this.publisher.subscribeToRemote();
}
this.session.publish(this.publisher)
.then(() => {
console.log(this.publisher);
})
.catch(e => {
console.error(e);
});
})
.catch(err => {
if (err) {
console.error(err);
this.openviduError = err;
if (err.name === 'SCREEN_EXTENSION_NOT_INSTALLED') {
this.extensionDialog.open(ExtensionDialogComponent, {
data: { url: err.message },
disableClose: true,
width: '250px'
});
}
}
});
}
syncSubscribe(session: Session, event) {
const subscriber: Subscriber = session.subscribe(event.stream, 'remote-vid-' + session.connection.connectionId);
this.subscribers[subscriber.stream.connection.connectionId] = {
'subscriber': subscriber,
'subbed': true,
'recorder': undefined,
'recording': false,
'paused': false,
'videoElement': undefined
};
subscriber.on('videoElementCreated', (e) => {
if (!event.stream.hasVideo) {
$(e.element).css({ 'background-color': '#4d4d4d' });
$(e.element).attr('poster', 'assets/images/volume.png');
}
this.subscribers[subscriber.stream.connection.connectionId].videoElement = e.element;
this.updateEventList('videoElementCreated', e.element.id);
});
subscriber.on('videoPlaying', (e) => {
this.appendSubscriberData(e.element, subscriber.stream.connection);
this.updateEventList('videoPlaying', e.element.id);
});
subscriber.on('videoElementDestroyed', (e) => {
this.updateEventList('videoElementDestroyed', '(Subscriber)');
});
}
asyncSubscribe(session: Session, event) {
session.subscribeAsync(event.stream, 'remote-vid-' + session.connection.connectionId)
.then(subscriber => {
this.subscribers[subscriber.stream.connection.connectionId] = {
'subscriber': subscriber,
'subbed': true,
'recorder': undefined,
'recording': false,
'paused': false,
'videoElement': undefined
};
subscriber.on('videoElementCreated', (e) => {
if (!event.stream.hasVideo) {
$(e.element).css({ 'background-color': '#4d4d4d' });
$(e.element).attr('poster', 'assets/images/volume.png');
}
this.subscribers[subscriber.stream.connection.connectionId].videoElement = e.element;
this.updateEventList('videoElementCreated', e.element.id);
});
subscriber.on('videoPlaying', (e) => {
this.appendSubscriberData(e.element, subscriber.stream.connection);
this.updateEventList('videoPlaying', e.element.id);
});
subscriber.on('videoElementDestroyed', (e) => {
this.updateEventList('videoElementDestroyed', '(Subscriber)');
});
})
.catch(err => {
console.error(err);
});
}
enableSpeakingEvents() {
this.session.on('publisherStartSpeaking', (event) => {
});
this.session.on('publisherStopSpeaking', (event) => {
});
}
disableSpeakingEvents() {
this.session.off('publisherStartSpeaking');
this.session.off('publisherStopSpeaking');
}
initGrayVideo(): void {
this.OV.getUserMedia(
{
videoSource: undefined,
resolution: '1280x720',
frameRate: 10,
}
)
.then((mediaStream: MediaStream) => {
const videoStreamTrack = mediaStream.getVideoTracks()[0];
const video = document.createElement('video');
video.srcObject = new MediaStream([videoStreamTrack]);
video.play();
const canvas = document.createElement('canvas') as any;
const ctx = canvas.getContext('2d');
ctx.filter = 'grayscale(100%)';
video.addEventListener('play', () => {
const loop = () => {
if (!video.paused && !video.ended) {
ctx.drawImage(video, 0, 0, 300, 170);
setTimeout(loop, 100); // Drawing at 10fps
}
};
loop();
});
const grayVideoTrack = canvas.captureStream(30).getVideoTracks()[0];
this.OV.initPublisher(
document.body,
{
audioSource: false,
videoSource: grayVideoTrack,
insertMode: 'APPEND'
});
})
.catch(error => {
console.error(error);
});
}
} }

View File

@ -11,15 +11,54 @@
</div> </div>
</div> </div>
<div>
<h3>Session Properties</h3>
<table>
<tr>
<th>Archive Mode</th>
<th>Archive Layout</th>
<th>Media Mode</th>
</tr>
<tr id="tr-session-properties">
<td>
<mat-select placeholder="ArchiveMode" [(ngModel)]="selectedArchiveMode">
<mat-option *ngFor="let archiveMode of archiveModes" [value]="archiveMode">
{{ archiveMode }}
</mat-option>
</mat-select>
</td>
<td>
<mat-select placeholder="ArchiveLayout" [(ngModel)]="selectedArchiveLayout">
<mat-option *ngFor="let archiveLayout of archiveLayouts" [value]="archiveLayout">
{{ archiveLayout }}
</mat-option>
</mat-select>
</td>
<td>
<mat-select placeholder="MediaMode" [(ngModel)]="selectedMediaMode">
<mat-option *ngFor="let mediaMode of mediaModes" [value]="mediaMode">
{{ mediaMode }}
</mat-option>
</mat-select>
</td>
</tr>
</table>
</div>
<hr style="margin: 30px 0 30px 0">
<div id="table-row" fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="start"> <div id="table-row" fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="start">
<div fxLayout="column" fxFlex="65" fxFlexAlign="start" fxFill> <div fxLayout="column" fxFlex="65" fxFlexAlign="start" fxFill>
<table> <table>
<tr> <tr>
<th class="first-col">sessionIds</th> <th *ngIf="this.data.length > 1">Selection</th>
<th>tokens</th> <th class="first-col">Session IDs</th>
<th>Session</th> <th>Tokens</th>
</tr> </tr>
<tr *ngFor="let sid of this.data; let ind = index"> <tr *ngFor="let sid of this.data; let ind = index">
<td *ngIf="this.data.length > 1" style="text-align: center">
<mat-radio-button [checked]="selectedRadioIndex === ind" (click)="selectedRadioIndex = ind" name="sidOption"></mat-radio-button>
</td>
<td class="first-col"> <td class="first-col">
<mat-card [style.background]="getBackgroundColor(ind)">{{sid[0]}}</mat-card> <mat-card [style.background]="getBackgroundColor(ind)">{{sid[0]}}</mat-card>
</td> </td>
@ -28,9 +67,6 @@
<p *ngFor="let token of sid[1]">{{token}}</p> <p *ngFor="let token of sid[1]">{{token}}</p>
</mat-card> </mat-card>
</td> </td>
<td style="text-align: center">
<mat-radio-button [checked]="selectedRadioIndex === ind" (click)="selectedRadioIndex = ind" name="sidOption"></mat-radio-button>
</td>
</tr> </tr>
</table> </table>
</div> </div>

View File

@ -2,6 +2,7 @@ import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from 'rxjs/Subscription';
import { OpenviduRestService } from '../../services/openvidu-rest.service'; import { OpenviduRestService } from '../../services/openvidu-rest.service';
import { OpenviduParamsService } from '../../services/openvidu-params.service'; import { OpenviduParamsService } from '../../services/openvidu-params.service';
import { SessionProperties, ArchiveMode, ArchiveLayout, MediaMode } from 'openvidu-node-client';
import * as colormap from 'colormap'; import * as colormap from 'colormap';
const numColors = 64; const numColors = 64;
@ -21,8 +22,19 @@ export class TestApirestComponent implements OnInit, OnDestroy {
// API REST params // API REST params
serverData = 'data_test'; serverData = 'data_test';
selectedRadioIndex = 0; selectedRadioIndex = 0;
selectedRole = 'PUBLISHER';
openViduRoles = ['SUBSCRIBER', 'PUBLISHER', 'MODERATOR']; openViduRoles = ['SUBSCRIBER', 'PUBLISHER', 'MODERATOR'];
selectedRole = 'PUBLISHER';
archiveModes = ['ALWAYS', 'MANUAL'];
selectedArchiveMode = 'MANUAL';
archiveLayouts = ['BEST_FIT'];
selectedArchiveLayout = 'BEST_FIT';
mediaModes = ['ROUTED'];
selectedMediaMode = 'ROUTED';
// API REST data collected // API REST data collected
data = []; data = [];
@ -57,7 +69,12 @@ export class TestApirestComponent implements OnInit, OnDestroy {
} }
private getSessionId() { private getSessionId() {
this.openviduRestService.getSessionId(this.openviduUrl, this.openviduSecret) this.openviduRestService.getSessionId(this.openviduUrl, this.openviduSecret,
new SessionProperties.Builder()
.archiveMode(ArchiveMode[this.selectedArchiveMode])
.archiveLayout(ArchiveLayout[this.selectedArchiveLayout])
.mediaMode(MediaMode[this.selectedMediaMode])
.build())
.then((sessionId) => { .then((sessionId) => {
this.updateData(); this.updateData();
}) })

View File

@ -3,7 +3,8 @@ import {
OpenVidu as OpenViduAPI, OpenVidu as OpenViduAPI,
Session as SessionAPI, Session as SessionAPI,
TokenOptions as TokenOptionsAPI, TokenOptions as TokenOptionsAPI,
OpenViduRole as OpenViduRoleAPI OpenViduRole as OpenViduRoleAPI,
SessionProperties as SessionPropertiesAPI
} from 'openvidu-node-client'; } from 'openvidu-node-client';
import { environment } from '../../environments/environment'; import { environment } from '../../environments/environment';
@ -15,9 +16,9 @@ export class OpenviduRestService {
constructor() { } constructor() { }
getSessionId(openviduURL: string, openviduSecret: string): Promise<string> { getSessionId(openviduURL: string, openviduSecret: string, sessionProperties: SessionPropertiesAPI): Promise<string> {
const OV = new OpenViduAPI(openviduURL, openviduSecret); const OV = new OpenViduAPI(openviduURL, openviduSecret);
const session = OV.createSession(); const session = OV.createSession(sessionProperties);
return new Promise(resolve => { return new Promise(resolve => {
session.getSessionId((sessionId) => { session.getSessionId((sessionId) => {