TokBox Tutorial 100% compatible

pull/3/head
pabloFuente 2017-04-12 11:45:08 +02:00
parent 471fca15ac
commit 9f41599afd
7 changed files with 203 additions and 119 deletions

View File

@ -18,7 +18,7 @@ import { Session, SessionOptions } from './Session';
import { Stream } from './Stream'; import { Stream } from './Stream';
import * as RpcBuilder from 'kurento-jsonrpc'; import * as RpcBuilder from 'kurento-jsonrpc';
export type Callback<T> = ( error?: any, openVidu?: T ) => void; export type Callback<T> = (error?: any, openVidu?: T) => void;
export class OpenVidu { export class OpenVidu {
@ -29,8 +29,8 @@ export class OpenVidu {
private camera: Stream; private camera: Stream;
private remoteStreams: Stream[] = []; private remoteStreams: Stream[] = [];
constructor( private wsUri: string ) { constructor(private wsUri: string) {
if(this.wsUri.charAt(wsUri.length-1) != '/'){ if (this.wsUri.charAt(wsUri.length - 1) != '/') {
this.wsUri += '/'; this.wsUri += '/';
} }
this.wsUri += 'room'; this.wsUri += 'room';
@ -58,19 +58,17 @@ export class OpenVidu {
console.log("Error accessing the camera"); console.log("Error accessing the camera");
} }
else { else {
this.camera.playOnlyVideo(parentId, null); this.cameraReady(camera!, parentId);
this.camera.isReady = true;
this.camera.emitStreamReadyEvent();
} }
}); });
return this.camera; return this.camera;
} else { } else {
this.camera.requestCameraAccess((error, camera) => { this.camera.requestCameraAccess((error, camera) => {
if (error){ if (error) {
callback(error); callback(error);
} }
else { else {
this.camera.playOnlyVideo(parentId, null); this.cameraReady(camera!, parentId);
callback(undefined); callback(undefined);
} }
}); });
@ -78,6 +76,13 @@ export class OpenVidu {
} }
} }
cameraReady(camera: Stream, parentId: string) {
this.camera = camera;
this.camera.playOnlyVideo(parentId, null);
this.camera.isReady = true;
this.camera.emitStreamReadyEvent();
}
initPublisher(cameraOptions: any, callback) { initPublisher(cameraOptions: any, callback) {
console.log("Publisher initialized!"); console.log("Publisher initialized!");
@ -105,14 +110,14 @@ export class OpenVidu {
return this.session; return this.session;
} }
connect( callback: Callback<OpenVidu> ): void { connect(callback: Callback<OpenVidu>): void {
this.callback = callback; this.callback = callback;
this.initJsonRpcClient( this.wsUri ); this.initJsonRpcClient(this.wsUri);
} }
private initJsonRpcClient( wsUri: string ): void { private initJsonRpcClient(wsUri: string): void {
let config = { let config = {
heartbeat: 3000, heartbeat: 3000,
@ -120,177 +125,181 @@ export class OpenVidu {
ws: { ws: {
uri: wsUri, uri: wsUri,
useSockJS: false, useSockJS: false,
onconnected: this.connectCallback.bind( this ), onconnected: this.connectCallback.bind(this),
ondisconnect: this.disconnectCallback.bind( this ), ondisconnect: this.disconnectCallback.bind(this),
onreconnecting: this.reconnectingCallback.bind( this ), onreconnecting: this.reconnectingCallback.bind(this),
onreconnected: this.reconnectedCallback.bind( this ) onreconnected: this.reconnectedCallback.bind(this)
}, },
rpc: { rpc: {
requestTimeout: 15000, requestTimeout: 15000,
//notifications //notifications
participantJoined: this.onParticipantJoined.bind( this ), participantJoined: this.onParticipantJoined.bind(this),
participantPublished: this.onParticipantPublished.bind( this ), participantPublished: this.onParticipantPublished.bind(this),
participantUnpublished: this.onParticipantLeft.bind( this ), participantUnpublished: this.onParticipantLeft.bind(this),
participantLeft: this.onParticipantLeft.bind( this ), participantLeft: this.onParticipantLeft.bind(this),
participantEvicted: this.onParticipantEvicted.bind( this ), participantEvicted: this.onParticipantEvicted.bind(this),
sendMessage: this.onNewMessage.bind( this ), sendMessage: this.onNewMessage.bind(this),
iceCandidate: this.iceCandidateEvent.bind( this ), iceCandidate: this.iceCandidateEvent.bind(this),
mediaError: this.onMediaError.bind( this ), mediaError: this.onMediaError.bind(this),
custonNotification: this.customNotification.bind( this ) custonNotification: this.customNotification.bind(this)
} }
}; };
this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient( config ); this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
} }
private customNotification( params ) { private customNotification(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.emitEvent( "custom-message-received", [{ params: params }] ); this.session.emitEvent("custom-message-received", [{ params: params }]);
} }
} }
private connectCallback( error ) { private connectCallback(error) {
if ( error ) { if (error) {
this.callback( error ); this.callback(error);
} else { } else {
this.callback( null ); this.callback(null);
} }
} }
private isRoomAvailable() { private isRoomAvailable() {
if ( this.session !== undefined && this.session instanceof Session ) { if (this.session !== undefined && this.session instanceof Session) {
return true; return true;
} else { } else {
console.warn( 'Room instance not found' ); console.warn('Room instance not found');
return false; return false;
} }
} }
private disconnectCallback() { private disconnectCallback() {
console.log( 'Websocket connection lost' ); console.log('Websocket connection lost');
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onLostConnection(); this.session.onLostConnection();
} else { } else {
alert( 'Connection error. Please reload page.' ); alert('Connection error. Please reload page.');
} }
} }
private reconnectingCallback() { private reconnectingCallback() {
console.log( 'Websocket connection lost (reconnecting)' ); console.log('Websocket connection lost (reconnecting)');
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onLostConnection(); this.session.onLostConnection();
} else { } else {
alert( 'Connection error. Please reload page.' ); alert('Connection error. Please reload page.');
} }
} }
private reconnectedCallback() { private reconnectedCallback() {
console.log( 'Websocket reconnected' ); console.log('Websocket reconnected');
} }
private onParticipantJoined( params ) { private onParticipantJoined(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onParticipantJoined( params ); this.session.onParticipantJoined(params);
} }
} }
private onParticipantPublished( params ) { private onParticipantPublished(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onParticipantPublished( params ); this.session.onParticipantPublished(params);
} }
} }
private onParticipantLeft( params ) { private onParticipantLeft(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onParticipantLeft( params ); this.session.onParticipantLeft(params);
} }
} }
private onParticipantEvicted( params ) { private onParticipantEvicted(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onParticipantEvicted( params ); this.session.onParticipantEvicted(params);
} }
} }
private onNewMessage( params ) { private onNewMessage(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onNewMessage( params ); this.session.onNewMessage(params);
} }
} }
private iceCandidateEvent( params ) { private iceCandidateEvent(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.recvIceCandidate( params ); this.session.recvIceCandidate(params);
} }
} }
private onRoomClosed( params ) { private onRoomClosed(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onRoomClosed( params ); this.session.onRoomClosed(params);
} }
} }
private onMediaError( params ) { private onMediaError(params) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.onMediaError( params ); this.session.onMediaError(params);
} }
} }
setRpcParams( params: any ) { setRpcParams(params: any) {
this.rpcParams = params; this.rpcParams = params;
} }
sendRequest( method, params, callback?) { sendRequest(method, params, callback?) {
if ( params && params instanceof Function ) { if (params && params instanceof Function) {
callback = params; callback = params;
params = undefined; params = undefined;
} }
params = params || {}; params = params || {};
if ( this.rpcParams && this.rpcParams !== null && this.rpcParams !== undefined ) { if (this.rpcParams && this.rpcParams !== null && this.rpcParams !== undefined) {
for ( let index in this.rpcParams ) { for (let index in this.rpcParams) {
if ( this.rpcParams.hasOwnProperty( index ) ) { if (this.rpcParams.hasOwnProperty(index)) {
params[index] = this.rpcParams[index]; params[index] = this.rpcParams[index];
console.log( 'RPC param added to request {' + index + ': ' + this.rpcParams[index] + '}' ); console.log('RPC param added to request {' + index + ': ' + this.rpcParams[index] + '}');
} }
} }
} }
console.log( 'Sending request: { method:"' + method + '", params: ' + JSON.stringify( params ) + ' }' ); console.log('Sending request: { method:"' + method + '", params: ' + JSON.stringify(params) + ' }');
this.jsonRpcClient.send( method, params, callback ); this.jsonRpcClient.send(method, params, callback);
} }
close( forced ) { close(forced) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.leave( forced, this.jsonRpcClient ); this.session.leave(forced, this.jsonRpcClient);
} }
}; };
disconnectParticipant( stream ) { disconnectParticipant(stream) {
if ( this.isRoomAvailable() ) { if (this.isRoomAvailable()) {
this.session.disconnect( stream ); this.session.disconnect(stream);
} }
} }
getCamera(options?) { getCamera(options?) {
if(this.camera){ if (this.camera) {
return this.camera; return this.camera;
} }
options = options || { options = options || {
audio: true, audio: true,
video: true, video: true,
data: true data: true,
mediaConstraints: {
audio: true,
video: { width: { ideal: 1280 } }
}
} }
options.participant = this.session.getLocalParticipant(); options.participant = this.session.getLocalParticipant();
this.camera = new Stream( this, true, this.session, options ); this.camera = new Stream(this, true, this.session, options);
return this.camera; return this.camera;
}; };
@ -308,30 +317,30 @@ export class OpenVidu {
};*/ };*/
//CHAT //CHAT
sendMessage( room, user, message ) { sendMessage(room, user, message) {
this.sendRequest( 'sendMessage', { this.sendRequest('sendMessage', {
message: message, message: message,
userMessage: user, userMessage: user,
roomMessage: room roomMessage: room
}, function( error, response ) { }, function (error, response) {
if ( error ) { if (error) {
console.error( error ); console.error(error);
} }
}); });
}; };
sendCustomRequest( params, callback ) { sendCustomRequest(params, callback) {
this.sendRequest( 'customRequest', params, callback ); this.sendRequest('customRequest', params, callback);
}; };
toggleLocalVideoTrack(activate: boolean){ toggleLocalVideoTrack(activate: boolean) {
this.getCamera().getWebRtcPeer().videoEnabled = activate; this.getCamera().getWebRtcPeer().videoEnabled = activate;
} }
toggleLocalAudioTrack(activate: boolean){ toggleLocalAudioTrack(activate: boolean) {
this.getCamera().getWebRtcPeer().audioEnabled = activate; this.getCamera().getWebRtcPeer().audioEnabled = activate;
} }

