@flashphoner/websdk 2.0.271 → 2.0.274

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.
@@ -9679,6 +9679,34 @@ var getMediaDevices = function (mediaProvider, labels, kind, deviceConstraints)
9679
9679
  return MediaProvider[mediaProvider].listDevices(labels, kind, deviceConstraints);
9680
9680
  };
9681
9681
 
9682
+ /**
9683
+ * Get mobile local media devices
9684
+ *
9685
+ * @param {String=} mediaProvider Media provider that will be asked for device list
9686
+ * @param {Flashphoner.constants.MEDIA_DEVICE_KIND} kind Media devices kind to access:
9687
+ * MEDIA_DEVICE_KIND.INPUT (default) get access to input devices only (camera, mic).
9688
+ * MEDIA_DEVICE_KIND.OUTPUT get access to output devices only (speaker, headphone).
9689
+ * MEDIA_DEVICE_KIND.ALL get access to all devices (cam, mic, speaker, headphone).
9690
+ * @param {Object=} deviceConstraints
9691
+ * If {audio: true, video: false}, then access to the camera will not be requested.
9692
+ * If {audio: false, video: true}, then access to the microphone will not be requested.
9693
+ * @returns {Promise.<Flashphoner.MediaDeviceList>} Promise with media device list on fulfill
9694
+ * @throws {Error} Error if API is not initialized
9695
+ * @memberof Flashphoner
9696
+ */
9697
+ var getMobileDevices = function (mediaProvider, kind, deviceConstraints) {
9698
+ if (!initialized) {
9699
+ throw new Error("Flashphoner API is not initialized");
9700
+ }
9701
+ if (!mediaProvider) {
9702
+ mediaProvider = getMediaProviders()[0];
9703
+ }
9704
+ if (MediaProvider[mediaProvider].getMobileDevices) {
9705
+ return MediaProvider[mediaProvider].getMobileDevices(kind, deviceConstraints);
9706
+ }
9707
+ return [];
9708
+ };
9709
+
9682
9710
  /**
9683
9711
  * Get access to local media
9684
9712
  *
@@ -10116,33 +10144,19 @@ var createSession = function (options) {
10116
10144
  streamRefreshHandlers[obj.mediaSessionId](obj);
10117
10145
  }
10118
10146
  break;
10119
- case `webRTCMetricsDescriptionUpdate`:
10120
- if (obj.ids) {
10121
- obj.ids.forEach((id) => {
10122
- if (streamRefreshHandlers[id]) {
10123
- streamRefreshHandlers[id](obj);
10124
- }
10125
- });
10126
- } else {
10127
- if (obj.compression) {
10128
- webRTCMetricsServerDescription.compression = obj.compression;
10129
- }
10130
- if (obj.batchSize) {
10131
- webRTCMetricsServerDescription.batchSize = obj.batchSize;
10132
- }
10133
- if (obj.sampling) {
10134
- webRTCMetricsServerDescription.sampling = obj.sampling;
10135
- }
10136
- if (obj.types) {
10137
- webRTCMetricsServerDescription.types = obj.types;
10138
- }
10139
- if (obj.collect) {
10140
- webRTCMetricsServerDescription.collect = obj.collect;
10141
- }
10142
- for (const [id, handler] of Object.entries(streamRefreshHandlers)) {
10143
- handler(obj);
10144
- }
10145
- }
10147
+ case 'webRTCMetricsDescriptionUpdate':
10148
+ handleWebRTCMetricsUpdate(obj, {
10149
+ compression: "compression",
10150
+ batchSize: "batchSize",
10151
+ sampling: "sampling",
10152
+ types: "types",
10153
+ collect: "collect"
10154
+ });
10155
+ break;
10156
+ case 'webRTCMetricsTokenRefresh':
10157
+ handleWebRTCMetricsUpdate(obj, {
10158
+ authorization: "authorization"
10159
+ });
10146
10160
  break;
10147
10161
  default:
10148
10162
  logger.info(LOG_PREFIX, "Unknown server message " + data.message);
@@ -10153,6 +10167,26 @@ var createSession = function (options) {
10153
10167
  };
10154
10168
  }
10155
10169
 
10170
+ function handleWebRTCMetricsUpdate(obj, updateFields = {}) {
10171
+ if (obj.ids) {
10172
+ obj.ids.forEach((id) => {
10173
+ if (streamRefreshHandlers[id]) {
10174
+ streamRefreshHandlers[id](obj);
10175
+ }
10176
+ });
10177
+ } else {
10178
+ Object.entries(updateFields).forEach(([key, value]) => {
10179
+ if (obj[value] !== undefined) {
10180
+ webRTCMetricsServerDescription[key] = obj[value];
10181
+ }
10182
+ });
10183
+
10184
+ for (const [id, handler] of Object.entries(streamRefreshHandlers)) {
10185
+ handler(obj);
10186
+ }
10187
+ }
10188
+ }
10189
+
10156
10190
  //WebSocket send helper
10157
10191
  function send(message, data) {
10158
10192
  if (wsConnection.readyState === WebSocket.OPEN) {
@@ -11306,6 +11340,11 @@ var createSession = function (options) {
11306
11340
  }
11307
11341
  }
11308
11342
 
11343
+ if (streamInfo.authorization && statsCollector && statsCollector.description.ingestPoint) {
11344
+ statsCollector.description.authorization = streamInfo.authorization;
11345
+ statsCollector.updateHttpConnection(statsCollector.description.ingestPoint, statsCollector.description.authorization);
11346
+ }
11347
+
11309
11348
  // Pause or resume metrics collection
11310
11349
  if (!streamInfo.status && streamInfo.collect !== undefined && statsCollector) {
11311
11350
  statsCollector.update(streamInfo);
@@ -12526,6 +12565,7 @@ module.exports = {
12526
12565
  isUsingTemasys: isUsingTemasys,
12527
12566
  getMediaProviders: getMediaProviders,
12528
12567
  getMediaDevices: getMediaDevices,
12568
+ getMobileDevices: getMobileDevices,
12529
12569
  getMediaAccess: getMediaAccess,
12530
12570
  releaseLocalMedia: releaseLocalMedia,
12531
12571
  getSessions: getSessions,
@@ -13333,6 +13373,11 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13333
13373
  }
13334
13374
  }
13335
13375
  },
13376
+ updateHttpConnection: function(url, authorization) {
13377
+ if (url.startsWith(CONNECTION_TYPE.HTTP) && authorization) {
13378
+ statCollector.connection.http.setAuthorization(authorization);
13379
+ }
13380
+ },
13336
13381
  checkForCompression: async function(compression) {
13337
13382
  try {
13338
13383
  await util.compress(compression, "test", false);
@@ -13373,6 +13418,9 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13373
13418
  statCollector.metricsBatch = null;
13374
13419
  }
13375
13420
  },
13421
+ isMetricValid: function(value) {
13422
+ return value != null && value !== "" && value !== "undefined" && value !== "null";
13423
+ },
13376
13424
  collectMetrics: async function() {
13377
13425
  if (statCollector.timer && !statCollector.timerBusy) {
13378
13426
  // Unfortunately there are no real atomics in JS unless SharedArrayBuffer is used
@@ -13402,7 +13450,7 @@ const StreamStatsCollector = function(description, id, mediaConnection, wsConnec
13402
13450
  }
13403
13451
  }
13404
13452
  }
13405
- if (value) {
13453
+ if (statCollector.isMetricValid(value)) {
13406
13454
  metrics.push(value);
13407
13455
  } else {
13408
13456
  lostMetrics.push(descriptor);
@@ -13576,6 +13624,9 @@ const HttpConnection = function(url, headers) {
13576
13624
  const connection = {
13577
13625
  url: addSlash(url),
13578
13626
  headers: headers,
13627
+ setAuthorization(token) {
13628
+ this.headers.Authorization = token;
13629
+ },
13579
13630
  send: async function(message, data) {
13580
13631
  let code = CONNECTION_STATUS.BAD_REQUEST;
13581
13632
  if (connection.url) {
@@ -16344,6 +16395,63 @@ var available = function () {
16344
16395
  return ('getUserMedia' in navigator && 'RTCPeerConnection' in window);
16345
16396
  };
16346
16397
 
16398
+ /**
16399
+ * Helper function to get media devices list in id, label, type form
16400
+ *
16401
+ * @param devices
16402
+ * @param kind
16403
+ * @param videoFilter
16404
+ * @returns {{audio: *[], video: *[]}}
16405
+ */
16406
+ const getList = function (devices, kind, videoFilter = null) {
16407
+ var list = {
16408
+ audio: [],
16409
+ video: []
16410
+ };
16411
+
16412
+ var micCount = 0;
16413
+ var outputCount = 0;
16414
+ var camCount = 0;
16415
+ for (var i = 0; i < devices.length; i++) {
16416
+ var device = devices[i];
16417
+ var ret = {
16418
+ id: device.deviceId,
16419
+ label: device.label
16420
+ };
16421
+ if (device.kind.indexOf("audio" + kind) === 0 && device.deviceId !== "communications") {
16422
+ ret.type = (device.kind === "audioinput") ? "mic" : "speaker";
16423
+ if (ret.type === "mic" && ret.label === "") {
16424
+ ret.label = 'microphone' + ++micCount;
16425
+ }
16426
+ if (ret.type === "speaker" && ret.label === "") {
16427
+ ret.label = 'speaker' + ++outputCount;
16428
+ }
16429
+ list.audio.push(ret);
16430
+ } else if (device.kind.indexOf("video" + kind) === 0) {
16431
+ if (!videoFilter || videoFilter.find((id) => id === device.deviceId)) {
16432
+ if (ret.label === "") {
16433
+ ret.label = 'camera' + ++camCount;
16434
+ }
16435
+ ret.type = "camera";
16436
+ list.video.push(ret);
16437
+ } else {
16438
+ logger.debug(LOG_PREFIX, "Video device " + device.deviceId + "does not conform the filter " + JSON.stringify(videoFilter));
16439
+ }
16440
+ } else {
16441
+ logger.debug(LOG_PREFIX, "unknown device " + device.kind + " id " + device.deviceId);
16442
+ }
16443
+ }
16444
+ return list;
16445
+ }
16446
+
16447
+ /**
16448
+ * Get media devices list
16449
+ *
16450
+ * @param labels
16451
+ * @param kind
16452
+ * @param deviceConstraints
16453
+ * @returns {Promise<{audio: [], video: []}>}
16454
+ */
16347
16455
  var listDevices = function (labels, kind, deviceConstraints) {
16348
16456
  //WCS-1963. added deviceConstraints.
16349
16457
  if (!deviceConstraints) {
@@ -16354,7 +16462,7 @@ var listDevices = function (labels, kind, deviceConstraints) {
16354
16462
  }
16355
16463
  if (!kind) {
16356
16464
  kind = constants.MEDIA_DEVICE_KIND.INPUT;
16357
- } else if (kind == "all") {
16465
+ } else if (kind === constants.MEDIA_DEVICE_KIND.ALL) {
16358
16466
  kind = "";
16359
16467
  }
16360
16468
  var getConstraints = function (devices) {
@@ -16362,9 +16470,9 @@ var listDevices = function (labels, kind, deviceConstraints) {
16362
16470
  for (var i = 0; i < devices.length; i++) {
16363
16471
  var device = devices[i];
16364
16472
  if (device.kind.indexOf("audio" + kind) === 0 && deviceConstraints.audio) {
16365
- constraints.audio = true;
16473
+ constraints.audio = deviceConstraints.audio;
16366
16474
  } else if (device.kind.indexOf("video" + kind) === 0 && deviceConstraints.video) {
16367
- constraints.video = true;
16475
+ constraints.video = deviceConstraints.video;
16368
16476
  } else {
16369
16477
  logger.debug(LOG_PREFIX, "unknown device " + device.kind + " id " + device.deviceId);
16370
16478
  }
@@ -16372,43 +16480,6 @@ var listDevices = function (labels, kind, deviceConstraints) {
16372
16480
  return constraints;
16373
16481
  };
16374
16482
 
16375
- var getList = function (devices) {
16376
- var list = {
16377
- audio: [],
16378
- video: []
16379
- };
16380
-
16381
- var micCount = 0;
16382
- var outputCount = 0;
16383
- var camCount = 0;
16384
- for (var i = 0; i < devices.length; i++) {
16385
- var device = devices[i];
16386
- var ret = {
16387
- id: device.deviceId,
16388
- label: device.label
16389
- };
16390
- if (device.kind.indexOf("audio" + kind) === 0 && device.deviceId != "communications") {
16391
- ret.type = (device.kind == "audioinput") ? "mic" : "speaker";
16392
- if (ret.type == "mic" && ret.label == "") {
16393
- ret.label = 'microphone' + ++micCount;
16394
- }
16395
- if (ret.type == "speaker" && ret.label == "") {
16396
- ret.label = 'speaker' + ++outputCount;
16397
- }
16398
- list.audio.push(ret);
16399
- } else if (device.kind.indexOf("video" + kind) === 0) {
16400
- if (ret.label == "") {
16401
- ret.label = 'camera' + ++camCount;
16402
- }
16403
- ret.type = "camera";
16404
- list.video.push(ret);
16405
- } else {
16406
- logger.debug(LOG_PREFIX, "unknown device " + device.kind + " id " + device.deviceId);
16407
- }
16408
- }
16409
- return list;
16410
- };
16411
-
16412
16483
  return new Promise(function (resolve, reject) {
16413
16484
  navigator.mediaDevices.enumerateDevices().then(function (devices) {
16414
16485
  if (labels) {
@@ -16420,19 +16491,96 @@ var listDevices = function (labels, kind, deviceConstraints) {
16420
16491
  }
16421
16492
  navigator.getUserMedia(constraints, function (stream) {
16422
16493
  navigator.mediaDevices.enumerateDevices().then(function (devicesWithLabels) {
16423
- resolve(getList(devicesWithLabels));
16494
+ resolve(getList(devicesWithLabels, kind));
16424
16495
  stream.getTracks().forEach(function (track) {
16425
16496
  track.stop();
16426
16497
  });
16427
16498
  }, reject);
16428
16499
  }, reject);
16429
16500
  } else {
16430
- resolve(getList(devices));
16501
+ resolve(getList(devices, kind));
16431
16502
  }
16432
16503
  }, reject);
16433
-
16434
16504
  });
16435
- };
16505
+ }
16506
+
16507
+ const getMobileDevices = async function (kind, deviceConstraints = null) {
16508
+ let constraints = {};
16509
+ let videoFilter = [];
16510
+ let list = null;
16511
+ if (!kind) {
16512
+ kind = constants.MEDIA_DEVICE_KIND.INPUT;
16513
+ } else if (kind === constants.MEDIA_DEVICE_KIND.ALL) {
16514
+ kind = "";
16515
+ }
16516
+ if (deviceConstraints && deviceConstraints.audio) {
16517
+ constraints.audio = deviceConstraints.audio;
16518
+ } else {
16519
+ constraints.audio = true;
16520
+ }
16521
+ if (deviceConstraints && deviceConstraints.video) {
16522
+ if (typeof deviceConstraints.video === 'object') {
16523
+ constraints.video = deviceConstraints.video;
16524
+ }
16525
+ else {
16526
+ constraints.video = {};
16527
+ }
16528
+ } else {
16529
+ constraints.video = {};
16530
+ }
16531
+
16532
+ const getCamera = async function (constraints, facingMode) {
16533
+ let deviceId = null;
16534
+ let mediaConstraints = {
16535
+ audio: false,
16536
+ video: constraints.video
16537
+ };
16538
+ mediaConstraints.video.facingMode = facingMode;
16539
+ try {
16540
+ stream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
16541
+ if (stream) {
16542
+ if (stream.getVideoTracks().length > 0) {
16543
+ deviceId = stream.getVideoTracks()[0].getSettings().deviceId;
16544
+ }
16545
+ stream.getTracks().forEach((track) => {
16546
+ track.stop();
16547
+ });
16548
+ }
16549
+ } catch (error) {
16550
+ logger.error(LOG_PREFIX, "Can't get device access with video constraints " + JSON.stringify(constraints.video) + ", error " + error);
16551
+ }
16552
+ return deviceId;
16553
+ }
16554
+
16555
+ let front = await getCamera(constraints, { ideal: 'user' });
16556
+ if (front && front !== "") {
16557
+ logger.debug(LOG_PREFIX, "Front camera id: " + front);
16558
+ videoFilter.push(front);
16559
+ }
16560
+ let back = await getCamera(constraints, { ideal: 'environment' });
16561
+ if (back && back !== "") {
16562
+ logger.debug(LOG_PREFIX, "Back camera id: " + back);
16563
+ videoFilter.push(back);
16564
+ }
16565
+
16566
+ try {
16567
+ const stream = await navigator.mediaDevices.getUserMedia(constraints);
16568
+ if (stream) {
16569
+ const mediaDevices = await navigator.mediaDevices.enumerateDevices();
16570
+ if (mediaDevices) {
16571
+ logger.debug(LOG_PREFIX, "mediaDevices: " + JSON.stringify(mediaDevices));
16572
+ list = getList(mediaDevices, kind, videoFilter);
16573
+ }
16574
+ stream.getTracks().forEach(function (track) {
16575
+ track.stop();
16576
+ });
16577
+ }
16578
+ } catch (error) {
16579
+ logger.error(LOG_PREFIX, "Can't get device access with constraints " + JSON.stringify(constraints) + ", error " + error);
16580
+ }
16581
+
16582
+ return list;
16583
+ }
16436
16584
 
16437
16585
  function normalizeConstraints(constraints) {
16438
16586
  //WCS-2010. fixed TypeError after publish->stop->publish
@@ -16554,6 +16702,7 @@ module.exports = {
16554
16702
  getMediaAccess: getMediaAccess,
16555
16703
  releaseMedia: releaseMedia,
16556
16704
  listDevices: listDevices,
16705
+ getMobileDevices: getMobileDevices,
16557
16706
  playFirstSound: playFirstSound,
16558
16707
  playFirstVideo: playFirstVideo,
16559
16708
  available: available,