openvidu-browser: IE major compatibility (streamPlaying, videoDimensions)

pull/255/head
pabloFuente 2019-05-14 11:40:24 +02:00
parent 4e1a080232
commit c8b648fef8
4 changed files with 97 additions and 58 deletions

View File

@ -1,7 +1,7 @@
{
"author": "OpenVidu",
"dependencies": {
"@types/node": "11.13.6",
"@types/node": "12.0.0",
"@types/platform": "1.3.2",
"freeice": "2.2.2",
"hark": "1.2.3",
@ -24,8 +24,8 @@
"tsify": "4.0.1",
"tslint": "5.16.0",
"typedoc": "0.14.2",
"typescript": "3.4.4",
"uglify-js": "3.5.6"
"typescript": "3.4.5",
"uglify-js": "3.5.11"
},
"license": "Apache-2.0",
"main": "lib/index.js",

View File

@ -19,12 +19,15 @@ import { LocalRecorder } from './LocalRecorder';
import { Publisher } from './Publisher';
import { Session } from './Session';
import { Stream } from './Stream';
import { StreamManager } from './StreamManager';
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
import { Device } from '../OpenViduInternal/Interfaces/Public/Device';
import { OpenViduAdvancedConfiguration } from '../OpenViduInternal/Interfaces/Public/OpenViduAdvancedConfiguration';
import { PublisherProperties } from '../OpenViduInternal/Interfaces/Public/PublisherProperties';
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent';
import { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent';
import * as screenSharingAuto from '../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto';
import * as screenSharing from '../OpenViduInternal/ScreenSharing/Screen-Capturing';
@ -109,6 +112,7 @@ export class OpenVidu {
console.info("Detected IE Explorer " + platform.version);
this.importIEAdapterJS();
this.importURLLibrary();
this.setGlobalIEFunctions();
}
if (platform.os!!.family === 'iOS' || platform.os!!.family === 'Android') {
@ -781,7 +785,7 @@ export class OpenVidu {
}
private importURLLibrary(): void {
const moduleSpecifier = 'https://polyfill.io/v3/polyfill.min.js?features=URL';
const moduleSpecifier = 'https://cdn.jsdelivr.net/npm/url-polyfill@1.1.5/url-polyfill.min.js';
const scriptId = 'url-script-element';
var script = document.createElement('script');
script.async = false;
@ -800,4 +804,50 @@ export class OpenVidu {
}
}
private setGlobalIEFunctions(): void {
// FIX: the IE plugin seems to require the handler functions to be globally accessible. Store the functions with unique streamId
// Global handler for onloadedmetadata
(<any>window).IEOnLoadedMetadata = (simVideo: HTMLVideoElement, str: Stream) => {
const videoDimensionsSet = () => {
str.videoDimensions = {
width: simVideo.videoWidth,
height: simVideo.videoHeight
};
// TODO: if screen-share, set this.screenShareResizeInterval
str.isLocalStreamReadyToPublish = true;
str.ee.emitEvent('stream-ready-to-publish', []);
};
let interval;
if (simVideo.videoWidth === 0) {
interval = setInterval(() => {
if (simVideo.videoWidth !== 0) {
clearInterval(interval);
videoDimensionsSet();
}
}, 40);
} else {
videoDimensionsSet();
}
};
// Global handler for oncanplay
(<any>window).IEOnCanPlay = (strManager: StreamManager) => {
if (strManager.stream.isLocal()) {
if (!strManager.stream.displayMyRemote()) {
console.info("Your local 'Stream' with id [" + strManager.stream.streamId + '] video is now playing');
strManager.ee.emitEvent('videoPlaying', [new VideoElementEvent(strManager.videos[0].video, strManager, 'videoPlaying')]);
} else {
console.info("Your own remote 'Stream' with id [" + strManager.stream.streamId + '] video is now playing');
strManager.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent(strManager.videos[0].video, strManager, 'remoteVideoPlaying')]);
}
} else {
console.info("Remote 'Stream' with id [" + strManager.stream.streamId + '] video is now playing');
strManager.ee.emitEvent('videoPlaying', [new VideoElementEvent(strManager.videos[0].video, strManager, 'videoPlaying')]);
}
strManager.ee.emitEvent('streamPlaying', [new StreamManagerEvent(strManager, 'streamPlaying', undefined)]);
};
}
}

View File

