@techsee/techsee-media-service 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +1 -0
  2. package/lib/constants.js +20 -0
  3. package/lib/constants.js.map +1 -0
  4. package/lib/event-emitter.js +39 -0
  5. package/lib/event-emitter.js.map +1 -0
  6. package/lib/index.js +64 -0
  7. package/lib/index.js.map +1 -0
  8. package/lib/opentok/session.js +304 -0
  9. package/lib/opentok/session.js.map +1 -0
  10. package/lib/opentok/stream.js +310 -0
  11. package/lib/opentok/stream.js.map +1 -0
  12. package/lib/publisher.js +143 -0
  13. package/lib/publisher.js.map +1 -0
  14. package/lib/qos/raw-qos.js +319 -0
  15. package/lib/qos/raw-qos.js.map +1 -0
  16. package/lib/service.js +316 -0
  17. package/lib/service.js.map +1 -0
  18. package/lib/session.js +104 -0
  19. package/lib/session.js.map +1 -0
  20. package/lib/stream.js +195 -0
  21. package/lib/stream.js.map +1 -0
  22. package/lib/subscriber.js +90 -0
  23. package/lib/subscriber.js.map +1 -0
  24. package/lib/webrtc/constants.js +112 -0
  25. package/lib/webrtc/constants.js.map +1 -0
  26. package/lib/webrtc/helper.js +169 -0
  27. package/lib/webrtc/helper.js.map +1 -0
  28. package/lib/webrtc/session-kms.js +558 -0
  29. package/lib/webrtc/session-kms.js.map +1 -0
  30. package/lib/webrtc/session-loopback.js +340 -0
  31. package/lib/webrtc/session-loopback.js.map +1 -0
  32. package/lib/webrtc/session-turn.js +807 -0
  33. package/lib/webrtc/session-turn.js.map +1 -0
  34. package/lib/webrtc/session-turn.v2.js +2 -0
  35. package/lib/webrtc/session-turn.v2.js.map +1 -0
  36. package/lib/webrtc/session.js +40 -0
  37. package/lib/webrtc/session.js.map +1 -0
  38. package/lib/webrtc/stream.js +631 -0
  39. package/lib/webrtc/stream.js.map +1 -0
  40. package/lib/webrtc/temasys/adapter-loader.js +12 -0
  41. package/lib/webrtc/temasys/adapter-loader.js.map +1 -0
  42. package/lib/webrtc/temasys/adapter.js +5861 -0
  43. package/lib/webrtc/temasys/adapter.js.map +1 -0
  44. package/package.json +53 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["service.js"],"names":["environmentDetect","TsEnvironmentDetect","waitForTemasysPlugin","isIE11","AdapterJS","require","webRTCReady","isChrome","majorVersion","_isOTDefined","OT","e","_waitForOT","Promise","resolve","isDefined","reduce","Array","WAIT_FOR_OPENTOK_INITIALIZATION_MAX_ATTEMPTS","delay","WAIT_FOR_OPENTOK_INITIALIZATION_INTERVAL","then","reject","SERVICE_EVENTS","SESSION_CREATED","EXCEPTION","EVENTS","sessions","latestLocalStream","userMediaPromise","TsMediaService","_","assign","EventEmitter","createLocalMediaStream","constraints","videoTrack","getVideoTracks","length","readyState","destroyLocalMediaStream","navigator","mediaDevices","getUserMedia","stream","catch","err","getTracks","forEach","track","stop","getDevices","error","devices","enumerateDevices","isTemasysPluginAvailable","verifyPluginState","pluginNotInstalled","setTimeout","TEMASYS_PLUGIN_CHECK_INTERVAL","verifyCameraAccess","deviceOpts","initSession","isMobile","resolution","mediaServiceType","credentials","isLoopback","MEDIA_SERVICE_TYPES","MEDIASERVER","sessionOptions","tsMediaServer","audio","video","KMSWebRTCSession","TURNSERVER","WAIT_FOR_TEMASYS_PLUGIN_INITIALIZATION","creds","turnServer","opentok","LoopbackWebRTCSession","TurnWebRTCSession","bind","TsOpenTokSession","session","emit","push"],"mappings":"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","file":"service.js","sourcesContent":["import {EventEmitter} from './event-emitter';\nimport {KMSWebRTCSession, LoopbackWebRTCSession, TurnWebRTCSession} from './webrtc/session';\nimport {TsEnvironmentDetect} from 'techsee-common/lib/helpers/ts-environment-detect';\nimport {TsOpenTokSession} from './opentok/session';\nimport {getHighestResolutionStream} from './webrtc/helper';\n\nimport {\n MEDIA_SERVICE_TYPES,\n TEMASYS_PLUGIN_CHECK_INTERVAL,\n WAIT_FOR_OPENTOK_INITIALIZATION_INTERVAL,\n WAIT_FOR_OPENTOK_INITIALIZATION_MAX_ATTEMPTS,\n WAIT_FOR_TEMASYS_PLUGIN_INITIALIZATION\n} from './constants';\n\nconst environmentDetect = new TsEnvironmentDetect();\n\nlet waitForTemasysPlugin = false;\n\nif (environmentDetect.isIE11()) {\n waitForTemasysPlugin = true;\n\n const AdapterJS = require('./webrtc/temasys/adapter-loader')(); // eslint-disable-line global-require\n\n AdapterJS.webRTCReady(() => {\n waitForTemasysPlugin = false;\n });\n} else if (!(environmentDetect.isChrome() && (environmentDetect.majorVersion() < 49))) {\n require('webrtc-adapter/src/js/adapter_core'); // eslint-disable-line global-require\n}\n\nfunction _isOTDefined() {\n try {\n return !!OT;\n } catch (e) {\n return false;\n }\n}\n\nfunction _waitForOT() {\n if (_isOTDefined()) {\n return Promise.resolve();\n }\n\n let isDefined = false;\n\n return Promise.reduce(\n new Array(WAIT_FOR_OPENTOK_INITIALIZATION_MAX_ATTEMPTS),\n () => {\n if (isDefined || _isOTDefined()) {\n isDefined = true;\n\n return Promise.resolve();\n }\n\n return Promise.delay(WAIT_FOR_OPENTOK_INITIALIZATION_INTERVAL);\n }, 0)\n .then(() => isDefined || Promise.reject('OT is undefined'));\n}\n\n/**\n * @enum SERVICE_EVENTS\n */\nconst SERVICE_EVENTS = {\n SESSION_CREATED: 'SESSION_CREATED',\n EXCEPTION: 'EXCEPTION'\n};\n\nexport {SERVICE_EVENTS as EVENTS};\n\nconst sessions = [];\nlet latestLocalStream = null;\nlet userMediaPromise = null;\n\n/**\n * The top of hierarchy and the entry point of the TsMedia Service.\n *\n * @static\n * @class\n * @extends EventEmitter\n */\nexport const TsMediaService = _.assign(new EventEmitter(), {\n\n /**\n * All created sessoins\n *\n * @member { Object }\n * @memberof TsMediaService\n * @type { Array<TsMediaSession> }\n */\n get sessions() {\n return sessions;\n },\n\n createLocalMediaStream(constraints) {\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (latestLocalStream) {\n const videoTrack = latestLocalStream.getVideoTracks();\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve(latestLocalStream);\n } else {\n this.destroyLocalMediaStream();\n }\n }\n\n userMediaPromise = new Promise((resolve, reject) => {\n try {\n navigator.mediaDevices.getUserMedia(constraints)\n .then((stream) => {\n latestLocalStream = stream;\n userMediaPromise = null;\n resolve(stream);\n })\n .catch((err) => {\n userMediaPromise = null;\n reject(err);\n });\n } catch (e) {\n userMediaPromise = null;\n reject(e);\n }\n });\n\n return userMediaPromise;\n },\n\n destroyLocalMediaStream() {\n if (latestLocalStream) {\n latestLocalStream.getTracks().forEach((track) => {\n track.stop();\n });\n }\n\n latestLocalStream = null;\n },\n\n /**\n * Enumerate available media devices\n *\n * @method\n * @memberof TsMediaService\n * @returns { Promise<Array<MediaDeviceInfo>> } devices list\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo | MediaDeviceInfo documentation}\n */\n getDevices() {\n if ((typeof OT !== 'undefined') && OT && OT.getDevices) {\n return new Promise((resolve, reject) => {\n OT.getDevices((error, devices) => {\n if (error) {\n return reject(error);\n }\n\n return resolve(devices);\n });\n });\n }\n\n if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {\n return navigator.mediaDevices.enumerateDevices();\n }\n\n return Promise.reject('getDevices is not supported');\n },\n\n /**\n * Enumerate available media devices\n *\n * @method\n * @memberof TsMediaService\n * @returns { Promise<Array<MediaDeviceInfo>> } devices list\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo | MediaDeviceInfo documentation}\n */\n isTemasysPluginAvailable() {\n return new Promise((resolve) => {\n if (!AdapterJS) {\n return resolve(false);\n }\n\n const verifyPluginState = () => {\n if (waitForTemasysPlugin && !AdapterJS.pluginNotInstalled) {\n return setTimeout(verifyPluginState, TEMASYS_PLUGIN_CHECK_INTERVAL);\n }\n\n resolve(!AdapterJS.pluginNotInstalled);\n };\n\n setTimeout(verifyPluginState, TEMASYS_PLUGIN_CHECK_INTERVAL);\n });\n },\n\n /**\n * Verifies camera access\n *\n * @method\n * @memberof TsMediaService\n * @returns { Promise<Object> } returns {stream,constraints} if successful, or rejected promise if failed\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo | MediaDeviceInfo documentation}\n */\n verifyCameraAccess(deviceOpts) {\n return getHighestResolutionStream(deviceOpts);\n },\n\n /**\n * Init WebRTC or OpenTok session depends on required type.\n *\n * Returns an initialized specific implementation of TsMediaSession interface.\n *\n * Assuming mobile will be a publisher and not mobile will be a subscriber.\n *\n * @method\n * @memberof TsMediaService\n *\n * @param { OPENTOK|MEDIASERVER|TURNSERVER } mediaServiceType required implementation\n * @param { Boolean } isMobile Whether techsee-mobile or not calls this method.\n * @param { Object } resolution constraint to use for video stream\n * @param { opentok|tsMediaServer|turnServer } credentials server/service credentials\n * @param { Object } deviceOpts requested devices (mainly audio/video device ids)\n * @param { Boolean } isLoopback Whether to use loopback webrtc\n *\n * @returns { Promise<TsMediaSession> }\n */\n initSession({\n mediaServiceType,\n isMobile,\n resolution,\n credentials,\n deviceOpts,\n isLoopback\n } = {\n isMobile: false,\n resolution: '640x480'\n }) {\n return Promise.resolve()\n .then(() => {\n if (mediaServiceType === MEDIA_SERVICE_TYPES.MEDIASERVER) {\n //\n // KMS CONNECTION\n //\n return Promise.resolve()\n .then(() => {\n const sessionOptions = {\n isMobile,\n resolution,\n\n credentials: credentials.tsMediaServer,\n deviceOpts: deviceOpts || {audio: true, video: true}\n };\n\n return new KMSWebRTCSession(sessionOptions);\n });\n } else if (mediaServiceType === MEDIA_SERVICE_TYPES.TURNSERVER || isLoopback) {\n //\n // TURN-based connection or loopback (no connection)\n //\n return Promise.resolve()\n .then(() => {\n if (waitForTemasysPlugin) {\n return Promise.delay(WAIT_FOR_TEMASYS_PLUGIN_INITIALIZATION);\n }\n })\n .then(() => {\n if (waitForTemasysPlugin) {\n return Promise.reject('Temasys plugin has not yet been initialized, despite waiting a grace period');\n }\n\n let creds = null;\n\n if (!isLoopback) {\n creds = (mediaServiceType === MEDIA_SERVICE_TYPES.TURNSERVER) ? credentials.turnServer : credentials.opentok;\n }\n\n const sessionOptions = {\n isMobile,\n resolution,\n\n credentials: creds,\n deviceOpts: deviceOpts || {audio: true, video: true}\n };\n\n return (isLoopback)\n ? new LoopbackWebRTCSession(sessionOptions)\n : new TurnWebRTCSession(sessionOptions, this.createLocalMediaStream.bind(this));\n });\n }\n\n //\n // OT CONNECTION (default mediaServiceType)\n //\n return Promise.resolve()\n .then(() => _waitForOT())\n .then(() => {\n const sessionOptions = {\n isMobile,\n resolution,\n\n credentials: credentials.opentok\n };\n\n return new TsOpenTokSession(sessionOptions);\n });\n })\n .then((session) => {\n this.emit(SERVICE_EVENTS.SESSION_CREATED, session);\n\n sessions.push(session);\n\n return session;\n });\n }\n});\n"]}
