OpenVidu + OpenViduTokBox Interfaces

pull/3/head
pabloFuente 2017-04-12 00:54:35 +02:00
parent c19307e066
commit 471fca15ac
16 changed files with 332 additions and 132 deletions

View File

@ -47,19 +47,35 @@ export class OpenVidu {
return this.session;
}
initPublisherTagged(parentId: string, cameraOptions: any, callback) {
initPublisherTagged(parentId: string, cameraOptions: any, callback?) {
console.log("Publisher tagged initialized!");
this.getCamera(cameraOptions);
this.camera.requestCameraAccess((error, camera) => {
if (error){
callback(error);
}
else {
this.camera.playOnlyVideo(parentId, null);
callback(undefined);
}
});
if (callback == null) {
this.camera.requestCameraAccess((error, camera) => {
if (error) {
console.log("Error accessing the camera");
}
else {
this.camera.playOnlyVideo(parentId, null);
this.camera.isReady = true;
this.camera.emitStreamReadyEvent();
}
});
return this.camera;
} else {
this.camera.requestCameraAccess((error, camera) => {
if (error){
callback(error);
}
else {
this.camera.playOnlyVideo(parentId, null);
callback(undefined);
}
});
return this.camera;
}
}
initPublisher(cameraOptions: any, callback) {

View File

@ -41,7 +41,8 @@ export class Session {
else {
this.configure({
sessionId: this.sessionId,
participantId: token
participantId: token,
subscribeToStreams: this.subscribeToStreams
});
let joinParams = {
@ -91,14 +92,14 @@ export class Session {
}
}
if (this.subscribeToStreams) {
//if (this.subscribeToStreams) {
for (let stream of roomEvent.streams) {
this.ee.emitEvent('stream-added', [{ stream }]);
// Adding the remote stream to the OpenVidu object
this.openVidu.getRemoteStreams().push(stream);
}
}
//}
callback(undefined);
}
@ -174,7 +175,7 @@ export class Session {
this.options = options;
this.id = options.sessionId;
this.subscribeToStreams = options.subscribeToStreams || true;
this.subscribeToStreams = options.subscribeToStreams == null ? true : options.subscribeToStreams;
this.updateSpeakerInterval = options.updateSpeakerInterval || 1500;
this.thresholdSpeaker = options.thresholdSpeaker || -50;
this.localParticipant.setId(options.participantId);
@ -187,6 +188,10 @@ export class Session {
return this.id;
}
getSessionId(){
return this.sessionId;
}
private activateUpdateMainSpeaker() {
setInterval(() => {
@ -236,11 +241,10 @@ export class Session {
if ( this.subscribeToStreams ) {
stream.subscribe();
this.ee.emitEvent( 'stream-added', [{ stream }] );
// Adding the remote stream to the OpenVidu object
this.openVidu.getRemoteStreams().push(stream);
}
this.ee.emitEvent( 'stream-added', [{ stream }] );
// Adding the remote stream to the OpenVidu object
this.openVidu.getRemoteStreams().push(stream);
}
}
@ -457,6 +461,31 @@ export class Session {
}
}
unpublish(stream: Stream){
let participant = stream.getParticipant();
if ( !participant ) {
console.error( "Stream to disconnect has no participant", stream );
return;
}
if ( participant === this.localParticipant ) {
delete this.participants[participant.getId()];
participant.dispose();
console.log( "Unpublishing my media (I'm " + participant.getId() + ")" );
delete this.localParticipant;
this.openVidu.sendRequest( 'unpublishVideo', function( error, response ) {
if ( error ) {
console.error( error );
} else {
console.info( "Media unpublished correctly" );
}
});
}
}
getStreams() {
return this.streams;
}

View File

@ -70,6 +70,7 @@ export class Stream {
private dataChannelOpened = false;
private videoSrc: string;
public isReady: boolean = false;
constructor(private openVidu: OpenVidu, private local: boolean, private room: Session, options: StreamOptions) {
@ -100,6 +101,10 @@ export class Stream {
}]);
}
emitStreamReadyEvent(){
this.ee.emitEvent('stream-ready'), [{}];
}
getVideoSrc() {
return this.videoSrc;
}
@ -426,8 +431,13 @@ export class Stream {
publish() {
// FIXME: Throw error when stream is not local
this.initWebRtcPeer(this.publishVideoCallback);
if (this.isReady) {
this.initWebRtcPeer(this.publishVideoCallback);
} else {
this.addEventListener('stream-ready', streamEvent => {
this.publish();
});
}
// FIXME: Now we have coupled connecting to a room and adding a
// stream to this room. But in the new API, there are two steps.

View File

@ -18,7 +18,7 @@
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"strictNullChecks": true,
"outDir": "../lib",
"outDir": "../../lib/OpenVidu",
"emitBOM": false,
"preserveConstEnums": true,
"sourceMap": true

View File

@ -0,0 +1,12 @@
import { OpenViduTokBox } from './OpenViduTokBox';
//This export with --standalone option allows using OpenVidu from bowser with namespace
//export { OpenVidu } from './OpenVidu';
//This "hack" allows to use OpenVidu from the global space window
if(window){
window["OpenViduTokBox"] = OpenViduTokBox;
}
//Command to generate bundle.js without namespace
//watchify Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/OpenVidu.js -v

View File

@ -0,0 +1,45 @@
/*
* (C) Copyright 2016 OpenVidu (http://kurento.org/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { OpenVidu } from '../OpenVidu/OpenVidu';
import { SessionTokBox } from './SessionTokBox';
import { PublisherTokBox } from './PublisherTokBox';
export class OpenViduTokBox {
openVidu: OpenVidu;
constructor(private wsUri: string) {
this.openVidu = new OpenVidu(wsUri);
}
initSession(apiKey: string, sessionId: string): SessionTokBox;
initSession(sessionId: string): SessionTokBox;
initSession(param1, param2?): any {
if (typeof param2 == "string") {
return new SessionTokBox(this.openVidu.initSession(param2), this);
} else {
return new SessionTokBox(this.openVidu.initSession(param1), this);
}
}
initPublisher(parentId: string, cameraOptions: any): PublisherTokBox {
return new PublisherTokBox(this.openVidu.initPublisherTagged(parentId, cameraOptions));
}
}

View File

@ -0,0 +1,20 @@
/*
* options: name: XXX data: true (Maybe this is based on webrtc) audio: true,
* video: true, url: "file:///..." > Player screen: true > Desktop (implicit
* video:true, audio:false) audio: true, video: true > Webcam
*
* stream.hasAudio(); stream.hasVideo(); stream.hasData();
*/
import { Stream, StreamOptions, VideoOptions } from '../OpenVidu/Stream';
import { OpenViduTokBox } from './OpenViduTokBox';
import { SessionTokBox } from './SessionTokBox';
export class PublisherTokBox {
stream: Stream;
constructor(stream: Stream) {
this.stream = stream;
}
}

View File

@ -0,0 +1,121 @@
import { Session, SessionOptions } from '../OpenVidu/Session';
import { Stream } from '../OpenVidu/Stream';
import { OpenViduTokBox } from './OpenViduTokBox';
import { PublisherTokBox } from './PublisherTokBox';
export class SessionTokBox {
constructor(private session: Session, private openVidu: OpenViduTokBox) { }
connect(token, callback) {
// Early configuration to deactivate automatic subscription to streams
this.session.configure({
sessionId: this.session.getSessionId(),
participantId: token,
subscribeToStreams: false
});
this.session.connect(token, callback);
}
disconnect() {
this.openVidu.openVidu.close(false);
}
publish(publisher: PublisherTokBox) {
publisher.stream.publish();
}
unpublish(publisher: PublisherTokBox) {
this.session.unpublish(publisher.stream);
}
on(eventName: string, callback) {
let realEventName = '';
switch (eventName) {
case 'streamCreated':
realEventName = 'stream-added'
break;
case 'streamDestroyed':
realEventName = 'stream-removed'
break;
}
if (realEventName != '') {
this.session.addEventListener(realEventName, event => {
callback(event);
});
} else {
console.warn("That is not a supported event!");
}
}
subscribe(stream: Stream, htmlId: string, videoOptions: any);
subscribe(stream: Stream, htmlId: string);
subscribe(param1, param2, param3?) {
// Subscription
this.session.subscribe(param1);
param1.playOnlyVideo(param2, null);
}
/* Shortcut event API */
onStreamCreated(callback) {
this.session.addEventListener("stream-added", streamEvent => {
callback(streamEvent.stream);
});
}
onStreamDestroyed(callback) {
this.session.addEventListener("stream-removed", streamEvent => {
callback(streamEvent.stream);
});
}
onParticipantJoined(callback) {
this.session.addEventListener("participant-joined", participantEvent => {
callback(participantEvent.participant);
});
}
onParticipantLeft(callback) {
this.session.addEventListener("participant-left", participantEvent => {
callback(participantEvent.participant);
});
}
onParticipantPublished(callback) {
this.session.addEventListener("participant-published", participantEvent => {
callback(participantEvent.participant);
});
}
onParticipantEvicted(callback) {
this.session.addEventListener("participant-evicted", participantEvent => {
callback(participantEvent.participant);
});
}
onRoomClosed(callback) {
this.session.addEventListener("room-closed", roomEvent => {
callback(roomEvent.room);
});
}
onLostConnection(callback) {
this.session.addEventListener("lost-connection", roomEvent => {
callback(roomEvent.room);
});
}
onMediaError(callback) {
this.session.addEventListener("error-media", errorEvent => {
callback(errorEvent.error)
});
}
/* Shortcut event API */
}

View File

@ -0,0 +1,3 @@
declare module "kurento-jsonrpc";
declare module "webrtc-adapter";
declare module "kurento-utils";

View File

@ -0,0 +1,3 @@
export * from './OpenViduTokBox';
export * from './PublisherTokBox';
export * from './SessionTokBox';

View File

@ -0,0 +1,28 @@
{
"compilerOptions": {
"declaration": true,
"target": "es5",
"module": "commonjs",
//"noImplicitAny": true,
"noImplicitThis": true,
//"noUnusedLocals": true,
//"noUnusedParameters": true,
"skipDefaultLibCheck": true,
"skipLibCheck": true,
"suppressExcessPropertyErrors": true,
"suppressImplicitAnyIndexErrors": true,
//"allowUnusedLabels": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
//"allowUnreachableCode": true,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"strictNullChecks": true,
"outDir": "../../lib/OpenViduTokBox",
"emitBOM": false,
"preserveConstEnums": true,
"sourceMap": true
},
//"buildOnSave": true,
"compileOnSave":true
}

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { OpenVidu, Session, Stream } from 'openvidu-browser';
import { OpenViduTokBox, SessionTokBox, PublisherTokBox } from 'openvidu-browser';
import { VideoSessionService } from '../../services/video-session.service';
import { AuthenticationService } from '../../services/authentication.service';
@ -16,8 +16,8 @@ export class VideoSessionComponent implements OnInit {
lesson: Lesson;
OV: OpenVidu;
session: Session;
OV: OpenViduTokBox;
session: SessionTokBox;
sessionId: string;
token: string;
@ -44,69 +44,27 @@ export class VideoSessionComponent implements OnInit {
// In this case, the method ngOnInit takes care of it
// 1) Initialize OpenVidu and your Session
this.OV = new OpenVidu("wss://" + location.hostname + ":8443/");
this.OV = new OpenViduTokBox("wss://" + location.hostname + ":8443/");
this.session = this.OV.initSession(this.sessionId);
// 2) Specify the actions when participants enter and leave the session
this.session.onStreamAddedOV((stream) => {
console.warn("Stream added:");
console.warn(stream);
stream.playOnlyVideo(this.remoteParentId, null);
// 2) Specify the actions when events take place
this.session.on('streamCreated', (event) => {
console.warn("Stream created:");
console.warn(event.stream);
this.session.subscribe(event.stream, this.remoteParentId);
});
this.session.onStreamRemovedOV((stream) => {
console.warn("Stream removed:");
console.warn(stream);
stream.removeVideo(this.remoteParentId);
});
this.session.onParticipantJoinedOV((participant) => {
console.warn("Participant joined:");
console.warn(participant);
});
this.session.onParticipantLeftOV((participant) => {
console.warn("Participant left:");
console.warn(participant);
});
this.session.onParticipantPublishedOV((participant) => {
console.warn("Participant published:");
console.warn(participant);
});
this.session.onParticipantEvictedOV((participant) => {
console.warn("Participant evicted:");
console.warn(participant);
});
this.session.onRoomClosedOV((room) => {
console.warn("Room closed:");
console.warn(room);
});
this.session.onLostConnectionOV((room) => {
console.warn("Connection lost:");
console.warn(room);
});
this.session.onMediaErrorOV((error) => {
console.warn("Media error:");
console.warn(error);
});
// 3) Connect to the session
this.session.connect(this.token, (error) => {
if (error) return console.log("There was an error: " + error);
// 4) Get your own camera stream with the desired resolution and publish it, only if the user is supposed to do so
// Local publish generating an HTML video element as a child of parentId HTML element
this.OV.initPublisherTagged(this.localParentId, this.cameraOptions, (error) => {
if (error) return console.log("There was an error with your camera: " + error);
this.session.publish();
});
// Local publish without generating an HTML video element
/*this.OV.initPublisher(this.cameraOptions, (error) => {
if (error) return console.log("There was an error: " + error);
this.session.publish();
});*/
if (!error) {
// 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);
// 5) Publish your stream
this.session.publish(publisher);
}
else {
return console.log("There was an error: " + error);
}
});
@ -169,26 +127,14 @@ export class VideoSessionComponent implements OnInit {
ngOnDestroy() {
this.videoSessionService.removeUser(this.lesson.id).subscribe(
response => {
console.warn("You have succesfully left the lesson");
},
error => {
console.log(error);
});
console.warn("You have succesfully left the lesson");
},
error => {
console.log(error);
});
this.toggleScrollPage("auto");
this.exitFullScreen();
if (this.OV) this.OV.close(false);
}
toggleLocalVideo() {
this.localVideoActivated = !this.localVideoActivated;
this.OV.toggleLocalVideoTrack(this.localVideoActivated);
this.videoIcon = this.localVideoActivated ? 'videocam' : 'videocam_off';
}
toggleLocalAudio() {
this.localAudioActivated = !this.localAudioActivated;
this.OV.toggleLocalAudioTrack(this.localAudioActivated);
this.audioIcon = this.localAudioActivated ? 'mic' : 'mic_off';
if (this.OV) this.session.disconnect();
}
toggleScrollPage(scroll: string) {
@ -196,39 +142,6 @@ export class VideoSessionComponent implements OnInit {
content.style.overflow = scroll;
}
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() {
let document: any = window.document;
let fs = document.getElementsByTagName('html')[0];