openviu-testapp: on-demand turn configuration

pull/73/head
pabloFuente 2018-06-08 11:07:38 +02:00
parent b480eca0af
commit d8c98e0901
7 changed files with 171 additions and 61 deletions

View File

@ -535,11 +535,36 @@ export class Stream {
}
private getIceServersConf(): RTCIceServer[] | undefined {
return !!this.session.openvidu.advancedConfiguration.iceServers ?
this.session.openvidu.advancedConfiguration.iceServers :
!!this.session.openvidu.turnCredentials ?
[this.session.openvidu.turnCredentials] :
undefined;
let returnValue;
if (!!this.session.openvidu.advancedConfiguration.iceServers) {
returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ?
undefined :
this.session.openvidu.advancedConfiguration.iceServers;
} else if (this.session.openvidu.turnCredentials) {
returnValue = [this.session.openvidu.turnCredentials];
} else {
returnValue = undefined;
}
return returnValue;
}
// tslint:disable:no-string-literal
/*getSelectedIceCandidate() {
return new Promise((resolve, reject) => {
const connectionDetails = {};
this.getRTCPeerConnection().getStats(null).then(stats => {
stats.result().forEach((report) => {
const selectedCandidatePair = report[Object.keys(report).filter(key => { return report[key].selected; })[0]]
, localICE = stats[selectedCandidatePair.localCandidateId]
, remoteICE = stats[selectedCandidatePair.remoteCandidateId];
connectionDetails['LocalAddress'] = [localICE.ipAddress, localICE.portNumber].join(':');
connectionDetails['RemoteAddress'] = [remoteICE.ipAddress, remoteICE.portNumber].join(':');
connectionDetails['LocalCandidateType'] = localICE.candidateType;
connectionDetails['RemoteCandidateType'] = remoteICE.candidateType;
resolve(connectionDetails);
});
});
});
}*/
}

View File