package/lib/session.js ADDED
@@ -0,0 +1,104 @@
1
+ 'use strict';
2
+
3
+ exports.__esModule = true;
4
+ exports.TsMediaSession = exports.EVENTS = undefined;
5
+
6
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
7
+
8
+ var _eventEmitter = require('./event-emitter');
9
+
10
+ var _stream = require('./stream');
11
+
12
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
13
+
14
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
15
+
16
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
17
+
18
+ /**
19
+ * @enum SESSION_EVENTS
20
+ */
21
+ var SESSION_EVENTS = {
22
+ CONNECTED: 'CONNECTED',
23
+ DISCONNECTED: 'DISCONNECTED',
24
+ EXCEPTION: 'EXCEPTION',
25
+ STREAM_CREATED: 'STREAM_CREATED',
26
+ STREAM_DESTROYED: 'STREAM_DESTROYED',
27
+ STREAM_PROPERTY_CHANGED: 'STREAM_PROPERTY_CHANGED',
28
+ RECONNECT_TURN_SERVER: 'RECONNECT_TURN_SERVER',
29
+ TURN_SERVER_CONNECTION_FAILED: 'TURN_SERVER_CONNECTION_FAILED'
30
+ };
31
+
32
+ exports.EVENTS = SESSION_EVENTS;
33
+
34
+ /**
35
+ * Session object returned by TsMediaSercice.initSession() call.
36
+ * <br>
37
+ * Represents connection to OpenTok server or TsMediaServer.
38
+ * <br>
39
+ * General interface for the specific implementations - TsOpenTokSession and TsWebRTCSession
40
+ *
41
+ * @interface
42
+ * @extends EventEmitter
43
+ *
44
+ * @fires SESSION_EVENTS#CONNECTED
45
+ * @fires SESSION_EVENTS#DISCONNECTED
46
+ * @fires SESSION_EVENTS#EXCEPTION
47
+ * @fires SESSION_EVENTS#STREAM_CREATED
48
+ */
49
+
50
+ var TsMediaSession = exports.TsMediaSession = function (_EventEmitter) {
51
+ _inherits(TsMediaSession, _EventEmitter);
52
+
53
+ function TsMediaSession() {
54
+ _classCallCheck(this, TsMediaSession);
55
+
56
+ var _this = _possibleConstructorReturn(this, _EventEmitter.call(this));
57
+
58
+ _this._streams = new Map();
59
+
60
+ _this.on(SESSION_EVENTS.STREAM_PROPERTY_CHANGED, function (event) {
61
+ if (event.stream) {
62
+ event.stream.emit(_stream.EVENTS.PROPERTY_CHANGED, event);
63
+ }
64
+ });
65
+ return _this;
66
+ }
67
+
68
+ /**
69
+ * All media streams registered in the session.
70
+ *
71
+ * @member { Object }
72
+ * @type { Array<TsMediaStream> }
73
+ */
74
+
75
+
76
+ /**
77
+ * Register new media stream in the session.
78
+ *
79
+ * Called internally by TsMediaStream constructor.
80
+ *
81
+ * @method
82
+ * @param { String } id Stream id
83
+ * @param { TsMediaStream } stream Media Stream
84
+ */
85
+ TsMediaSession.prototype.registerStream = function registerStream(id, stream) {
86
+ this._streams.set(id, stream);
87
+ };
88
+
89
+ _createClass(TsMediaSession, [{
90
+ key: 'streams',
91
+ get: function get() {
92
+ var streamArray = [];
93
+
94
+ this._streams.forEach(function (stream) {
95
+ return streamArray.push(stream);
96
+ });
97
+
98
+ return streamArray;
99
+ }
100
+ }]);
101
+
102
+ return TsMediaSession;
103
+ }(_eventEmitter.EventEmitter);
104
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["session.js"],"names":["SESSION_EVENTS","CONNECTED","DISCONNECTED","EXCEPTION","STREAM_CREATED","STREAM_DESTROYED","STREAM_PROPERTY_CHANGED","RECONNECT_TURN_SERVER","TURN_SERVER_CONNECTION_FAILED","EVENTS","TsMediaSession","_streams","Map","on","event","stream","emit","STREAM_EVENTS","PROPERTY_CHANGED","registerStream","id","set","streamArray","forEach","push","EventEmitter"],"mappings":";;;;;;;AAAA;;AAEA;;;;;;;;AAEA;;;AAGA,IAAMA,iBAAiB;AACnBC,eAAW,WADQ;AAEnBC,kBAAc,cAFK;AAGnBC,eAAW,WAHQ;AAInBC,oBAAgB,gBAJG;AAKnBC,sBAAkB,kBALC;AAMnBC,6BAAyB,yBANN;AAOnBC,2BAAuB,uBAPJ;AAQnBC,mCAA+B;AARZ,CAAvB;;QAW2BC,M,GAAlBT,c;;AAET;;;;;;;;;;;;;;;;IAeaU,c,WAAAA,c;;;AACT,8BAAc;AAAA;;AAAA,qDACV,wBADU;;AAGV,cAAKC,QAAL,GAAgB,IAAIC,GAAJ,EAAhB;;AAEA,cAAKC,EAAL,CAAQb,eAAeM,uBAAvB,EAAgD,UAACQ,KAAD,EAAW;AACvD,gBAAIA,MAAMC,MAAV,EAAkB;AACdD,sBAAMC,MAAN,CAAaC,IAAb,CAAkBC,eAAcC,gBAAhC,EAAkDJ,KAAlD;AACH;AACJ,SAJD;AALU;AAUb;;AAED;;;;;;;;AAcA;;;;;;;;;6BASAK,c,2BAAeC,E,EAAIL,M,EAAQ;AACvB,aAAKJ,QAAL,CAAcU,GAAd,CAAkBD,EAAlB,EAAsBL,MAAtB;AACH,K;;;;4BAnBa;AACV,gBAAMO,cAAc,EAApB;;AAEA,iBAAKX,QAAL,CAAcY,OAAd,CAAsB,UAACR,MAAD;AAAA,uBAAYO,YAAYE,IAAZ,CAAiBT,MAAjB,CAAZ;AAAA,aAAtB;;AAEA,mBAAOO,WAAP;AACH;;;;EAzB+BG,0B","file":"session.js","sourcesContent":["import { EventEmitter } from './event-emitter';\n\nimport { EVENTS as STREAM_EVENTS } from './stream';\n\n/**\n * @enum SESSION_EVENTS\n */\nconst SESSION_EVENTS = {\n CONNECTED: 'CONNECTED',\n DISCONNECTED: 'DISCONNECTED',\n EXCEPTION: 'EXCEPTION',\n STREAM_CREATED: 'STREAM_CREATED',\n STREAM_DESTROYED: 'STREAM_DESTROYED',\n STREAM_PROPERTY_CHANGED: 'STREAM_PROPERTY_CHANGED',\n RECONNECT_TURN_SERVER: 'RECONNECT_TURN_SERVER',\n TURN_SERVER_CONNECTION_FAILED: 'TURN_SERVER_CONNECTION_FAILED'\n};\n\nexport { SESSION_EVENTS as EVENTS };\n\n/**\n * Session object returned by TsMediaSercice.initSession() call.\n * <br>\n * Represents connection to OpenTok server or TsMediaServer.\n * <br>\n * General interface for the specific implementations - TsOpenTokSession and TsWebRTCSession\n *\n * @interface\n * @extends EventEmitter\n *\n * @fires SESSION_EVENTS#CONNECTED\n * @fires SESSION_EVENTS#DISCONNECTED\n * @fires SESSION_EVENTS#EXCEPTION\n * @fires SESSION_EVENTS#STREAM_CREATED\n */\nexport class TsMediaSession extends EventEmitter {\n constructor() {\n super();\n\n this._streams = new Map();\n\n this.on(SESSION_EVENTS.STREAM_PROPERTY_CHANGED, (event) => {\n if (event.stream) {\n event.stream.emit(STREAM_EVENTS.PROPERTY_CHANGED, event);\n }\n });\n }\n\n /**\n * All media streams registered in the session.\n *\n * @member { Object }\n * @type { Array<TsMediaStream> }\n */\n get streams() {\n const streamArray = [];\n\n this._streams.forEach((stream) => streamArray.push(stream));\n\n return streamArray;\n }\n\n /**\n * Register new media stream in the session.\n *\n * Called internally by TsMediaStream constructor.\n *\n * @method\n * @param { String } id Stream id\n * @param { TsMediaStream } stream Media Stream\n */\n registerStream(id, stream) {\n this._streams.set(id, stream);\n }\n}\n\n"]}
package/lib/stream.js ADDED
@@ -0,0 +1,195 @@
1
+ 'use strict';
2
+
3
+ exports.__esModule = true;
4
+ exports.TsMediaStream = exports.EVENTS = undefined;
5
+
6
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
7
+
8
+ var _eventEmitter = require('./event-emitter');
9
+
10
+ var _session = require('./session');
11
+
12
+ var _subscriber = require('./subscriber');
13
+
14
+ var _tsEnvironmentDetect = require('techsee-common/lib/helpers/ts-environment-detect');
15
+
16
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
17
+
18
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
19
+
20
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
21
+
22
+ /**
23
+ * @enum STREAM_EVENTS
24
+ */
25
+ var STREAM_EVENTS = {
26
+ PROPERTY_CHANGED: 'PROPERTY_CHANGED'
27
+ };
28
+
29
+ exports.EVENTS = STREAM_EVENTS;
30
+
31
+ /**
32
+ * Media stream wrapper.
33
+ *
34
+ * Represents video or audio stream, local or remote.
35
+ *
36
+ * General interface for the specific implementations - TsOpenTokStream or TsWebRTCStream
37
+ *
38
+ * @interface
39
+ *
40
+ * @see TsOpenTokStream
41
+ * @see TsWebRTCStream
42
+ */
43
+
44
+ var TsMediaStream = exports.TsMediaStream = function (_EventEmitter) {
45
+ _inherits(TsMediaStream, _EventEmitter);
46
+
47
+ function TsMediaStream(id, session) {
48
+ var isRemote = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
49
+ var videoTrackSettings = arguments[3];
50
+
51
+ _classCallCheck(this, TsMediaStream);
52
+
53
+ var _this = _possibleConstructorReturn(this, _EventEmitter.call(this));
54
+
55
+ session.registerStream(id, _this);
56
+ _this.remote = isRemote;
57
+
58
+ if (videoTrackSettings) {
59
+ _this._width = videoTrackSettings.width;
60
+ _this._height = videoTrackSettings.height;
61
+ }
62
+
63
+ /**
64
+ * Environment detector
65
+ *
66
+ * @protected
67
+ * @member { Object }
68
+ */
69
+ _this._environment = new _tsEnvironmentDetect.TsEnvironmentDetect();
70
+ return _this;
71
+ }
72
+
73
+ /**
74
+ * Stream video dimensions
75
+ *
76
+ * @member { Object }
77
+ * @type { Object }
78
+ */
79
+
80
+
81
+ TsMediaStream.prototype._updateVideoDimensions = function _updateVideoDimensions(videoEl) {
82
+ if (videoEl) {
83
+ this._width = videoEl.videoWidth;
84
+ this._height = videoEl.videoHeight;
85
+
86
+ var stream = this;
87
+ var property = 'videoDimensions';
88
+ var value = this.videoDimensions;
89
+
90
+ this._session.emit(_session.EVENTS.STREAM_PROPERTY_CHANGED, { stream: stream, property: property, value: value });
91
+ }
92
+ };
93
+
94
+ TsMediaStream.prototype.setupDimensionsListener = function setupDimensionsListener(videoEl, subscriber) {
95
+ var _this2 = this;
96
+
97
+ this._clearUpdateDimensionsInterval();
98
+
99
+ this._width = videoEl.videoWidth;
100
+ this._height = videoEl.videoHeight;
101
+
102
+ if (!subscriber && !this._environment.isIE11() && !this._environment.isIOS()) {
103
+ $(videoEl).on('resize', function () {
104
+ return _this2._updateVideoDimensions(videoEl);
105
+ });
106
+ } else {
107
+ this.intervalId = setInterval(function () {
108
+ if (subscriber && !(subscriber.stream && subscriber.stream.hasVideo)) {
109
+ return;
110
+ }
111
+
112
+ if (_this2._width !== videoEl.videoWidth || _this2._height !== videoEl.videoHeight) {
113
+ _this2._updateVideoDimensions(videoEl);
114
+ }
115
+ }, 500);
116
+ }
117
+
118
+ if (subscriber && this.intervalId) {
119
+ subscriber.on(_subscriber.EVENTS.DESTROYED, function () {
120
+ _this2._clearUpdateDimensionsInterval();
121
+ });
122
+ }
123
+ };
124
+
125
+ TsMediaStream.prototype._clearUpdateDimensionsInterval = function _clearUpdateDimensionsInterval() {
126
+ if (this.intervalId) {
127
+ clearInterval(this.intervalId);
128
+
129
+ this.intervalId = null;
130
+ }
131
+ };
132
+
133
+ /* eslint-disable no-unused-vars */
134
+ /**
135
+ * Get snapshot of the current frame in the media stream
136
+ *
137
+ * Used internally in (TsMediaPublisher | TsMediaSubscriber).getSnapshot
138
+ *
139
+ * @method
140
+ * @param { TsMediaPublisher | TsMediaSubscriber } tsMediaElement
141
+ * @param { Number } timeout Usually used in IE. Time between video element transformation and snapshot.
142
+ * @param { Object } options
143
+ * format: Output MIME type (image/png or image/jpeg; default: image/png).
144
+ * quality: Output quality (between 0 and 1; default: 0.92; applies only when the format is image/jpeg).
145
+ * x: The x coordinate of the crop starting position.
146
+ * y: The y coordinate of the crop starting position.
147
+ * w: Crop width.
148
+ * h: Crop Height.
149
+ *
150
+ * @returns { Promise<String> } snapshot
151
+ */
152
+
153
+
154
+ TsMediaStream.prototype.getSnapshot = function getSnapshot(tsMediaElement) {
155
+ var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
156
+
157
+ var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
158
+ _ref$format = _ref.format,
159
+ format = _ref$format === undefined ? 'image/png' : _ref$format,
160
+ _ref$quality = _ref.quality,
161
+ quality = _ref$quality === undefined ? 0.92 : _ref$quality,
162
+ x = _ref.x,
163
+ y = _ref.y,
164
+ w = _ref.w,
165
+ h = _ref.h;
166
+
167
+ throw new TypeError('The method \'getSnapshot\' is not implemented');
168
+ };
169
+
170
+ TsMediaStream.prototype.turnFlashlight = function turnFlashlight() {
171
+ var isTorchOn = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
172
+
173
+ throw new TypeError('The method \'turnFlashlight\' is not implemented');
174
+ };
175
+
176
+ TsMediaStream.prototype.setAutoLightOffTimer = function setAutoLightOffTimer(flashlightTimeout) {
177
+ throw new TypeError('The method \'setAutoLightOffTimer\' is not implemented');
178
+ };
179
+
180
+ /* eslint-enable no-unused-vars */
181
+
182
+
183
+ _createClass(TsMediaStream, [{
184
+ key: 'videoDimensions',
185
+ get: function get() {
186
+ // FIXME the fallback dimensions should be removed, and the Opentok/Webrtc implementations
187
+ // should pass the dimensions just like loopback does. I suspect current behavior is
188
+ // the cause of the video element "jumping" (change size) on initial connection
189
+ return { width: this._width || 480, height: this._height || 640 };
190
+ }
191
+ }]);
192
+
193
+ return TsMediaStream;
194
+ }(_eventEmitter.EventEmitter);
195
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["stream.js"],"names":["STREAM_EVENTS","PROPERTY_CHANGED","EVENTS","TsMediaStream","id","session","isRemote","videoTrackSettings","registerStream","remote","_width","width","_height","height","_environment","TsEnvironmentDetect","_updateVideoDimensions","videoEl","videoWidth","videoHeight","stream","property","value","videoDimensions","_session","emit","SESSION_EVENTS","STREAM_PROPERTY_CHANGED","setupDimensionsListener","subscriber","_clearUpdateDimensionsInterval","isIE11","isIOS","$","on","intervalId","setInterval","hasVideo","SUBSCRIBER_EVENTS","DESTROYED","clearInterval","getSnapshot","tsMediaElement","timeout","format","quality","x","y","w","h","TypeError","turnFlashlight","isTorchOn","setAutoLightOffTimer","flashlightTimeout","EventEmitter"],"mappings":"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","file":"stream.js","sourcesContent":["import {EventEmitter} from './event-emitter';\n\nimport {\n EVENTS as SESSION_EVENTS\n} from './session';\n\nimport {\n EVENTS as SUBSCRIBER_EVENTS\n} from './subscriber';\n\nimport {TsEnvironmentDetect} from 'techsee-common/lib/helpers/ts-environment-detect';\n\n/**\n * @enum STREAM_EVENTS\n */\nconst STREAM_EVENTS = {\n PROPERTY_CHANGED: 'PROPERTY_CHANGED'\n};\n\nexport {STREAM_EVENTS as EVENTS};\n\n/**\n * Media stream wrapper.\n *\n * Represents video or audio stream, local or remote.\n *\n * General interface for the specific implementations - TsOpenTokStream or TsWebRTCStream\n *\n * @interface\n *\n * @see TsOpenTokStream\n * @see TsWebRTCStream\n */\nexport class TsMediaStream extends EventEmitter {\n constructor(id, session, isRemote = true, videoTrackSettings) {\n super();\n\n session.registerStream(id, this);\n this.remote = isRemote;\n\n if (videoTrackSettings) {\n this._width = videoTrackSettings.width;\n this._height = videoTrackSettings.height;\n }\n\n /**\n * Environment detector\n *\n * @protected\n * @member { Object }\n */\n this._environment = new TsEnvironmentDetect();\n }\n\n /**\n * Stream video dimensions\n *\n * @member { Object }\n * @type { Object }\n */\n get videoDimensions() {\n // FIXME the fallback dimensions should be removed, and the Opentok/Webrtc implementations\n // should pass the dimensions just like loopback does. I suspect current behavior is\n // the cause of the video element \"jumping\" (change size) on initial connection\n return {width: this._width || 480, height: this._height || 640};\n }\n\n _updateVideoDimensions(videoEl) {\n if (videoEl) {\n this._width = videoEl.videoWidth;\n this._height = videoEl.videoHeight;\n\n const stream = this;\n const property = 'videoDimensions';\n const value = this.videoDimensions;\n\n this._session.emit(SESSION_EVENTS.STREAM_PROPERTY_CHANGED, {stream, property, value});\n }\n }\n\n setupDimensionsListener(videoEl, subscriber) {\n this._clearUpdateDimensionsInterval();\n\n this._width = videoEl.videoWidth;\n this._height = videoEl.videoHeight;\n\n if (!subscriber && !this._environment.isIE11() && !this._environment.isIOS()) {\n $(videoEl).on('resize', () => this._updateVideoDimensions(videoEl));\n } else {\n this.intervalId = setInterval(() => {\n if (subscriber && !(subscriber.stream && subscriber.stream.hasVideo)) {\n return;\n }\n\n if (this._width !== videoEl.videoWidth || this._height !== videoEl.videoHeight) {\n this._updateVideoDimensions(videoEl);\n }\n }, 500);\n }\n\n if (subscriber && this.intervalId) {\n subscriber.on(SUBSCRIBER_EVENTS.DESTROYED, () => {\n this._clearUpdateDimensionsInterval();\n });\n }\n }\n\n _clearUpdateDimensionsInterval() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n\n this.intervalId = null;\n }\n }\n\n /* eslint-disable no-unused-vars */\n /**\n * Get snapshot of the current frame in the media stream\n *\n * Used internally in (TsMediaPublisher | TsMediaSubscriber).getSnapshot\n *\n * @method\n * @param { TsMediaPublisher | TsMediaSubscriber } tsMediaElement\n * @param { Number } timeout Usually used in IE. Time between video element transformation and snapshot.\n * @param { Object } options\n * format: Output MIME type (image/png or image/jpeg; default: image/png).\n * quality: Output quality (between 0 and 1; default: 0.92; applies only when the format is image/jpeg).\n * x: The x coordinate of the crop starting position.\n * y: The y coordinate of the crop starting position.\n * w: Crop width.\n * h: Crop Height.\n *\n * @returns { Promise<String> } snapshot\n */\n getSnapshot(tsMediaElement, timeout = 0, {format = 'image/png', quality = 0.92, x, y, w, h} = {}) {\n throw new TypeError('The method \\'getSnapshot\\' is not implemented');\n }\n\n turnFlashlight(isTorchOn = true) {\n throw new TypeError('The method \\'turnFlashlight\\' is not implemented');\n }\n\n setAutoLightOffTimer(flashlightTimeout) {\n throw new TypeError('The method \\'setAutoLightOffTimer\\' is not implemented');\n }\n\n /* eslint-enable no-unused-vars */\n}\n\n"]}
@@ -0,0 +1,90 @@
1
+ 'use strict';
2
+
3
+ exports.__esModule = true;
4
+ exports.TsMediaSubscriber = exports.EVENTS = undefined;
5
+
6
+ var _eventEmitter = require('./event-emitter');
7
+
8
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
9
+
10
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
11
+
12
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
13
+
14
+ /**
15
+ * @enum SUBSCRIBER_EVENTS
16
+ */
17
+ var SUBSCRIBER_EVENTS = {
18
+ DESTROYED: 'DESTROYED',
19
+ DISCONNECTED: 'DISCONNECTED'
20
+ };
21
+
22
+ exports.EVENTS = SUBSCRIBER_EVENTS;
23
+
24
+ /**
25
+ * Subscriber object represents subscription to a media stream.
26
+ *
27
+ * Exposes session and stream wrapper methods specific for media subscription.
28
+ *
29
+ * Instance is returned by TsMediaStream.subscribe() call
30
+ *
31
+ * @class
32
+ *
33
+ * @see TsMediaStream
34
+ */
35
+
36
+ var TsMediaSubscriber = exports.TsMediaSubscriber = function (_EventEmitter) {
37
+ _inherits(TsMediaSubscriber, _EventEmitter);
38
+
39
+ function TsMediaSubscriber(data) {
40
+ _classCallCheck(this, TsMediaSubscriber);
41
+
42
+ var _this = _possibleConstructorReturn(this, _EventEmitter.call(this));
43
+
44
+ _.assign(_this, data);
45
+ return _this;
46
+ }
47
+
48
+ /**
49
+ * Unsubscribe from the media stream and destroy subscriber's view
50
+ *
51
+ * @method
52
+ */
53
+
54
+
55
+ TsMediaSubscriber.prototype.destroy = function destroy() {
56
+ return this.stream.destroySubscriber(this);
57
+ };
58
+
59
+ /**
60
+ * Get snapshot of the current frame in the media stream
61
+ *
62
+ * @method
63
+ * @param { Number } timeout Usually used in IE.
64
+ * Time between video element transformation and snapshot.
65
+ *
66
+ * @param { Object } options Snapshot options: format, quality and crop positions
67
+ *
68
+ * @returns { Promise<String> } snapshot
69
+ */
70
+
71
+
72
+ TsMediaSubscriber.prototype.getSnapshot = function getSnapshot(timeout, options) {
73
+ return this.stream.getSnapshot(this, timeout, options);
74
+ };
75
+
76
+ /**
77
+ * Get statistics of the media subscription like bytes received.
78
+ *
79
+ * @method
80
+ * @returns { Promise<ToBeDefined> } stats
81
+ */
82
+
83
+
84
+ TsMediaSubscriber.prototype.getStats = function getStats() {
85
+ return this.stream.getStats(this);
86
+ };
87
+
88
+ return TsMediaSubscriber;
89
+ }(_eventEmitter.EventEmitter);
90
+ //# sourceMappingURL=subscriber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["subscriber.js"],"names":["SUBSCRIBER_EVENTS","DESTROYED","DISCONNECTED","EVENTS","TsMediaSubscriber","data","_","assign","destroy","stream","destroySubscriber","getSnapshot","timeout","options","getStats","EventEmitter"],"mappings":";;;;;AAAA;;;;;;;;AAEA;;;AAGA,IAAMA,oBAAoB;AACtBC,eAAW,WADW;AAEtBC,kBAAc;AAFQ,CAA1B;;QAK8BC,M,GAArBH,iB;;AAET;;;;;;;;;;;;IAWaI,iB,WAAAA,iB;;;AACT,+BAAYC,IAAZ,EAAkB;AAAA;;AAAA,qDACd,wBADc;;AAGdC,UAAEC,MAAF,QAAeF,IAAf;AAHc;AAIjB;;AAED;;;;;;;gCAKAG,O,sBAAU;AACN,eAAO,KAAKC,MAAL,CAAYC,iBAAZ,CAA8B,IAA9B,CAAP;AACH,K;;AAED;;;;;;;;;;;;;gCAWAC,W,wBAAYC,O,EAASC,O,EAAS;AAC1B,eAAO,KAAKJ,MAAL,CAAYE,WAAZ,CAAwB,IAAxB,EAA8BC,OAA9B,EAAuCC,OAAvC,CAAP;AACH,K;;AAED;;;;;;;;gCAMAC,Q,uBAAW;AACP,eAAO,KAAKL,MAAL,CAAYK,QAAZ,CAAqB,IAArB,CAAP;AACH,K;;;EAvCkCC,0B","file":"subscriber.js","sourcesContent":["import { EventEmitter } from './event-emitter';\n\n/**\n * @enum SUBSCRIBER_EVENTS\n */\nconst SUBSCRIBER_EVENTS = {\n DESTROYED: 'DESTROYED',\n DISCONNECTED: 'DISCONNECTED',\n};\n\nexport { SUBSCRIBER_EVENTS as EVENTS };\n\n/**\n * Subscriber object represents subscription to a media stream.\n *\n * Exposes session and stream wrapper methods specific for media subscription.\n *\n * Instance is returned by TsMediaStream.subscribe() call\n *\n * @class\n *\n * @see TsMediaStream\n */\nexport class TsMediaSubscriber extends EventEmitter {\n constructor(data) {\n super();\n\n _.assign(this, data);\n }\n\n /**\n * Unsubscribe from the media stream and destroy subscriber's view\n *\n * @method\n */\n destroy() {\n return this.stream.destroySubscriber(this);\n }\n\n /**\n * Get snapshot of the current frame in the media stream\n *\n * @method\n * @param { Number } timeout Usually used in IE.\n * Time between video element transformation and snapshot.\n *\n * @param { Object } options Snapshot options: format, quality and crop positions\n *\n * @returns { Promise<String> } snapshot\n */\n getSnapshot(timeout, options) {\n return this.stream.getSnapshot(this, timeout, options);\n }\n\n /**\n * Get statistics of the media subscription like bytes received.\n *\n * @method\n * @returns { Promise<ToBeDefined> } stats\n */\n getStats() {\n return this.stream.getStats(this);\n }\n}\n\n"]}
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ exports.__esModule = true;
4
+ var SOCKET_EVENTS = exports.SOCKET_EVENTS = {
5
+ OUTGOING: {
6
+ // Emitted to a peer, offering an ICE candidate
7
+ ICE_CANDIDATE: 'onIceCandidate',
8
+
9
+ //
10
+ // KMS Events
11
+ //
12
+
13
+ // Initial event, sent by pub/sub as a request to create/join a pipeline
14
+ JOIN_PIPELINE: 'joinPipeline',
15
+
16
+ // Final event, sent by pub/sub as a request to destroy a pipeline, or response to PIPELINE_DESTROYED event
17
+ DESTROY_PIPELINE: 'destroyPipeline',
18
+
19
+ //
20
+ // TURN Events
21
+ //
22
+
23
+ // Initial event, sent by pub/sub as a request to create/join a room
24
+ JOIN_ROOM: 'joinRoom',
25
+
26
+ // Sent by publisher, as a response to an SDP offer request (SEND_OFFER)
27
+ SDP_OFFER: 'sdpOfferSend',
28
+
29
+ // An SDP response (emitted after receiving an SDP offer)
30
+ SDP_ANSWER: 'sdpAnswerSend'
31
+ },
32
+ INCOMING: {
33
+ // In TURN - Received by a publisher, as a response to an SDP_ANSWER sent by a subscriber
34
+ // In KMS - Received after JOIN_PIPELINE is processed
35
+ JOIN_RESPONSE: 'joinResponse', // This event is received by a publisher, when the sig server receive an SDP answer from subscriber
36
+
37
+ // An incoming ICE candidate sent by a peer
38
+ ICE_CANDIDATE: 'iceCandidate',
39
+
40
+ // An error occured in the signaling server
41
+ ERROR: 'errorOccured',
42
+
43
+ //
44
+ // KMS Events
45
+ //
46
+
47
+ // KMS pipeline was destroyed, in response we do a cleanup
48
+ PIPELINE_DESTROYED: 'pipelineDestroyed',
49
+
50
+ //
51
+ // TURN Events
52
+ //
53
+
54
+ // Received by a publisher (sent by signaling server when a peer joining a room)
55
+ SEND_OFFER: 'sendOffer',
56
+
57
+ // Recieved by a subscriber when publisher sent an SDP offer
58
+ SDP_OFFER: 'sdpOfferRecv',
59
+
60
+ // Recieved by all subscribers, when the publisher has reconnected
61
+ PUBLISHER_RECONNECT: 'publisherReconnect',
62
+
63
+ // Recieved by the publisher, when a subscriber has disconnected
64
+ PEER_DISCONNECTED: 'peerDisconnected'
65
+ }
66
+ };
67
+
68
+ // KMS - Pipeline types
69
+ var PIPELINE_TYPES = exports.PIPELINE_TYPES = {
70
+ AUDIO_VIDEO_TO_SUBSCRIBERS: 'AudioVideoToSub',
71
+ AUDIO_VIDEO_TO_SUBSCRIBERS_WITH_SMART: 'AudioVideoToSubWithSmart'
72
+ };
73
+
74
+ var CLIENT_TYPES = exports.CLIENT_TYPES = {
75
+ PUBLISHER: 'publisher',
76
+ SUBSCRIBER: 'subscriber'
77
+ };
78
+
79
+ var PEER_CONNECTION_TYPES = exports.PEER_CONNECTION_TYPES = {
80
+ SEND_ONLY: 'WebRtcPeerSendonly',
81
+ RECV_ONLY: 'WebRtcPeerRecvonly',
82
+ SEND_RECV: 'WebRtcPeerSendrecv'
83
+ };
84
+
85
+ // Used to store the peer unique identifier (UID)
86
+ var COOKIES = exports.COOKIES = {
87
+ UID: 'media-client.uid'
88
+ };
89
+
90
+ var DEFAULT_STREAM_NAMES = exports.DEFAULT_STREAM_NAMES = {
91
+ MOBILE_CLIENT_VIDEO_STREAM: 'MOBILE_CLIENT_VIDEO_STREAM',
92
+ MOBILE_CLIENT_AUDIO_STREAM: 'MOBILE_CLIENT_AUDIO_STREAM',
93
+ DASHBOARD_AUDIO_STREAM: 'DASHBOARD_AUDIO_STREAM'
94
+ };
95
+
96
+ // When ICE exchange fail, an interval between reconnection attempts
97
+ var RECONNECT_TURN_SERVER_INTERVAL = exports.RECONNECT_TURN_SERVER_INTERVAL = 1000;
98
+
99
+ // When ICE exchange start, this is the timeout until the connection is deemed failed
100
+ var FAILED_CONNECTING_TURN_SERVER_INTERVAL = exports.FAILED_CONNECTING_TURN_SERVER_INTERVAL = 15000;
101
+
102
+ // Grace to to wait before creating a publisher, if peer connection has not been created yet
103
+ var WAIT_FOR_PC_INTERVAL = exports.WAIT_FOR_PC_INTERVAL = 2000;
104
+
105
+ // Interval between checks of video publishing ability attempts
106
+ var PUBLISH_APPROVAL_CHECK_INTERVAL = exports.PUBLISH_APPROVAL_CHECK_INTERVAL = 1000;
107
+
108
+ var SOCKET_RECONNECTION_DELAY = exports.SOCKET_RECONNECTION_DELAY = 3000,
109
+ SOCKET_RECONNECTION_DELAY_MAX = exports.SOCKET_RECONNECTION_DELAY_MAX = 6000,
110
+ SOCKET_RECONNECTION_ATTEMPTS = exports.SOCKET_RECONNECTION_ATTEMPTS = 100,
111
+ SOCKET_PATH = exports.SOCKET_PATH = '/socket2.io';
112
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["webrtc/constants.js"],"names":["SOCKET_EVENTS","OUTGOING","ICE_CANDIDATE","JOIN_PIPELINE","DESTROY_PIPELINE","JOIN_ROOM","SDP_OFFER","SDP_ANSWER","INCOMING","JOIN_RESPONSE","ERROR","PIPELINE_DESTROYED","SEND_OFFER","PUBLISHER_RECONNECT","PEER_DISCONNECTED","PIPELINE_TYPES","AUDIO_VIDEO_TO_SUBSCRIBERS","AUDIO_VIDEO_TO_SUBSCRIBERS_WITH_SMART","CLIENT_TYPES","PUBLISHER","SUBSCRIBER","PEER_CONNECTION_TYPES","SEND_ONLY","RECV_ONLY","SEND_RECV","COOKIES","UID","DEFAULT_STREAM_NAMES","MOBILE_CLIENT_VIDEO_STREAM","MOBILE_CLIENT_AUDIO_STREAM","DASHBOARD_AUDIO_STREAM","RECONNECT_TURN_SERVER_INTERVAL","FAILED_CONNECTING_TURN_SERVER_INTERVAL","WAIT_FOR_PC_INTERVAL","PUBLISH_APPROVAL_CHECK_INTERVAL","SOCKET_RECONNECTION_DELAY","SOCKET_RECONNECTION_DELAY_MAX","SOCKET_RECONNECTION_ATTEMPTS","SOCKET_PATH"],"mappings":";;;AAAO,IAAMA,wCAAgB;AACzBC,cAAU;AACN;AACAC,uBAAe,gBAFT;;AAIN;AACA;AACA;;AAEA;AACAC,uBAAe,cATT;;AAWN;AACAC,0BAAkB,iBAZZ;;AAcN;AACA;AACA;;AAEA;AACAC,mBAAW,UAnBL;;AAqBN;AACAC,mBAAW,cAtBL;;AAwBN;AACAC,oBAAY;AAzBN,KADe;AA4BzBC,cAAU;AACN;AACA;AACAC,uBAAe,cAHT,EAGyB;;AAE/B;AACAP,uBAAe,cANT;;AAQN;AACAQ,eAAO,cATD;;AAWN;AACA;AACA;;AAEA;AACAC,4BAAoB,mBAhBd;;AAkBN;AACA;AACA;;AAEA;AACAC,oBAAY,WAvBN;;AAyBN;AACAN,mBAAW,cA1BL;;AA4BN;AACAO,6BAAqB,oBA7Bf;;AA+BN;AACAC,2BAAmB;AAhCb;AA5Be,CAAtB;;AAgEP;AACO,IAAMC,0CAAiB;AAC1BC,gCAA4B,iBADF;AAE1BC,2CAAuC;AAFb,CAAvB;;AAKA,IAAMC,sCAAe;AACxBC,eAAW,WADa;AAExBC,gBAAY;AAFY,CAArB;;AAKA,IAAMC,wDAAwB;AACjCC,eAAW,oBADsB;AAEjCC,eAAW,oBAFsB;AAGjCC,eAAW;AAHsB,CAA9B;;AAMP;AACO,IAAMC,4BAAU;AACnBC,SAAK;AADc,CAAhB;;AAIA,IAAMC,sDAAuB;AAChCC,gCAA4B,4BADI;AAEhCC,gCAA4B,4BAFI;AAGhCC,4BAAwB;AAHQ,CAA7B;;AAMP;AACO,IAAMC,0EAAiC,IAAvC;;AAEP;AACO,IAAMC,0FAAyC,KAA/C;;AAEP;AACO,IAAMC,sDAAuB,IAA7B;;AAEP;AACO,IAAMC,4EAAkC,IAAxC;;AAEA,IAAMC,gEAA4B,IAAlC;AAAA,IACHC,wEAAgC,IAD7B;AAAA,IAEHC,sEAA+B,GAF5B;AAAA,IAGHC,oCAAc,aAHX","file":"constants.js","sourcesContent":["export const SOCKET_EVENTS = {\n OUTGOING: {\n // Emitted to a peer, offering an ICE candidate\n ICE_CANDIDATE: 'onIceCandidate',\n\n //\n // KMS Events\n //\n\n // Initial event, sent by pub/sub as a request to create/join a pipeline\n JOIN_PIPELINE: 'joinPipeline',\n\n // Final event, sent by pub/sub as a request to destroy a pipeline, or response to PIPELINE_DESTROYED event\n DESTROY_PIPELINE: 'destroyPipeline',\n\n //\n // TURN Events\n //\n\n // Initial event, sent by pub/sub as a request to create/join a room\n JOIN_ROOM: 'joinRoom',\n\n // Sent by publisher, as a response to an SDP offer request (SEND_OFFER)\n SDP_OFFER: 'sdpOfferSend',\n\n // An SDP response (emitted after receiving an SDP offer)\n SDP_ANSWER: 'sdpAnswerSend',\n },\n INCOMING: {\n // In TURN - Received by a publisher, as a response to an SDP_ANSWER sent by a subscriber\n // In KMS - Received after JOIN_PIPELINE is processed\n JOIN_RESPONSE: 'joinResponse', // This event is received by a publisher, when the sig server receive an SDP answer from subscriber\n\n // An incoming ICE candidate sent by a peer\n ICE_CANDIDATE: 'iceCandidate',\n\n // An error occured in the signaling server\n ERROR: 'errorOccured',\n\n //\n // KMS Events\n //\n\n // KMS pipeline was destroyed, in response we do a cleanup\n PIPELINE_DESTROYED: 'pipelineDestroyed',\n\n //\n // TURN Events\n //\n\n // Received by a publisher (sent by signaling server when a peer joining a room)\n SEND_OFFER: 'sendOffer',\n\n // Recieved by a subscriber when publisher sent an SDP offer\n SDP_OFFER: 'sdpOfferRecv',\n\n // Recieved by all subscribers, when the publisher has reconnected\n PUBLISHER_RECONNECT: 'publisherReconnect',\n\n // Recieved by the publisher, when a subscriber has disconnected\n PEER_DISCONNECTED: 'peerDisconnected'\n },\n};\n\n// KMS - Pipeline types\nexport const PIPELINE_TYPES = {\n AUDIO_VIDEO_TO_SUBSCRIBERS: 'AudioVideoToSub',\n AUDIO_VIDEO_TO_SUBSCRIBERS_WITH_SMART: 'AudioVideoToSubWithSmart',\n};\n\nexport const CLIENT_TYPES = {\n PUBLISHER: 'publisher',\n SUBSCRIBER: 'subscriber',\n};\n\nexport const PEER_CONNECTION_TYPES = {\n SEND_ONLY: 'WebRtcPeerSendonly',\n RECV_ONLY: 'WebRtcPeerRecvonly',\n SEND_RECV: 'WebRtcPeerSendrecv'\n};\n\n// Used to store the peer unique identifier (UID)\nexport const COOKIES = {\n UID: 'media-client.uid',\n};\n\nexport const DEFAULT_STREAM_NAMES = {\n MOBILE_CLIENT_VIDEO_STREAM: 'MOBILE_CLIENT_VIDEO_STREAM',\n MOBILE_CLIENT_AUDIO_STREAM: 'MOBILE_CLIENT_AUDIO_STREAM',\n DASHBOARD_AUDIO_STREAM: 'DASHBOARD_AUDIO_STREAM'\n};\n\n// When ICE exchange fail, an interval between reconnection attempts\nexport const RECONNECT_TURN_SERVER_INTERVAL = 1000;\n\n// When ICE exchange start, this is the timeout until the connection is deemed failed\nexport const FAILED_CONNECTING_TURN_SERVER_INTERVAL = 15000;\n\n// Grace to to wait before creating a publisher, if peer connection has not been created yet\nexport const WAIT_FOR_PC_INTERVAL = 2000;\n\n// Interval between checks of video publishing ability attempts\nexport const PUBLISH_APPROVAL_CHECK_INTERVAL = 1000;\n\nexport const SOCKET_RECONNECTION_DELAY = 3000,\n SOCKET_RECONNECTION_DELAY_MAX = 6000,\n SOCKET_RECONNECTION_ATTEMPTS = 100,\n SOCKET_PATH = '/socket2.io';\n"]}