View File

@ -434,7 +434,7 @@ export class Stream {
if (this.isReady) { if (this.isReady) {
this.initWebRtcPeer(this.publishVideoCallback); this.initWebRtcPeer(this.publishVideoCallback);
} else { } else {
this.addEventListener('stream-ready', streamEvent => { this.ee.once('stream-ready', streamEvent => {
this.publish(); this.publish();
}); });
} }

View File

@ -38,8 +38,23 @@ export class OpenViduTokBox {
} }
} }
initPublisher(parentId: string, cameraOptions: any): PublisherTokBox { initPublisher(parentId: string, cameraOptions: any): PublisherTokBox;
return new PublisherTokBox(this.openVidu.initPublisherTagged(parentId, cameraOptions)); initPublisher(parentId: string, cameraOptions: any, callback: any): PublisherTokBox;
initPublisher(parentId: string, cameraOptions: any, callback?): PublisherTokBox {
if (!("audio" in cameraOptions && "data" in cameraOptions && "mediaConstraints" in cameraOptions &&
"video" in cameraOptions && (Object.keys(cameraOptions).length === 4))) {
cameraOptions = {
audio: true,
video: true,
data: true,
mediaConstraints: {
audio: true,
video: { width: { ideal: 1280 } }
}
}
}
return new PublisherTokBox(this.openVidu.initPublisherTagged(parentId, cameraOptions, callback));
} }
} }