@ -20,7 +20,7 @@ export interface OpenViduAdvancedConfiguration {
/**
* Array of [RTCIceServer](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer) to be used by OpenVidu Browser instead of the default free ice server array (got from [freeice](https://github.com/DamonOehlman/freeice) library)
*/
iceServers?: RTCIceServer[];
iceServers?: RTCIceServer[] | string;
/**
* URL to a custom screen share extension for Chrome (always based on ours: [openvidu-screen-sharing-chrome-extension](https://github.com/OpenVidu/openvidu-screen-sharing-chrome-extension)) to be used instead of the default one.

View File

@ -3257,7 +3257,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -3278,12 +3279,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -3298,17 +3301,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -3425,7 +3431,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -3437,6 +3444,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -3451,6 +3459,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -3458,12 +3467,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@ -3482,6 +3493,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -3562,7 +3574,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -3574,6 +3587,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -3659,7 +3673,8 @@
"safe-buffer": {
"version": "5.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -3695,6 +3710,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -3714,6 +3730,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -3757,12 +3774,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},

View File

@ -0,0 +1,28 @@
mat-radio-button {
margin-left: 5px;
font-size: 14px;
}
mat-radio-button:first-child {
margin-left: 0;
}
#turn-conf-label {
display: block;
font-size: 12px;
color: rgba(0, 0, 0, 0.54);
font-weight: 400;
margin-bottom: 5px;
}
.not-manual {
padding-top: 6px;
padding-bottom: 15px;
}
#manual-turn-div {
margin-top: 10px;
padding: 5px;
border: 1px solid #00000026;
border-radius: 3px;
}

View File

@ -0,0 +1,55 @@
<div>
<h2 mat-dialog-title>Session properties</h2>
<mat-dialog-content>
<mat-form-field>
<mat-select placeholder="MediaMode" [(ngModel)]="sessionProperties.mediaMode">
<mat-option *ngFor="let enumerator of enumToArray(mediaMode)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="RecordingMode" [(ngModel)]="sessionProperties.recordingMode">
<mat-option *ngFor="let enumerator of enumToArray(recordingMode)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="DefaultRecordingLayout" [(ngModel)]="sessionProperties.defaultRecordingLayout">
<mat-option *ngFor="let enumerator of enumToArray(defaultRecordingLayout)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="this.sessionProperties.defaultRecordingLayout === 'CUSTOM'">
<input matInput placeholder="DefaultCustomLayout" [(ngModel)]="sessionProperties.defaultCustomLayout">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="CustomSessionId" [(ngModel)]="sessionProperties.customSessionId">
</mat-form-field>
<label id="turn-conf-label">Turn configuration</label>
<div [class.not-manual]="turnConf !== 'manual'">
<mat-radio-group name="Turn configuration" [(ngModel)]="turnConf">
<mat-radio-button value="auto">Auto</mat-radio-button>
<mat-radio-button value="freeice">Freeice</mat-radio-button>
<mat-radio-button value="manual">Manual</mat-radio-button>
</mat-radio-group>
<div *ngIf="turnConf === 'manual'" id="manual-turn-div">
<mat-form-field style="width: 100%">
<input matInput placeholder="url" [(ngModel)]="manualTurnConf.urls[0]">
</mat-form-field>
<mat-form-field style="width: 49%; padding-right: 2px">
<input matInput placeholder="user" [(ngModel)]="manualTurnConf.username">
</mat-form-field>
<mat-form-field style="width: 49%; padding-left: 2px">
<input matInput placeholder="pass" [(ngModel)]="manualTurnConf.credential">
</mat-form-field>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button [mat-dialog-close]="undefined">CANCEL</button>
<button mat-button [mat-dialog-close]="{sessionProperties: sessionProperties, turnConf: turnConf, manualTurnConf: manualTurnConf}">SAVE</button>
</mat-dialog-actions>
</div>

View File

@ -5,56 +5,24 @@ import { SessionProperties, MediaMode, RecordingMode, RecordingLayout } from 'op
@Component({
selector: 'app-session-properties-dialog',
template: `
<div>
<h2 mat-dialog-title>Session properties</h2>
<mat-dialog-content>
<mat-form-field>
<mat-select placeholder="MediaMode" [(ngModel)]="sessionProperties.mediaMode">
<mat-option *ngFor="let enumerator of enumToArray(mediaMode)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="RecordingMode" [(ngModel)]="sessionProperties.recordingMode">
<mat-option *ngFor="let enumerator of enumToArray(recordingMode)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="DefaultRecordingLayout" [(ngModel)]="sessionProperties.defaultRecordingLayout">
<mat-option *ngFor="let enumerator of enumToArray(defaultRecordingLayout)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="this.sessionProperties.defaultRecordingLayout === 'CUSTOM'">
<input matInput placeholder="DefaultCustomLayout" [(ngModel)]="sessionProperties.defaultCustomLayout">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="CustomSessionId" [(ngModel)]="sessionProperties.customSessionId">
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button [mat-dialog-close]="undefined">CANCEL</button>
<button mat-button [mat-dialog-close]="sessionProperties">SAVE</button>
</mat-dialog-actions>
</div>
`
templateUrl: './session-properties-dialog.component.html',
styleUrls: ['./session-properties-dialog.component.css']
})
export class SessionPropertiesDialogComponent {
sessionProperties: SessionProperties;
turnConf: string;
manualTurnConf: RTCIceServer = {};
mediaMode = MediaMode;
recordingMode = RecordingMode;
defaultRecordingLayout = RecordingLayout;
constructor(public dialogRef: MatDialogRef<SessionPropertiesDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: SessionProperties) {
this.sessionProperties = data;
@Inject(MAT_DIALOG_DATA) public data) {
this.sessionProperties = data.sessionProperties;
this.turnConf = data.turnConf;
this.manualTurnConf = data.manualTurnConf;
}
enumToArray(enumerator: any) {

View File

@ -112,6 +112,9 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
publisherStopSpeaking: false
};
turnConf = 'auto';
manualTurnConf: RTCIceServer = { urls: [] };
events: OpenViduEvent[] = [];
openviduError: any;
@ -183,6 +186,12 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
this.OV = new OpenVidu();
if (this.turnConf === 'freeice') {
this.OV.setAdvancedConfiguration({ iceServers: 'freeice' });
} else if (this.turnConf === 'manual') {
this.OV.setAdvancedConfiguration({ iceServers: [this.manualTurnConf] });
}
this.session = this.OV.initSession();
this.updateSessionEvents({
@ -471,16 +480,22 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
openSessionPropertiesDialog() {
this.sessionProperties.customSessionId = this.sessionName;
const dialogRef = this.dialog.open(SessionPropertiesDialogComponent, {
data: this.sessionProperties,
width: '235px'
data: {
sessionProperties: this.sessionProperties,
turnConf: this.turnConf,
manualTurnConf: this.manualTurnConf
},
width: '280px'
});
dialogRef.afterClosed().subscribe((result: SessionPropertiesAPI) => {
dialogRef.afterClosed().subscribe((result) => {
if (!!result) {
this.sessionProperties = result;
this.sessionProperties = result.sessionProperties;
if (!!this.sessionProperties.customSessionId) {
this.sessionName = this.sessionProperties.customSessionId;
}
this.turnConf = result.turnConf;
this.manualTurnConf = result.manualTurnConf;
}
document.getElementById('session-settings-btn-' + this.index).classList.remove('cdk-program-focused');
});