@ -322,6 +322,16 @@ export class Publisher extends StreamManager {
if (platform['isInternetExplorer']) {
this.videoReference = video;
}
} else {
if (platform['isInternetExplorer']) {
// IE cannot have a video reference not inserted into DOM
// Pick up the first video element of videos array
this.videoReference = this.videos[0].video;
if (!this.videoReference) {
console.warn('IE requires the video element to be defined when initializing a Publisher. ' +
'Be sure to initialize the publisher passing a pre-existing targetElement')
}
}
}
this.stream.setMediaStream(mediaStream);
@ -331,43 +341,15 @@ export class Publisher extends StreamManager {
this.videoReference = this.customAttachMediaStreamIE(this.videoReference, mediaStream);
if (this.stream.isSendVideo()) {
if (!this.stream.isSendScreen()) {
/*this.videoReference.onloadedmetadata = () => {
this.stream.videoDimensions = {
width: this.videoReference.videoWidth,
height: this.videoReference.videoHeight
};
// TODO: if screen-share, set this.screenShareResizeInterval
console.warn(this.stream.videoDimensions);
this.stream.isLocalStreamReadyToPublish = true;
this.stream.ee.emitEvent('stream-ready-to-publish', []);
}*/
this.stream.videoDimensions = {
width: this.videoReference.videoWidth,
height: this.videoReference.videoHeight
};
// TODO: if screen-share, set this.screenShareResizeInterval
console.warn(this.stream.videoDimensions);
this.stream.isLocalStreamReadyToPublish = true;
this.stream.ee.emitEvent('stream-ready-to-publish', []);
this.videoReference.onplaying = () => {
console.warn("PLAYINNNGNGNGNGNGNG!!!");
}
this.videoReference.addEventListener('loadedmetadata', (<any>window).IEOnLoadedMetadata(this.videoReference, this.stream));
}
}
});
} else {
this.videoReference.srcObject = mediaStream;
}
if (!this.stream.displayMyRemote()) {
if (!this.stream.displayMyRemote() && (platform.name !== 'IE')) {
// When we are subscribed to our remote we don't still set the MediaStream object in the video elements to
// avoid early 'streamPlaying' event
this.stream.updateMediaStreamInVideos();
@ -395,18 +377,18 @@ export class Publisher extends StreamManager {
};
let interval;
this.videoReference.onloadedmetadata = () => {
this.videoReference.addEventListener('loadedmetadata', () => {
if (this.videoReference.videoWidth === 0) {
interval = setInterval(() => {
if (this.videoReference.videoWidth !== 0) {
videoDimensionsSet();
clearInterval(interval);
videoDimensionsSet();
}
}, 10);
}, 40);
} else {
videoDimensionsSet();
}
};
});
} else if (platform.name !== 'IE') {
// Rest of platforms except IE
// With no screen share, video dimension can be set directly from MediaStream (getSettings)
@ -430,7 +412,7 @@ export class Publisher extends StreamManager {
}
} else {
// With screen share, video dimension must be got from a video element (onloadedmetadata event)
this.videoReference.onloadedmetadata = () => {
this.videoReference.addEventListener('loadedmetadata', () => {
this.stream.videoDimensions = {
width: this.videoReference.videoWidth,
height: this.videoReference.videoHeight
@ -467,7 +449,7 @@ export class Publisher extends StreamManager {
}, 500);
this.stream.isLocalStreamReadyToPublish = true;
this.stream.ee.emitEvent('stream-ready-to-publish', []);
};
});
}
} else {
this.stream.isLocalStreamReadyToPublish = true;

View File

@ -87,11 +87,11 @@ export class StreamManager implements EventDispatcher {
/**
* @hidden
*/
protected ee = new EventEmitter();
ee = new EventEmitter();
/**
* @hidden
*/
protected canPlayListener: EventListenerOrEventListenerObject;
protected canPlayListener: EventListener;
/**
@ -123,21 +123,23 @@ export class StreamManager implements EventDispatcher {
this.element = targEl;
}
}
this.canPlayListener = () => {
if (this.stream.isLocal()) {
if (!this.stream.displayMyRemote()) {
console.info("Your local 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
if (!platform['isInternetExplorer']) {
this.canPlayListener = () => {
if (this.stream.isLocal()) {
if (!this.stream.displayMyRemote()) {
console.info("Your local 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
} else {
console.info("Your own remote 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
}
} else {
console.info("Your own remote 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]);
console.info("Remote 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
}
} else {
console.info("Remote 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
}
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this, 'streamPlaying', undefined)]);
};
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this, 'streamPlaying', undefined)]);
};
}
}
/**
@ -393,7 +395,7 @@ export class StreamManager implements EventDispatcher {
this.videos.forEach(streamManagerVideo => {
// Remove oncanplay event listener (only OpenVidu browser one, not the user ones)
streamManagerVideo.video.removeEventListener('canplay', this.canPlayListener);
streamManagerVideo.video.removeEventListener('canplay', platform['isInternetExplorer'] ? (<any>window).IEOnCanPlay : this.canPlayListener);
if (!!streamManagerVideo.targetElement) {
// Only remove from DOM videos created by OpenVidu Browser (those generated by passing a valid targetElement in OpenVidu.initPublisher
// and Session.subscribe or those created by StreamManager.createVideoElement). All this videos triggered a videoElementCreated event
@ -428,7 +430,7 @@ export class StreamManager implements EventDispatcher {
*/
addPlayEventToFirstVideo() {
if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) {
this.videos[0].video.addEventListener('canplay', this.canPlayListener);
this.videos[0].video.addEventListener('canplay', platform['isInternetExplorer'] ? (<any>window).IEOnCanPlay(this) : this.canPlayListener);
}
}
@ -482,6 +484,12 @@ export class StreamManager implements EventDispatcher {
protected customAttachMediaStreamIE(video: HTMLVideoElement, mediaStream: MediaStream): HTMLVideoElement {
var simVideo = attachMediaStream(video, mediaStream);
if (!simVideo) {
console.error('The video element used by IE to insert its custom media element is not properly added to DOM (must be inserted and visible)');
console.error(video);
return simVideo;
}
// Replace HTMLVideoElemet (if exists) with new HTMLObjectElement returned by IE plugin
for (let i = 0; i < this.videos.length; i++) {
if (this.videos[i].video === video) {
@ -492,7 +500,6 @@ export class StreamManager implements EventDispatcher {
// Always launch videoElementCreated event after IE plugin has inserted simulated video into DOM
this.ee.emitEvent('videoElementCreated', [new VideoElementEvent(simVideo, this, 'videoElementCreated')]);
this.addPlayEventToFirstVideo();
return simVideo;
}