View File

@ -17,4 +17,12 @@ export class PublisherTokBox {
this.stream = stream; this.stream = stream;
} }
publishAudio(value: boolean) {
this.stream.getWebRtcPeer().audioEnabled = value;
}
publishVideo(value: boolean) {
this.stream.getWebRtcPeer().videoEnabled = value;
}
} }

View File

@ -5,5 +5,5 @@
<md-icon class="right-btn" (click)="toggleLocalAudio()" [title]="'Toggle audio'">{{audioIcon}}</md-icon> <md-icon class="right-btn" (click)="toggleLocalAudio()" [title]="'Toggle audio'">{{audioIcon}}</md-icon>
<h1>{{lesson?.title}}</h1> <h1>{{lesson?.title}}</h1>
</div> </div>
<div id="local-stream"></div> <div id="publisher"></div>
<div id="remote-streams"></div> <div id="subscriber"></div>

View File

@ -18,13 +18,12 @@ export class VideoSessionComponent implements OnInit {
OV: OpenViduTokBox; OV: OpenViduTokBox;
session: SessionTokBox; session: SessionTokBox;
publisher: PublisherTokBox;
sessionId: string; sessionId: string;
token: string; token: string;
cameraOptions: any; cameraOptions: any;
localParentId: string = 'local-stream';
remoteParentId: string = 'remote-streams';
localVideoActivated: boolean; localVideoActivated: boolean;
localAudioActivated: boolean; localAudioActivated: boolean;
@ -45,29 +44,37 @@ export class VideoSessionComponent implements OnInit {
// 1) Initialize OpenVidu and your Session // 1) Initialize OpenVidu and your Session
this.OV = new OpenViduTokBox("wss://" + location.hostname + ":8443/"); this.OV = new OpenViduTokBox("wss://" + location.hostname + ":8443/");
this.session = this.OV.initSession(this.sessionId); this.session = this.OV.initSession("apikey", this.sessionId);
// 2) Specify the actions when events take place // 2) Specify the actions when events take place
this.session.on('streamCreated', (event) => { this.session.on('streamCreated', (event) => {
console.warn("Stream created:"); this.session.subscribe(event.stream, 'subscriber', {
console.warn(event.stream); insertMode: 'append',
this.session.subscribe(event.stream, this.remoteParentId); width: '100%',
height: '100%'
});
}); });
// 3) Connect to the session // 3) Connect to the session
this.session.connect(this.token, (error) => { this.session.connect(this.token, (error) => {
// If the connection is successful, initialize a publisher and publish to the session
if (!error) { if (!error) {
// 4) Get your own camera stream with the desired resolution and publish it, only if the user is supposed to do so // 4) Get your own camera stream with the desired resolution and publish it, only if the user is supposed to do so
let publisher = this.OV.initPublisher(this.localParentId, this.cameraOptions); this.publisher = this.OV.initPublisher('publisher', {
insertMode: 'append',
width: '100%',
height: '100%'
});
// 5) Publish your stream // 5) Publish your stream
this.session.publish(publisher); this.session.publish(this.publisher);
}
else {
return console.log("There was an error: " + error);
}
} else {
console.log('There was an error connecting to the session:', error.code, error.message);
}
}); });
} }
@ -142,6 +149,51 @@ export class VideoSessionComponent implements OnInit {
content.style.overflow = scroll; content.style.overflow = scroll;
} }
toggleLocalVideo() {
this.localVideoActivated = !this.localVideoActivated;
this.publisher.publishVideo(this.localVideoActivated);
this.videoIcon = this.localVideoActivated ? 'videocam' : 'videocam_off';
}
toggleLocalAudio() {
this.localAudioActivated = !this.localAudioActivated;
this.publisher.publishAudio(this.localAudioActivated);
this.audioIcon = this.localAudioActivated ? 'mic' : 'mic_off';
}
toggleFullScreen() {
let document: any = window.document;
let fs = document.getElementsByTagName('html')[0];
if (!document.fullscreenElement &&
!document.mozFullScreenElement &&
!document.webkitFullscreenElement &&
!document.msFullscreenElement) {
console.log("enter FULLSCREEN!");
this.fullscreenIcon = 'fullscreen_exit';
if (fs.requestFullscreen) {
fs.requestFullscreen();
} else if (fs.msRequestFullscreen) {
fs.msRequestFullscreen();
} else if (fs.mozRequestFullScreen) {
fs.mozRequestFullScreen();
} else if (fs.webkitRequestFullscreen) {
fs.webkitRequestFullscreen();
}
} else {
console.log("exit FULLSCREEN!");
this.fullscreenIcon = 'fullscreen';
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
}
exitFullScreen() { exitFullScreen() {
let document: any = window.document; let document: any = window.document;
let fs = document.getElementsByTagName('html')[0]; let fs = document.getElementsByTagName('html')[0];

View File

@ -66,21 +66,21 @@ md-icon:hover {
display: inline-block; display: inline-block;
} }
#local-stream { #publisher {
position: absolute; position: absolute;
width: 100%; width: 100%;
} }
#local-stream video { #publisher video {
width: 100%; width: 100%;
} }
#remote-streams { #subscriber {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
} }
#remote-streams video { #subscriber video {
width: 350px; width: 350px;
} }