mirror of https://github.com/OpenVidu/openvidu.git
547 lines
21 KiB
JavaScript
547 lines
21 KiB
JavaScript
![]() |
"use strict";
|
||
|
/*
|
||
|
* (C) Copyright 2017-2018 OpenVidu (http://openvidu.io/)
|
||
|
*
|
||
|
* 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.
|
||
|
*
|
||
|
*/
|
||
|
exports.__esModule = true;
|
||
|
var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
|
||
|
var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
|
||
|
var EventEmitter = require("wolfy87-eventemitter");
|
||
|
var kurentoUtils = require("../OpenViduInternal/KurentoUtils/kurento-utils-js");
|
||
|
var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
|
||
|
/**
|
||
|
* Represents each one of the videos send and receive by a user in a session.
|
||
|
* Therefore each [[Publisher]] and [[Subscriber]] has an attribute of type Stream
|
||
|
*/
|
||
|
var Stream = /** @class */ (function () {
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
function Stream(session, options) {
|
||
|
var _this = this;
|
||
|
this.ee = new EventEmitter();
|
||
|
this.isSubscribeToRemote = false;
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
this.isReadyToPublish = false;
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
this.isPublisherPublished = false;
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
this.isVideoELementCreated = false;
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
this.accessIsAllowed = false;
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
this.accessIsDenied = false;
|
||
|
this.session = session;
|
||
|
if (options.hasOwnProperty('id')) {
|
||
|
// InboundStreamOptions: stream belongs to a Subscriber
|
||
|
this.inboundStreamOpts = options;
|
||
|
this.streamId = this.inboundStreamOpts.id;
|
||
|
this.hasAudio = this.inboundStreamOpts.recvAudio;
|
||
|
this.hasVideo = this.inboundStreamOpts.recvVideo;
|
||
|
this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo;
|
||
|
this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate;
|
||
|
}
|
||
|
else {
|
||
|
// OutboundStreamOptions: stream belongs to a Publisher
|
||
|
this.outboundStreamOpts = options;
|
||
|
if (this.isSendVideo()) {
|
||
|
if (this.isSendScreen()) {
|
||
|
this.streamId = 'SCREEN';
|
||
|
this.typeOfVideo = 'SCREEN';
|
||
|
}
|
||
|
else {
|
||
|
this.streamId = 'CAMERA';
|
||
|
this.typeOfVideo = 'CAMERA';
|
||
|
}
|
||
|
this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate;
|
||
|
}
|
||
|
else {
|
||
|
this.streamId = 'MICRO';
|
||
|
delete this.typeOfVideo;
|
||
|
}
|
||
|
this.hasAudio = this.isSendAudio();
|
||
|
this.hasVideo = this.isSendVideo();
|
||
|
}
|
||
|
this.on('mediastream-updated', function () {
|
||
|
if (_this.video)
|
||
|
_this.video.srcObject = _this.mediaStream;
|
||
|
console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
|
||
|
});
|
||
|
}
|
||
|
/* Hidden methods */
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.getMediaStream = function () {
|
||
|
return this.mediaStream;
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.setMediaStream = function (mediaStream) {
|
||
|
this.mediaStream = mediaStream;
|
||
|
this.ee.emitEvent('mediastream-updated');
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.getWebRtcPeer = function () {
|
||
|
return this.webRtcPeer;
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.getRTCPeerConnection = function () {
|
||
|
return this.webRtcPeer.peerConnection;
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.getVideoElement = function () {
|
||
|
return this.video;
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.subscribeToMyRemote = function () {
|
||
|
this.isSubscribeToRemote = true;
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) {
|
||
|
this.outboundStreamOpts = outboundStreamOpts;
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.subscribe = function () {
|
||
|
var _this = this;
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
_this.initWebRtcPeerReceive()
|
||
|
.then(function () {
|
||
|
resolve();
|
||
|
})["catch"](function (error) {
|
||
|
reject(error);
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.publish = function () {
|
||
|
var _this = this;
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
if (_this.isReadyToPublish) {
|
||
|
_this.initWebRtcPeerSend()
|
||
|
.then(function () {
|
||
|
resolve();
|
||
|
})["catch"](function (error) {
|
||
|
reject(error);
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
_this.ee.once('stream-ready-to-publish', function (streamEvent) {
|
||
|
_this.publish()
|
||
|
.then(function () {
|
||
|
resolve();
|
||
|
})["catch"](function (error) {
|
||
|
reject(error);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.disposeWebRtcPeer = function () {
|
||
|
if (this.webRtcPeer) {
|
||
|
this.webRtcPeer.dispose();
|
||
|
}
|
||
|
if (this.speechEvent) {
|
||
|
this.speechEvent.stop();
|
||
|
}
|
||
|
this.stopWebRtcStats();
|
||
|
console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed');
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.disposeMediaStream = function () {
|
||
|
if (this.mediaStream) {
|
||
|
this.mediaStream.getAudioTracks().forEach(function (track) {
|
||
|
track.stop();
|
||
|
});
|
||
|
this.mediaStream.getVideoTracks().forEach(function (track) {
|
||
|
track.stop();
|
||
|
});
|
||
|
}
|
||
|
console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed');
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.displayMyRemote = function () {
|
||
|
return this.isSubscribeToRemote;
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.on = function (eventName, listener) {
|
||
|
this.ee.on(eventName, listener);
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.once = function (eventName, listener) {
|
||
|
this.ee.once(eventName, listener);
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.insertVideo = function (targetElement, insertMode) {
|
||
|
var _this = this;
|
||
|
if (!!targetElement) {
|
||
|
this.video = document.createElement('video');
|
||
|
this.video.id = (this.isLocal() ? 'local-' : 'remote-') + 'video-' + this.streamId;
|
||
|
this.video.autoplay = true;
|
||
|
this.video.controls = false;
|
||
|
this.video.srcObject = this.mediaStream;
|
||
|
if (this.isLocal() && !this.displayMyRemote()) {
|
||
|
this.video.muted = true;
|
||
|
if (this.outboundStreamOpts.publisherProperties.mirror) {
|
||
|
this.mirrorVideo(this.video);
|
||
|
}
|
||
|
this.video.oncanplay = function () {
|
||
|
console.info("Local 'Stream' with id [" + _this.streamId + '] video is now playing');
|
||
|
_this.ee.emitEvent('video-is-playing', [{
|
||
|
element: _this.video
|
||
|
}]);
|
||
|
};
|
||
|
}
|
||
|
else {
|
||
|
this.video.title = this.streamId;
|
||
|
}
|
||
|
this.targetElement = targetElement;
|
||
|
this.parentId = targetElement.id;
|
||
|
insertMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND;
|
||
|
this.insertElementWithMode(this.video, insertMode);
|
||
|
this.ee.emitEvent('video-element-created-by-stream', [{
|
||
|
element: this.video
|
||
|
}]);
|
||
|
this.isVideoELementCreated = true;
|
||
|
}
|
||
|
this.isReadyToPublish = true;
|
||
|
this.ee.emitEvent('stream-ready-to-publish');
|
||
|
return this.video;
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.removeVideo = function () {
|
||
|
if (this.video) {
|
||
|
if (document.getElementById(this.parentId)) {
|
||
|
document.getElementById(this.parentId).removeChild(this.video);
|
||
|
this.ee.emitEvent('video-removed', [this.video]);
|
||
|
}
|
||
|
delete this.video;
|
||
|
}
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.isSendAudio = function () {
|
||
|
return (!!this.outboundStreamOpts &&
|
||
|
this.outboundStreamOpts.publisherProperties.audioSource !== null &&
|
||
|
this.outboundStreamOpts.publisherProperties.audioSource !== false);
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.isSendVideo = function () {
|
||
|
return (!!this.outboundStreamOpts &&
|
||
|
this.outboundStreamOpts.publisherProperties.videoSource !== null &&
|
||
|
this.outboundStreamOpts.publisherProperties.videoSource !== false);
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.isSendScreen = function () {
|
||
|
return (!!this.outboundStreamOpts &&
|
||
|
this.outboundStreamOpts.publisherProperties.videoSource === 'screen');
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.emitEvent = function (type, eventArray) {
|
||
|
this.ee.emitEvent(type, eventArray);
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.setSpeechEventIfNotExists = function () {
|
||
|
if (!this.speechEvent) {
|
||
|
var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
|
||
|
harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
|
||
|
harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
|
||
|
this.speechEvent = kurentoUtils.WebRtcPeer.hark(this.mediaStream, harkOptions);
|
||
|
}
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.enableSpeakingEvents = function () {
|
||
|
var _this = this;
|
||
|
this.setSpeechEventIfNotExists();
|
||
|
this.speechEvent.on('speaking', function () {
|
||
|
_this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
|
||
|
});
|
||
|
this.speechEvent.on('stopped_speaking', function () {
|
||
|
_this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.enableOnceSpeakingEvents = function () {
|
||
|
var _this = this;
|
||
|
this.setSpeechEventIfNotExists();
|
||
|
this.speechEvent.on('speaking', function () {
|
||
|
_this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
|
||
|
_this.disableSpeakingEvents();
|
||
|
});
|
||
|
this.speechEvent.on('stopped_speaking', function () {
|
||
|
_this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
|
||
|
_this.disableSpeakingEvents();
|
||
|
});
|
||
|
};
|
||
|
/**
|
||
|
* @hidden
|
||
|
*/
|
||
|
Stream.prototype.disableSpeakingEvents = function () {
|
||
|
this.speechEvent.stop();
|
||
|
this.speechEvent = undefined;
|
||
|
};
|
||
|
/* Private methods */
|
||
|
Stream.prototype.initWebRtcPeerSend = function () {
|
||
|
var _this = this;
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
var userMediaConstraints = {
|
||
|
audio: _this.isSendAudio(),
|
||
|
video: _this.isSendVideo()
|
||
|
};
|
||
|
var options = {
|
||
|
videoStream: _this.mediaStream,
|
||
|
mediaConstraints: userMediaConstraints,
|
||
|
onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
|
||
|
iceServers: _this.session.openvidu.advancedConfiguration.iceServers
|
||
|
};
|
||
|
var successCallback = function (error, sdpOfferParam, wp) {
|
||
|
if (error) {
|
||
|
reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error)));
|
||
|
}
|
||
|
console.debug('Sending SDP offer to publish as '
|
||
|
+ _this.streamId, sdpOfferParam);
|
||
|
_this.session.openvidu.sendRequest('publishVideo', {
|
||
|
sdpOffer: sdpOfferParam,
|
||
|
doLoopback: _this.displayMyRemote() || false,
|
||
|
audioActive: _this.isSendAudio(),
|
||
|
videoActive: _this.isSendVideo(),
|
||
|
typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''),
|
||
|
frameRate: !!_this.frameRate ? _this.frameRate : -1
|
||
|
}, function (error, response) {
|
||
|
if (error) {
|
||
|
reject('Error on publishVideo: ' + JSON.stringify(error));
|
||
|
}
|
||
|
else {
|
||
|
_this.processSdpAnswer(response.sdpAnswer)
|
||
|
.then(function () {
|
||
|
_this.ee.emitEvent('stream-created-by-publisher');
|
||
|
resolve();
|
||
|
})["catch"](function (error) {
|
||
|
reject(error);
|
||
|
});
|
||
|
console.info("'Publisher' successfully published to session");
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
if (_this.displayMyRemote()) {
|
||
|
_this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function (err) {
|
||
|
if (err) {
|
||
|
reject(err);
|
||
|
}
|
||
|
_this.webRtcPeer.generateOffer(successCallback);
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
_this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, function (error) {
|
||
|
if (error) {
|
||
|
reject(error);
|
||
|
}
|
||
|
_this.webRtcPeer.generateOffer(successCallback);
|
||
|
});
|
||
|
}
|
||
|
_this.isPublisherPublished = true;
|
||
|
});
|
||
|
};
|
||
|
Stream.prototype.initWebRtcPeerReceive = function () {
|
||
|
var _this = this;
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
var offerConstraints = {
|
||
|
audio: _this.inboundStreamOpts.recvAudio,
|
||
|
video: _this.inboundStreamOpts.recvVideo
|
||
|
};
|
||
|
console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints);
|
||
|
var options = {
|
||
|
onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection),
|
||
|
mediaConstraints: offerConstraints
|
||
|
};
|
||
|
var successCallback = function (error, sdpOfferParam, wp) {
|
||
|
if (error) {
|
||
|
reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error)));
|
||
|
}
|
||
|
console.debug('Sending SDP offer to subscribe to '
|
||
|
+ _this.streamId, sdpOfferParam);
|
||
|
_this.session.openvidu.sendRequest('receiveVideoFrom', {
|
||
|
sender: _this.streamId,
|
||
|
sdpOffer: sdpOfferParam
|
||
|
}, function (error, response) {
|
||
|
if (error) {
|
||
|
reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
|
||
|
}
|
||
|
else {
|
||
|
_this.processSdpAnswer(response.sdpAnswer).then(function () {
|
||
|
resolve();
|
||
|
})["catch"](function (error) {
|
||
|
reject(error);
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
_this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) {
|
||
|
if (error) {
|
||
|
reject(error);
|
||
|
}
|
||
|
_this.webRtcPeer.generateOffer(successCallback);
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
Stream.prototype.processSdpAnswer = function (sdpAnswer) {
|
||
|
var _this = this;
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
var answer = new RTCSessionDescription({
|
||
|
type: 'answer',
|
||
|
sdp: sdpAnswer
|
||
|
});
|
||
|
console.debug(_this.streamId + ': set peer connection with recvd SDP answer', sdpAnswer);
|
||
|
var streamId = _this.streamId;
|
||
|
var peerConnection = _this.webRtcPeer.peerConnection;
|
||
|
peerConnection.setRemoteDescription(answer, function () {
|
||
|
// Avoids to subscribe to your own stream remotely
|
||
|
// except when showMyRemote is true
|
||
|
if (!_this.isLocal() || _this.displayMyRemote()) {
|
||
|
_this.mediaStream = peerConnection.getRemoteStreams()[0];
|
||
|
console.debug('Peer remote stream', _this.mediaStream);
|
||
|
if (!!_this.mediaStream) {
|
||
|
_this.ee.emitEvent('mediastream-updated');
|
||
|
if (!!_this.mediaStream.getAudioTracks()[0] && _this.session.speakingEventsEnabled) {
|
||
|
_this.enableSpeakingEvents();
|
||
|
}
|
||
|
}
|
||
|
if (!!_this.video) {
|
||
|
// let thumbnailId = this.video.thumb;
|
||
|
_this.video.oncanplay = function () {
|
||
|
if (_this.isLocal() && _this.displayMyRemote()) {
|
||
|
console.info("Your own remote 'Stream' with id [" + _this.streamId + '] video is now playing');
|
||
|
_this.ee.emitEvent('remote-video-is-playing', [{
|
||
|
element: _this.video
|
||
|
}]);
|
||
|
}
|
||
|
else if (!_this.isLocal() && !_this.displayMyRemote()) {
|
||
|
console.info("Remote 'Stream' with id [" + _this.streamId + '] video is now playing');
|
||
|
_this.ee.emitEvent('video-is-playing', [{
|
||
|
element: _this.video
|
||
|
}]);
|
||
|
}
|
||
|
// show(thumbnailId);
|
||
|
// this.hideSpinner(this.streamId);
|
||
|
};
|
||
|
}
|
||
|
_this.session.emitEvent('stream-subscribed', [{
|
||
|
stream: _this
|
||
|
}]);
|
||
|
}
|
||
|
_this.initWebRtcStats();
|
||
|
resolve();
|
||
|
}, function (error) {
|
||
|
reject(new Error(_this.streamId + ': Error setting SDP to the peer connection: ' + JSON.stringify(error)));
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
Stream.prototype.initWebRtcStats = function () {
|
||
|
this.webRtcStats = new WebRtcStats_1.WebRtcStats(this);
|
||
|
this.webRtcStats.initWebRtcStats();
|
||
|
};
|
||
|
Stream.prototype.stopWebRtcStats = function () {
|
||
|
if (!!this.webRtcStats && this.webRtcStats.isEnabled()) {
|
||
|
this.webRtcStats.stopWebRtcStats();
|
||
|
}
|
||
|
};
|
||
|
Stream.prototype.isLocal = function () {
|
||
|
// inbound options undefined and outbound options defined
|
||
|
return (!this.inboundStreamOpts && !!this.outboundStreamOpts);
|
||
|
};
|
||
|
Stream.prototype.insertElementWithMode = function (element, insertMode) {
|
||
|
if (!!this.targetElement) {
|
||
|
switch (insertMode) {
|
||
|
case VideoInsertMode_1.VideoInsertMode.AFTER:
|
||
|
this.targetElement.parentNode.insertBefore(element, this.targetElement.nextSibling);
|
||
|
break;
|
||
|
case VideoInsertMode_1.VideoInsertMode.APPEND:
|
||
|
this.targetElement.appendChild(element);
|
||
|
break;
|
||
|
case VideoInsertMode_1.VideoInsertMode.BEFORE:
|
||
|
this.targetElement.parentNode.insertBefore(element, this.targetElement);
|
||
|
break;
|
||
|
case VideoInsertMode_1.VideoInsertMode.PREPEND:
|
||
|
this.targetElement.insertBefore(element, this.targetElement.childNodes[0]);
|
||
|
break;
|
||
|
case VideoInsertMode_1.VideoInsertMode.REPLACE:
|
||
|
this.targetElement.parentNode.replaceChild(element, this.targetElement);
|
||
|
break;
|
||
|
default:
|
||
|
this.insertElementWithMode(element, VideoInsertMode_1.VideoInsertMode.APPEND);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
Stream.prototype.mirrorVideo = function (video) {
|
||
|
video.style.transform = 'rotateY(180deg)';
|
||
|
video.style.webkitTransform = 'rotateY(180deg)';
|
||
|
};
|
||
|
return Stream;
|
||
|
}());
|
||
|
exports.Stream = Stream;
|
||
|
//# sourceMappingURL=Stream.js.map
|