videomail-client 15.10.1 → 15.11.0

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.
@@ -423,7 +423,7 @@ var __webpack_modules__ = {
423
423
  return parts.join('');
424
424
  }
425
425
  },
426
- dY2 (__unused_rspack_module, exports1, __webpack_require__) {
426
+ dY (__unused_rspack_module, exports1, __webpack_require__) {
427
427
  "use strict";
428
428
  /*!
429
429
  * The buffer module from node.js, for the browser.
@@ -1706,7 +1706,7 @@ var __webpack_modules__ = {
1706
1706
  return null === arg || 'boolean' == typeof arg || 'number' == typeof arg || 'string' == typeof arg || 'symbol' == typeof arg || void 0 === arg;
1707
1707
  }
1708
1708
  exports1.isPrimitive = isPrimitive;
1709
- exports1.isBuffer = __webpack_require__("dY2").Buffer.isBuffer;
1709
+ exports1.isBuffer = __webpack_require__("dY").Buffer.isBuffer;
1710
1710
  function objectToString(o) {
1711
1711
  return Object.prototype.toString.call(o);
1712
1712
  }
@@ -1902,7 +1902,7 @@ var __webpack_modules__ = {
1902
1902
  } : false;
1903
1903
  },
1904
1904
  Y4 (module, __unused_rspack_exports, __webpack_require__) {
1905
- var Buffer = __webpack_require__("dY2").Buffer;
1905
+ var Buffer = __webpack_require__("dY").Buffer;
1906
1906
  var process = __webpack_require__("zT");
1907
1907
  var stream = __webpack_require__("GB");
1908
1908
  var eos = __webpack_require__("Qd");
@@ -3462,7 +3462,7 @@ var __webpack_modules__ = {
3462
3462
  exports1.PassThrough = __webpack_require__("P");
3463
3463
  },
3464
3464
  Uf (module, exports1, __webpack_require__) {
3465
- var buffer = __webpack_require__("dY2");
3465
+ var buffer = __webpack_require__("dY");
3466
3466
  var Buffer = buffer.Buffer;
3467
3467
  function copyProps(src, dst) {
3468
3468
  for(var key in src)dst[key] = src[key];
@@ -7044,7 +7044,7 @@ var __webpack_modules__ = {
7044
7044
  const Emitter = __webpack_require__("r");
7045
7045
  const safeStringify = __webpack_require__("X");
7046
7046
  const qs = __webpack_require__("b");
7047
- const RequestBase = __webpack_require__("dY");
7047
+ const RequestBase = __webpack_require__("d");
7048
7048
  const { isObject, mixin, hasOwn, isSafeKey } = __webpack_require__("Dp");
7049
7049
  const ResponseBase = __webpack_require__("e");
7050
7050
  const Agent = __webpack_require__("pf");
@@ -7459,7 +7459,7 @@ var __webpack_modules__ = {
7459
7459
  return request_;
7460
7460
  };
7461
7461
  },
7462
- dY (module, __unused_rspack_exports, __webpack_require__) {
7462
+ d (module, __unused_rspack_exports, __webpack_require__) {
7463
7463
  "use strict";
7464
7464
  const { isObject, hasOwn, isSafeKey } = __webpack_require__("Dp");
7465
7465
  module.exports = RequestBase;
@@ -7862,7 +7862,7 @@ var __webpack_modules__ = {
7862
7862
  exports1.isBrotliEncoding = (res)=>/^\s*br\s*$/i.test(res.headers['content-encoding']);
7863
7863
  },
7864
7864
  E (module, __unused_rspack_exports, __webpack_require__) {
7865
- var Buffer = __webpack_require__("dY2").Buffer;
7865
+ var Buffer = __webpack_require__("dY").Buffer;
7866
7866
  /*! typedarray-to-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */ module.exports = function(arr) {
7867
7867
  return ArrayBuffer.isView(arr) ? Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength) : Buffer.from(arr);
7868
7868
  };
@@ -9933,7 +9933,7 @@ var __webpack_modules__ = {
9933
9933
  exports1.PassThrough = __webpack_require__("X2");
9934
9934
  },
9935
9935
  CX (module, exports1, __webpack_require__) {
9936
- var buffer = __webpack_require__("dY2");
9936
+ var buffer = __webpack_require__("dY");
9937
9937
  var Buffer = buffer.Buffer;
9938
9938
  function copyProps(src, dst) {
9939
9939
  for(var key in src)dst[key] = src[key];
@@ -10471,7 +10471,7 @@ var __webpack_modules__ = {
10471
10471
  return i[1];
10472
10472
  };
10473
10473
  },
10474
- R (module) {
10474
+ RR (module) {
10475
10475
  "use strict";
10476
10476
  var stylesInDOM = [];
10477
10477
  function getIndexByIdentifier(identifier) {
@@ -10972,7 +10972,7 @@ var __webpack_exports__ = {};
10972
10972
  var client = __webpack_require__("Q");
10973
10973
  var client_default = /*#__PURE__*/ __webpack_require__.n(client);
10974
10974
  var package_namespaceObject = {
10975
- rE: "15.10.1"
10975
+ rE: "15.11.0"
10976
10976
  };
10977
10977
  function isAudioEnabled(options) {
10978
10978
  return Boolean(options.audio.enabled);
@@ -11050,7 +11050,7 @@ var __webpack_exports__ = {};
11050
11050
  if ("u" > typeof Event && anything instanceof Event) return inspect(error_getEventDetails(anything));
11051
11051
  return inspect(anything);
11052
11052
  }
11053
- const util_pretty = pretty;
11053
+ const string_pretty = pretty;
11054
11054
  var defined = __webpack_require__("MO");
11055
11055
  var defined_default = /*#__PURE__*/ __webpack_require__.n(defined);
11056
11056
  var LIBVERSION = '2.0.10', UA_MAX_LENGTH = 500, USER_AGENT = 'user-agent', EMPTY = '', UNKNOWN = '?', TYPEOF = {
@@ -14583,16 +14583,16 @@ var __webpack_exports__ = {};
14583
14583
  break;
14584
14584
  case error_VideomailError.DOM_EXCEPTION:
14585
14585
  message = "DOM Exception";
14586
- if (err) explanation = util_pretty(err);
14586
+ if (err) explanation = string_pretty(err);
14587
14587
  break;
14588
14588
  case error_VideomailError.MEDIA_DEVICE_NOT_SUPPORTED:
14589
14589
  message = "Media device not supported";
14590
- if (err) explanation = util_pretty(err);
14590
+ if (err) explanation = string_pretty(err);
14591
14591
  break;
14592
14592
  default:
14593
14593
  {
14594
14594
  const originalExplanation = explanation;
14595
- if (explanation && "object" == typeof explanation) explanation = util_pretty(explanation);
14595
+ if (explanation && "object" == typeof explanation) explanation = string_pretty(explanation);
14596
14596
  if (!explanation && originalExplanation) explanation = `Inspected: ${originalExplanation}`;
14597
14597
  if (!explanation && (null == err ? void 0 : err.explanation)) explanation = err.explanation;
14598
14598
  if (!message && (null == err ? void 0 : err.message)) message = err.message;
@@ -14781,7 +14781,7 @@ var __webpack_exports__ = {};
14781
14781
  emit(eventName, ...params) {
14782
14782
  const firstParam = params[0];
14783
14783
  const showParams = firstParam && ("object" != typeof firstParam || "object" == typeof firstParam && Object.keys(firstParam).filter(Boolean).length > 0);
14784
- if (showParams) this.options.logger.debug(`${this.name} emits ${eventName} with ${util_pretty(params)}`);
14784
+ if (showParams) this.options.logger.debug(`${this.name} emits ${eventName} with ${string_pretty(params)}`);
14785
14785
  else this.options.logger.debug(`${this.name} emits ${eventName}`);
14786
14786
  try {
14787
14787
  this.emitter.emit(eventName, ...params);
@@ -15096,7 +15096,7 @@ var __webpack_exports__ = {};
15096
15096
  return _async_to_generator(function*() {
15097
15097
  var _this_formElement_getAttribute;
15098
15098
  if (e) {
15099
- this.options.logger.debug(`Form: doTheSubmit(${util_pretty(e)})`);
15099
+ this.options.logger.debug(`Form: doTheSubmit(${string_pretty(e)})`);
15100
15100
  e.preventDefault();
15101
15101
  } else this.options.logger.debug("Form: doTheSubmit()");
15102
15102
  const url = null != (_this_formElement_getAttribute = this.formElement.getAttribute("action")) ? _this_formElement_getAttribute : this.options.apiUrl;
@@ -15409,12 +15409,12 @@ var __webpack_exports__ = {};
15409
15409
  if (!process.env.NODE_ENV) return NodeEnvType.DEVELOPMENT;
15410
15410
  return process.env.NODE_ENV;
15411
15411
  }
15412
- const util_getNodeEnv = getNodeEnv;
15413
- function isProductionMode() {
15414
- return util_getNodeEnv() === NodeEnvType.PRODUCTION;
15412
+ const env_getNodeEnv = getNodeEnv;
15413
+ function isProduction() {
15414
+ return env_getNodeEnv() === NodeEnvType.PRODUCTION;
15415
15415
  }
15416
- const util_isProductionMode = isProductionMode;
15417
- const PRODUCTION = util_isProductionMode();
15416
+ const env_isProduction = isProduction;
15417
+ const PRODUCTION = env_isProduction();
15418
15418
  const options_options = {
15419
15419
  logger: console,
15420
15420
  logStackSize: 30,
@@ -15588,7 +15588,7 @@ var __webpack_exports__ = {};
15588
15588
  function isTest() {
15589
15589
  return "test" === isTest_process.env.ENVIRON;
15590
15590
  }
15591
- const util_isTest = isTest;
15591
+ const env_isTest = isTest;
15592
15592
  function mergeWithDefaultOptions(options = {}) {
15593
15593
  const newOptions = cjs_default()(src_options, options, {
15594
15594
  arrayMerge (_destination, source) {
@@ -15597,11 +15597,11 @@ var __webpack_exports__ = {};
15597
15597
  });
15598
15598
  const collectLogger = new util_CollectLogger(newOptions);
15599
15599
  newOptions.logger = collectLogger;
15600
- if (util_isTest()) newOptions.verbose = false;
15600
+ if (env_isTest()) newOptions.verbose = false;
15601
15601
  return newOptions;
15602
15602
  }
15603
15603
  const options_mergeWithDefaultOptions = mergeWithDefaultOptions;
15604
- var injectStylesIntoStyleTag = __webpack_require__("R");
15604
+ var injectStylesIntoStyleTag = __webpack_require__("RR");
15605
15605
  var injectStylesIntoStyleTag_default = /*#__PURE__*/ __webpack_require__.n(injectStylesIntoStyleTag);
15606
15606
  var styleDomAPI = __webpack_require__("Bd");
15607
15607
  var styleDomAPI_default = /*#__PURE__*/ __webpack_require__.n(styleDomAPI);
@@ -18366,7 +18366,7 @@ var __webpack_exports__ = {};
18366
18366
  if (absNum < 10) return n < 0 ? `-0${absNum}` : `0${absNum}`;
18367
18367
  return String(n);
18368
18368
  }
18369
- const util_pad = pad;
18369
+ const string_pad = pad;
18370
18370
  function recordTimer_define_property(obj, key, value) {
18371
18371
  if (key in obj) Object.defineProperty(obj, key, {
18372
18372
  value: value,
@@ -18427,7 +18427,7 @@ var __webpack_exports__ = {};
18427
18427
  this.options.logger.debug(`End is nigh, ${this.countdown} seconds to go`);
18428
18428
  }
18429
18429
  }
18430
- if (this.recordTimerElement) this.recordTimerElement.textContent = `${mins}:${util_pad(secs)}`;
18430
+ if (this.recordTimerElement) this.recordTimerElement.textContent = `${mins}:${string_pad(secs)}`;
18431
18431
  }
18432
18432
  hide() {
18433
18433
  html_hideElement(this.recordTimerElement);
@@ -18745,7 +18745,7 @@ var __webpack_exports__ = {};
18745
18745
  error(err) {
18746
18746
  const message = err.message;
18747
18747
  const explanation = err.explanation;
18748
- if (!message) this.options.logger.debug(`Weird empty error message generated for error ${util_pretty(err)}`);
18748
+ if (!message) this.options.logger.debug(`Weird empty error message generated for error ${string_pretty(err)}`);
18749
18749
  this.notify(message, explanation, {
18750
18750
  blocking: true,
18751
18751
  problem: true,
@@ -18927,6 +18927,46 @@ var __webpack_exports__ = {};
18927
18927
  canvas_to_buffer_modern_r.atob = void 0;
18928
18928
  var websocket_stream_stream = __webpack_require__("U");
18929
18929
  var stream_default = /*#__PURE__*/ __webpack_require__.n(websocket_stream_stream);
18930
+ function boundedWriteQueue_define_property(obj, key, value) {
18931
+ if (key in obj) Object.defineProperty(obj, key, {
18932
+ value: value,
18933
+ enumerable: true,
18934
+ configurable: true,
18935
+ writable: true
18936
+ });
18937
+ else obj[key] = value;
18938
+ return obj;
18939
+ }
18940
+ const DEFAULT_MAX_QUEUED_BYTES = 1048576;
18941
+ class BoundedWriteQueue {
18942
+ enqueue(buffer, params) {
18943
+ if (this.queuedBytes + buffer.length > this.maxBytes) return false;
18944
+ this.writes.push({
18945
+ buffer,
18946
+ params
18947
+ });
18948
+ this.queuedBytes += buffer.length;
18949
+ return true;
18950
+ }
18951
+ dequeue() {
18952
+ const write = this.writes.shift();
18953
+ if (write) this.queuedBytes -= write.buffer.length;
18954
+ return write;
18955
+ }
18956
+ clear() {
18957
+ this.writes.length = 0;
18958
+ this.queuedBytes = 0;
18959
+ }
18960
+ constructor(maxBytes = DEFAULT_MAX_QUEUED_BYTES){
18961
+ boundedWriteQueue_define_property(this, "maxBytes", void 0);
18962
+ boundedWriteQueue_define_property(this, "writes", void 0);
18963
+ boundedWriteQueue_define_property(this, "queuedBytes", void 0);
18964
+ this.maxBytes = maxBytes;
18965
+ this.writes = [];
18966
+ this.queuedBytes = 0;
18967
+ }
18968
+ }
18969
+ const boundedWriteQueue = BoundedWriteQueue;
18930
18970
  function getEdgeCodes(value, amount, fromEnd) {
18931
18971
  const chars = fromEnd ? value.slice(-amount) : value.slice(0, amount);
18932
18972
  const codes = Array.from(chars, (char)=>String(char.codePointAt(0))).join(".");
@@ -19078,7 +19118,7 @@ var __webpack_exports__ = {};
19078
19118
  const util_isAutomatedUserAgent = isAutomatedUserAgent;
19079
19119
  function summarize(title, contents) {
19080
19120
  const lines = Object.entries(contents).sort(([keyA], [keyB])=>keyA.localeCompare(keyB)).map(([key, value])=>{
19081
- const formattedValue = void 0 === value ? "undefined" : "object" == typeof value ? util_pretty(value) : value;
19121
+ const formattedValue = void 0 === value ? "undefined" : "object" == typeof value ? string_pretty(value) : value;
19082
19122
  return ` • ${key}: ${formattedValue}`;
19083
19123
  });
19084
19124
  const line = [
@@ -19087,7 +19127,7 @@ var __webpack_exports__ = {};
19087
19127
  ].join("\n");
19088
19128
  return line;
19089
19129
  }
19090
- const util_summarize = summarize;
19130
+ const string_summarize = summarize;
19091
19131
  function getFirstVideoTrack(localMediaStream) {
19092
19132
  const videoTracks = localMediaStream.getVideoTracks();
19093
19133
  let videoTrack;
@@ -19301,7 +19341,7 @@ var __webpack_exports__ = {};
19301
19341
  return videoWidth > 0 && videoWidth < 3 || videoHeight > 0 && videoHeight < 3;
19302
19342
  }
19303
19343
  logEvent(eventType, params) {
19304
- this.options.logger.debug(`UserMedia: ... ${EVENT_ASCII} event ${eventType}: ${util_pretty(params)}`);
19344
+ this.options.logger.debug(`UserMedia: ... ${EVENT_ASCII} event ${eventType}: ${string_pretty(params)}`);
19305
19345
  }
19306
19346
  unloadRemainingEventListeners() {
19307
19347
  var _this_rawVisualUserMedia;
@@ -19340,7 +19380,7 @@ var __webpack_exports__ = {};
19340
19380
  var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
19341
19381
  null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.load();
19342
19382
  if (null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.paused) {
19343
- this.options.logger.debug(`UserMedia: play(): media.readyState=${this.rawVisualUserMedia.readyState}, media.paused=${this.rawVisualUserMedia.paused}, media.ended=${this.rawVisualUserMedia.ended}, media.played=${util_pretty(this.rawVisualUserMedia.played)}`);
19383
+ this.options.logger.debug(`UserMedia: play(): media.readyState=${this.rawVisualUserMedia.readyState}, media.paused=${this.rawVisualUserMedia.paused}, media.ended=${this.rawVisualUserMedia.ended}, media.played=${string_pretty(this.rawVisualUserMedia.played)}`);
19344
19384
  this.rawVisualUserMedia.play().then(()=>{
19345
19385
  if (!this.playingPromiseReached) {
19346
19386
  this.options.logger.debug("UserMedia: play promise successful. Playing now.");
@@ -19572,7 +19612,7 @@ var __webpack_exports__ = {};
19572
19612
  });
19573
19613
  null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.removeEventListener(e.type, this.outputEvent);
19574
19614
  }), userMedia_define_property(this, "handleMediaError", (event)=>{
19575
- this.options.logger.warn(`Caught video element error event: ${util_pretty(event)}`);
19615
+ this.options.logger.warn(`Caught video element error event: ${string_pretty(event)}`);
19576
19616
  });
19577
19617
  this.recorder = recorder;
19578
19618
  this.rawVisualUserMedia = recorder.getRawVisualUserMedia();
@@ -19583,7 +19623,7 @@ var __webpack_exports__ = {};
19583
19623
  }
19584
19624
  }
19585
19625
  const visuals_userMedia = UserMedia;
19586
- var Buffer = __webpack_require__("dY2").Buffer;
19626
+ var Buffer = __webpack_require__("dY").Buffer;
19587
19627
  function recorder_define_property(obj, key, value) {
19588
19628
  if (key in obj) Object.defineProperty(obj, key, {
19589
19629
  value: value,
@@ -19609,6 +19649,9 @@ var __webpack_exports__ = {};
19609
19649
  }
19610
19650
  const PIPE_SYMBOL = "°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸ ";
19611
19651
  class Recorder extends util_Despot {
19652
+ hasExceededWebSocketSendBuffer(buffer, opts) {
19653
+ return buffer.length > 0 && !this.pendingWrites.enqueue(buffer, opts);
19654
+ }
19612
19655
  writeStream(buffer, opts) {
19613
19656
  if (this.stream) if (this.stream.destroyed) {
19614
19657
  this.stopPings();
@@ -19617,41 +19660,187 @@ var __webpack_exports__ = {};
19617
19660
  explanation: "Sorry, connection to the server has been destroyed. Please reload.",
19618
19661
  options: this.options
19619
19662
  });
19620
- this.emit("ERROR", {
19621
- err
19663
+ this.handleWriteFailure(err);
19664
+ } else if (this.streamBackpressured) {
19665
+ if (this.hasExceededWebSocketSendBuffer(buffer, opts)) this.failMediaTransmission(error_createError({
19666
+ message: "WebSocket send buffer limit exceeded",
19667
+ explanation: "The connection to the server is too slow to keep up with this recording. The recording has been stopped; please start a new one.",
19668
+ options: this.options
19669
+ }));
19670
+ } else this.writeToStream(this.stream, buffer, opts);
19671
+ }
19672
+ writeToStream(stream, buffer, opts) {
19673
+ const onFlushedCallback = null == opts ? void 0 : opts.onFlushedCallback;
19674
+ try {
19675
+ const canContinue = stream.write(buffer, ()=>{
19676
+ if (!onFlushedCallback) return;
19677
+ try {
19678
+ onFlushedCallback(opts);
19679
+ } catch (exc) {
19680
+ const err = error_createError({
19681
+ message: "Failed to write stream buffer",
19682
+ explanation: `stream.write() failed because of ${string_pretty(exc)}`,
19683
+ options: this.options,
19684
+ exc
19685
+ });
19686
+ this.emit("ERROR", {
19687
+ err
19688
+ });
19689
+ }
19622
19690
  });
19623
- } else {
19624
- const onFlushedCallback = null == opts ? void 0 : opts.onFlushedCallback;
19625
- try {
19626
- this.stream.write(buffer, ()=>{
19627
- if (!onFlushedCallback) return;
19628
- try {
19629
- onFlushedCallback(opts);
19630
- } catch (exc) {
19631
- const err = error_createError({
19632
- message: "Failed to write stream buffer",
19633
- explanation: `stream.write() failed because of ${util_pretty(exc)}`,
19634
- options: this.options,
19635
- exc
19636
- });
19637
- this.emit("ERROR", {
19638
- err
19639
- });
19640
- }
19641
- });
19642
- } catch (exc) {
19643
- const err = error_createError({
19644
- message: "Failed writing to server",
19645
- explanation: `stream.write() failed because of ${util_pretty(exc)}`,
19646
- options: this.options,
19647
- exc
19648
- });
19649
- this.emit("ERROR", {
19650
- err
19651
- });
19691
+ if (!canContinue) {
19692
+ this.streamBackpressured = true;
19693
+ this.startBackpressureTimeout();
19694
+ this.pauseForBackpressure();
19695
+ return false;
19652
19696
  }
19697
+ return true;
19698
+ } catch (exc) {
19699
+ const err = error_createError({
19700
+ message: "Failed writing to server",
19701
+ explanation: `stream.write() failed because of ${string_pretty(exc)}`,
19702
+ options: this.options,
19703
+ exc
19704
+ });
19705
+ this.handleWriteFailure(err);
19706
+ return false;
19707
+ }
19708
+ }
19709
+ flushPendingWrites(stream) {
19710
+ if (this.isStaleStream(stream)) return;
19711
+ this.streamBackpressured = false;
19712
+ this.clearBackpressureTimeout();
19713
+ let pendingWrite = this.pendingWrites.dequeue();
19714
+ while(pendingWrite){
19715
+ if (!this.writeToStream(stream, pendingWrite.buffer, pendingWrite.params)) return;
19716
+ pendingWrite = this.pendingWrites.dequeue();
19717
+ }
19718
+ this.resumeRecordingAfterDrain();
19719
+ }
19720
+ isStaleStream(stream) {
19721
+ return this.stream !== stream || stream.destroyed;
19722
+ }
19723
+ canPauseForBackpressure() {
19724
+ var _this_userMedia, _this_loop;
19725
+ return Boolean(this.recordingActive && !(null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isPaused()) && (null == (_this_loop = this.loop) ? void 0 : _this_loop.isRunning()));
19726
+ }
19727
+ pauseForBackpressure() {
19728
+ if (!this.canPauseForBackpressure()) return;
19729
+ this.resumeAfterDrain = true;
19730
+ this.loop.stop();
19731
+ }
19732
+ resumeRecordingAfterDrain() {
19733
+ if (!this.resumeAfterDrain) return;
19734
+ this.resumeAfterDrain = false;
19735
+ if (this.canResumeAfterDrain()) {
19736
+ var _this_loop;
19737
+ null == (_this_loop = this.loop) || _this_loop.start();
19653
19738
  }
19654
19739
  }
19740
+ canResumeAfterDrain() {
19741
+ var _this_userMedia;
19742
+ return this.recordingActive && !(null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isPaused());
19743
+ }
19744
+ handleWriteFailure(err) {
19745
+ if (this.mediaTransmissionStarted) return void this.failMediaTransmission(err);
19746
+ this.emit("ERROR", {
19747
+ err
19748
+ });
19749
+ }
19750
+ failMediaTransmission(err) {
19751
+ if (this.recordingTransportFailed) return;
19752
+ this.recordingTransportFailed = true;
19753
+ this.recordingActive = false;
19754
+ this.mediaTransmissionStarted = false;
19755
+ this.streamBackpressured = false;
19756
+ this.resumeAfterDrain = false;
19757
+ this.pendingWrites.clear();
19758
+ this.connected = false;
19759
+ this.connecting = false;
19760
+ this.reconnecting = false;
19761
+ this.clearReconnectTimeout();
19762
+ this.clearBackpressureTimeout();
19763
+ this.discardSocket();
19764
+ this.reset();
19765
+ this.framesCount = this.samplesCount = 0;
19766
+ this.confirmedFrameNumber = this.confirmedSampleNumber = 0;
19767
+ delete this.recordingStats;
19768
+ this.recordingDimensions = void 0;
19769
+ this.emit("ERROR", {
19770
+ err
19771
+ });
19772
+ }
19773
+ startBackpressureTimeout() {
19774
+ if (!this.shouldStartBackpressureTimeout()) return;
19775
+ this.backpressureTimeout = window.setTimeout(()=>{
19776
+ this.backpressureTimeout = void 0;
19777
+ if (this.shouldIgnoreBackpressureTimeout()) return;
19778
+ const err = error_createError({
19779
+ message: "WebSocket write timed out",
19780
+ explanation: "The server stopped accepting recording data. The recording has been stopped; please check your connection and start a new one.",
19781
+ options: this.options
19782
+ });
19783
+ this.failMediaTransmission(err);
19784
+ }, this.options.timeouts.connection);
19785
+ }
19786
+ shouldStartBackpressureTimeout() {
19787
+ return void 0 === this.backpressureTimeout && this.mediaTransmissionStarted;
19788
+ }
19789
+ shouldIgnoreBackpressureTimeout() {
19790
+ return !this.streamBackpressured || this.recordingTransportFailed;
19791
+ }
19792
+ failInterruptedRecording() {
19793
+ const unconfirmedFrames = Math.max(0, this.framesCount - this.confirmedFrameNumber);
19794
+ const unconfirmedSamples = Math.max(0, this.samplesCount - this.confirmedSampleNumber);
19795
+ const err = error_createError({
19796
+ message: "Recording interrupted",
19797
+ explanation: "The server connection closed before this recording completed. It cannot be safely resumed, so it has been stopped. Please start a new recording.",
19798
+ options: this.options,
19799
+ cause: {
19800
+ unconfirmedFrames,
19801
+ unconfirmedSamples
19802
+ }
19803
+ });
19804
+ this.failMediaTransmission(err);
19805
+ }
19806
+ handleStreamDrain(stream) {
19807
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *drain* event emitted`);
19808
+ this.flushPendingWrites(stream);
19809
+ }
19810
+ canReconnectAfterStreamClose() {
19811
+ return Boolean(this.connected && this.userMediaLoaded);
19812
+ }
19813
+ shouldReportStreamClose() {
19814
+ return !this.connecting && !this.blocking;
19815
+ }
19816
+ handleStreamClose(url2Connect) {
19817
+ const debugLine = string_summarize(`${PIPE_SYMBOL}Stream has closed:`, {
19818
+ connecting: this.connecting,
19819
+ connected: this.connected,
19820
+ userMediaLoaded: this.userMediaLoaded,
19821
+ blocking: this.blocking
19822
+ });
19823
+ this.options.logger.debug(debugLine);
19824
+ const canReconnect = this.canReconnectAfterStreamClose();
19825
+ this.connected = false;
19826
+ if (this.shouldIgnoreStreamClose()) return;
19827
+ if (this.mediaTransmissionStarted) this.failInterruptedRecording();
19828
+ else if (canReconnect) {
19829
+ this.pendingWrites.clear();
19830
+ this.streamBackpressured = false;
19831
+ this.resumeAfterDrain = false;
19832
+ this.reconnecting = true;
19833
+ this.initSocket();
19834
+ } else if (this.shouldReportStreamClose()) window.setTimeout(()=>{
19835
+ this.handleConnectionFailure({
19836
+ url2Connect,
19837
+ cause: "closed"
19838
+ });
19839
+ }, 0);
19840
+ }
19841
+ shouldIgnoreStreamClose() {
19842
+ return this.recordingTransportFailed || Boolean(this.unloaded);
19843
+ }
19655
19844
  sendPings() {
19656
19845
  this.stopPings();
19657
19846
  this.pingInterval = window.setInterval(()=>{
@@ -19665,7 +19854,9 @@ var __webpack_exports__ = {};
19665
19854
  this.pingInterval = void 0;
19666
19855
  }
19667
19856
  onAudioSample(audioSample) {
19857
+ if (this.recordingTransportFailed) return;
19668
19858
  this.samplesCount++;
19859
+ this.mediaTransmissionStarted = true;
19669
19860
  const audioBuffer = audioSample.toBuffer();
19670
19861
  this.writeStream(audioBuffer);
19671
19862
  }
@@ -19674,7 +19865,7 @@ var __webpack_exports__ = {};
19674
19865
  }
19675
19866
  onUserMediaReady(params) {
19676
19867
  try {
19677
- this.options.logger.debug(`Recorder: onUserMediaReady(${params ? util_pretty(params) : ""})`);
19868
+ this.options.logger.debug(`Recorder: onUserMediaReady(${params ? string_pretty(params) : ""})`);
19678
19869
  const switchingFacingMode = null == params ? void 0 : params.switchingFacingMode;
19679
19870
  this.userMediaLoading = this.blocking = this.unloaded = this.submitting = false;
19680
19871
  this.userMediaLoaded = true;
@@ -19705,6 +19896,11 @@ var __webpack_exports__ = {};
19705
19896
  window.clearTimeout(this.connectionTimeout);
19706
19897
  this.connectionTimeout = void 0;
19707
19898
  }
19899
+ clearBackpressureTimeout() {
19900
+ if (void 0 === this.backpressureTimeout) return;
19901
+ window.clearTimeout(this.backpressureTimeout);
19902
+ this.backpressureTimeout = void 0;
19903
+ }
19708
19904
  clearReconnectTimeout() {
19709
19905
  if (void 0 === this.reconnectTimeout) return;
19710
19906
  this.options.logger.debug("Recorder: clearReconnectTimeout()");
@@ -19716,7 +19912,7 @@ var __webpack_exports__ = {};
19716
19912
  this.failConnection(params);
19717
19913
  }
19718
19914
  retryConnection(params) {
19719
- if (!this.reconnecting || !this.userMediaLoaded || !this.isOnline() || this.unloaded || this.blocking) return false;
19915
+ if (!this.canRetryConnection()) return false;
19720
19916
  if (void 0 !== this.reconnectTimeout) return true;
19721
19917
  const delayMs = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 10000);
19722
19918
  this.reconnectAttempts++;
@@ -19726,12 +19922,22 @@ var __webpack_exports__ = {};
19726
19922
  this.options.logger.debug(`Recorder: retrying WebSocket connection in ${delayMs}ms (cause ${params.cause}).`);
19727
19923
  this.reconnectTimeout = window.setTimeout(()=>{
19728
19924
  this.reconnectTimeout = void 0;
19729
- if (this.reconnecting && !this.unloaded && !this.blocking) this.initSocket();
19925
+ if (this.shouldContinueReconnect()) this.initSocket();
19730
19926
  }, delayMs);
19731
19927
  return true;
19732
19928
  }
19929
+ canRetryConnection() {
19930
+ return Boolean(this.reconnecting && this.userMediaLoaded && this.isOnline() && !this.unloaded && !this.blocking);
19931
+ }
19932
+ shouldContinueReconnect() {
19933
+ return this.reconnecting && !this.unloaded && !this.blocking;
19934
+ }
19733
19935
  discardSocket() {
19734
19936
  this.options.logger.debug("Recorder: discarding socket stream ...");
19937
+ this.clearBackpressureTimeout();
19938
+ this.pendingWrites.clear();
19939
+ this.streamBackpressured = false;
19940
+ this.resumeAfterDrain = false;
19735
19941
  const stream = this.stream;
19736
19942
  this.stream = void 0;
19737
19943
  if (stream && !stream.destroyed) stream.destroy();
@@ -19741,7 +19947,7 @@ var __webpack_exports__ = {};
19741
19947
  }
19742
19948
  failConnection(params) {
19743
19949
  var _this_stream;
19744
- if (this.connectionFailed || this.connected || this.unloaded) return;
19950
+ if (this.shouldIgnoreConnectionFailure()) return;
19745
19951
  this.connectionFailed = true;
19746
19952
  this.connecting = false;
19747
19953
  this.reconnecting = false;
@@ -19771,7 +19977,7 @@ var __webpack_exports__ = {};
19771
19977
  blocking: this.blocking,
19772
19978
  visibilityState: document.visibilityState
19773
19979
  };
19774
- const debugLine = util_summarize("Recorder: failConnection() diagnostic", contents);
19980
+ const debugLine = string_summarize("Recorder: failConnection() diagnostic", contents);
19775
19981
  this.options.logger.debug(debugLine);
19776
19982
  let explanation;
19777
19983
  if (online) if ("timeout" === cause) explanation = `The server at ${url2Connect} did not respond within ${this.options.timeouts.connection}ms, even though your device is online. This usually points to a firewall or proxy silently dropping the connection. Please try a different network. If the problem persists, contact us.`;
@@ -19795,6 +20001,9 @@ var __webpack_exports__ = {};
19795
20001
  err
19796
20002
  });
19797
20003
  }
20004
+ shouldIgnoreConnectionFailure() {
20005
+ return this.connectionFailed || this.connected || Boolean(this.unloaded);
20006
+ }
19798
20007
  calculateFrameProgress() {
19799
20008
  return `${(this.confirmedFrameNumber / (this.framesCount || 1) * 100).toFixed(2)}%`;
19800
20009
  }
@@ -19844,6 +20053,9 @@ var __webpack_exports__ = {};
19844
20053
  options: this.options
19845
20054
  });
19846
20055
  const hasAudio = this.samplesCount > 0;
20056
+ this.mediaTransmissionStarted = false;
20057
+ this.recordingActive = false;
20058
+ this.recordingTransportFailed = false;
19847
20059
  this.confirmedFrameNumber = this.confirmedSampleNumber = this.samplesCount = this.framesCount = 0;
19848
20060
  this.sampleProgress = this.frameProgress = void 0;
19849
20061
  this.key = args.key;
@@ -19945,7 +20157,8 @@ var __webpack_exports__ = {};
19945
20157
  err
19946
20158
  });
19947
20159
  }
19948
- if (this.stream) {
20160
+ const stream = this.stream;
20161
+ if (stream) {
19949
20162
  const connectionTimeoutMs = this.options.timeouts.connection;
19950
20163
  this.connectionTimeout = window.setTimeout(()=>{
19951
20164
  if (this.isOnline() && this.isUserMediaLoaded()) {
@@ -19960,29 +20173,12 @@ var __webpack_exports__ = {};
19960
20173
  cause: "timeout"
19961
20174
  });
19962
20175
  }, connectionTimeoutMs);
19963
- this.stream.on("close", ()=>{
19964
- const debugLine = util_summarize(`${PIPE_SYMBOL}Stream has closed:`, {
19965
- connecting: this.connecting,
19966
- connected: this.connected,
19967
- userMediaLoaded: this.userMediaLoaded,
19968
- blocking: this.blocking
19969
- });
19970
- this.options.logger.debug(debugLine);
19971
- const tryReconnect = this.connected && this.userMediaLoaded;
19972
- this.connected = false;
19973
- if (tryReconnect) {
19974
- this.reconnecting = true;
19975
- this.initSocket();
19976
- } else if (!this.connecting && !this.blocking) window.setTimeout(()=>{
19977
- this.handleConnectionFailure({
19978
- url2Connect,
19979
- cause: "closed"
19980
- });
19981
- }, 0);
20176
+ stream.on("close", ()=>{
20177
+ this.handleStreamClose(url2Connect);
19982
20178
  });
19983
- this.stream.on("connect", (args)=>{
20179
+ stream.on("connect", (args)=>{
19984
20180
  var _this_stream;
19985
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *connect* event emitted with args: ${util_pretty(args)}`);
20181
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *connect* event emitted with args: ${string_pretty(args)}`);
19986
20182
  this.clearConnectionTimeout();
19987
20183
  const isClosing = (null == (_this_stream = this.stream) ? void 0 : _this_stream.socket.readyState) === WebSocket.CLOSING;
19988
20184
  if (!this.connected && !isClosing && !this.unloaded) {
@@ -19995,7 +20191,7 @@ var __webpack_exports__ = {};
19995
20191
  null == cb || cb();
19996
20192
  }
19997
20193
  });
19998
- this.stream.on("data", (data)=>{
20194
+ stream.on("data", (data)=>{
19999
20195
  this.options.logger.debug(`${PIPE_SYMBOL}Stream *data* event emitted`);
20000
20196
  try {
20001
20197
  const command = JSON.parse(data.toString());
@@ -20013,11 +20209,11 @@ var __webpack_exports__ = {};
20013
20209
  });
20014
20210
  }
20015
20211
  });
20016
- this.stream.on("error", (err)=>{
20212
+ stream.on("error", (err)=>{
20017
20213
  var _this_lastSocketError;
20018
20214
  if ("u" > typeof Event && err instanceof Event) this.lastSocketError = error_getEventDetails(err);
20019
20215
  else this.lastSocketError = serializeError(err);
20020
- const debugLine = util_summarize(`${PIPE_SYMBOL}Stream *error* event emitted:`, {
20216
+ const debugLine = string_summarize(`${PIPE_SYMBOL}Stream *error* event emitted:`, {
20021
20217
  error: serializeError(err)
20022
20218
  });
20023
20219
  this.options.logger.debug(debugLine);
@@ -20028,47 +20224,45 @@ var __webpack_exports__ = {};
20028
20224
  const streamError = err instanceof Error ? err : new Error("WebSocket stream emitted an error event", {
20029
20225
  cause: null != (_this_lastSocketError = this.lastSocketError) ? _this_lastSocketError : err
20030
20226
  });
20227
+ if (this.mediaTransmissionStarted) return void this.failInterruptedRecording();
20031
20228
  this.emit("ERROR", {
20032
20229
  err: error_createError({
20033
20230
  message: "WebSocket stream error",
20034
- explanation: `The WebSocket stream emitted an error event. Details: ${util_pretty(err)}`,
20231
+ explanation: `The WebSocket stream emitted an error event. Details: ${string_pretty(err)}`,
20035
20232
  options: this.options,
20036
20233
  exc: streamError
20037
20234
  })
20038
20235
  });
20039
20236
  });
20040
- this.stream.on("drain", ()=>{
20041
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *drain* event emitted (should not happen!)`);
20237
+ stream.on("drain", ()=>{
20238
+ this.handleStreamDrain(stream);
20042
20239
  });
20043
- this.stream.on("preend", (args)=>{
20044
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *preend* event emitted with args: ${util_pretty(args)}`);
20240
+ stream.on("preend", (args)=>{
20241
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *preend* event emitted with args: ${string_pretty(args)}`);
20045
20242
  });
20046
- this.stream.on("end", ()=>{
20243
+ stream.on("end", ()=>{
20047
20244
  this.options.logger.debug(`${PIPE_SYMBOL}Stream *end* event emitted`);
20048
20245
  });
20049
- this.stream.on("drain", (args)=>{
20050
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *drain* event emitted with args: ${util_pretty(args)}`);
20246
+ stream.on("pipe", (src)=>{
20247
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *pipe* event emitted with src: ${string_pretty(src)}`);
20051
20248
  });
20052
- this.stream.on("pipe", (src)=>{
20053
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *pipe* event emitted with src: ${util_pretty(src)}`);
20249
+ stream.on("unpipe", (src)=>{
20250
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *unpipe* event emitted with src: ${string_pretty(src)}`);
20054
20251
  });
20055
- this.stream.on("unpipe", (src)=>{
20056
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *unpipe* event emitted with src: ${util_pretty(src)}`);
20252
+ stream.on("resume", (args)=>{
20253
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *resume* event emitted with args: ${string_pretty(args)}`);
20057
20254
  });
20058
- this.stream.on("resume", (args)=>{
20059
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *resume* event emitted with args: ${util_pretty(args)}`);
20255
+ stream.on("uncork", (args)=>{
20256
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *uncork* event emitted with args: ${string_pretty(args)}`);
20060
20257
  });
20061
- this.stream.on("uncork", (args)=>{
20062
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *uncork* event emitted with args: ${util_pretty(args)}`);
20258
+ stream.on("readable", (args)=>{
20259
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *readable* event emitted with args: ${string_pretty(args)}`);
20063
20260
  });
20064
- this.stream.on("readable", (args)=>{
20065
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *readable* event emitted with args: ${util_pretty(args)}`);
20261
+ stream.on("prefinish", (args)=>{
20262
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *prefinish* event emitted with args: ${string_pretty(args)}`);
20066
20263
  });
20067
- this.stream.on("prefinish", (args)=>{
20068
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *prefinish* event emitted with args: ${util_pretty(args)}`);
20069
- });
20070
- this.stream.on("finish", (args)=>{
20071
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *finish* event emitted with args: ${util_pretty(args)}`);
20264
+ stream.on("finish", (args)=>{
20265
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *finish* event emitted with args: ${string_pretty(args)}`);
20072
20266
  });
20073
20267
  }
20074
20268
  }
@@ -20082,11 +20276,11 @@ var __webpack_exports__ = {};
20082
20276
  }
20083
20277
  userMediaErrorCallback(err, usedConstraints) {
20084
20278
  var _this_userMedia;
20085
- if (this.unloaded) return void this.options.logger.debug(`Recorder: already unloaded. Not going to throw error ${util_pretty(err)}`);
20279
+ if (this.unloaded) return void this.options.logger.debug(`Recorder: already unloaded. Not going to throw error ${string_pretty(err)}`);
20086
20280
  this.userMediaLoading = false;
20087
20281
  this.clearUserMediaTimeout();
20088
20282
  const characteristics = null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.getCharacteristics();
20089
- this.options.logger.debug(`Recorder: userMediaErrorCallback(), name: ${err.name}, message: ${err.message} and Webcam characteristics: ${characteristics ? util_pretty(characteristics) : "none"}`);
20283
+ this.options.logger.debug(`Recorder: userMediaErrorCallback(), name: ${err.name}, message: ${err.message} and Webcam characteristics: ${characteristics ? string_pretty(characteristics) : "none"}`);
20090
20284
  const errorListeners = this.getListeners("ERROR");
20091
20285
  if (null == errorListeners ? void 0 : errorListeners.length) if (err.name !== error_VideomailError.MEDIA_DEVICE_NOT_SUPPORTED) {
20092
20286
  const videomailError = error_createError({
@@ -20098,14 +20292,14 @@ var __webpack_exports__ = {};
20098
20292
  err: videomailError
20099
20293
  });
20100
20294
  } else {
20101
- this.options.logger.debug(`Recorder: ignore user media error ${util_pretty(err)}`);
20295
+ this.options.logger.debug(`Recorder: ignore user media error ${string_pretty(err)}`);
20102
20296
  this.retryTimeout = window.setTimeout(()=>{
20103
20297
  this.retryTimeout = void 0;
20104
20298
  if (!this.unloaded) this.loadUserMedia();
20105
20299
  }, this.options.timeouts.userMedia);
20106
20300
  }
20107
20301
  else {
20108
- this.options.logger.debug(`Recorder: no error listeners attached but throwing error ${util_pretty(err)}`);
20302
+ this.options.logger.debug(`Recorder: no error listeners attached but throwing error ${string_pretty(err)}`);
20109
20303
  throw error_createError({
20110
20304
  err,
20111
20305
  message: "Unable to process this error since there are no error listeners anymore.",
@@ -20123,7 +20317,7 @@ var __webpack_exports__ = {};
20123
20317
  options: this.options
20124
20318
  });
20125
20319
  }
20126
- this.options.logger.debug(`Recorder: getUserMediaCallback(${params ? util_pretty(params) : ""})`);
20320
+ this.options.logger.debug(`Recorder: getUserMediaCallback(${params ? string_pretty(params) : ""})`);
20127
20321
  if (this.showUserMedia()) try {
20128
20322
  this.userMedia.init(localStream, ()=>{
20129
20323
  if (!this.unloaded) this.onUserMediaReady(params);
@@ -20151,7 +20345,7 @@ var __webpack_exports__ = {};
20151
20345
  }
20152
20346
  }
20153
20347
  loadGenuineUserMedia(params) {
20154
- this.options.logger.debug(`Recorder: loadGenuineUserMedia(${params ? util_pretty(params) : ""})`);
20348
+ this.options.logger.debug(`Recorder: loadGenuineUserMedia(${params ? string_pretty(params) : ""})`);
20155
20349
  this.emit("ASKING_WEBCAM_PERMISSION");
20156
20350
  this.userMediaLoading = true;
20157
20351
  const constraints = {
@@ -20162,26 +20356,9 @@ var __webpack_exports__ = {};
20162
20356
  },
20163
20357
  audio: isAudioEnabled(this.options)
20164
20358
  };
20165
- if ((null == params ? void 0 : params.switchingFacingMode) && constraints.video && true !== constraints.video) constraints.video.facingMode = params.switchingFacingMode;
20166
- if (this.options.video.width && constraints.video && true !== constraints.video) {
20167
- const idealWidth = this.options.video.width;
20168
- if (idealWidth) constraints.video.width = {
20169
- ideal: idealWidth
20170
- };
20171
- } else if (constraints.video && true !== constraints.video) {
20172
- const limitedWidth = this.limitWidth();
20173
- if (null == limitedWidth ? void 0 : limitedWidth.value) constraints.video.width = {
20174
- ideal: limitedWidth.value
20175
- };
20176
- }
20177
- if (this.options.video.height && constraints.video && true !== constraints.video) {
20178
- const idealHeight = this.options.video.height;
20179
- if (idealHeight) constraints.video.height = {
20180
- ideal: idealHeight
20181
- };
20182
- }
20183
- this.options.logger.debug(util_summarize("Recorder: our webcam constraints are:", constraints));
20184
- this.options.logger.debug(util_summarize("Recorder: available webcam constraints are:", navigator.mediaDevices.getSupportedConstraints()));
20359
+ this.configureVideoConstraints(constraints, params);
20360
+ this.options.logger.debug(string_summarize("Recorder: our webcam constraints are:", constraints));
20361
+ this.options.logger.debug(string_summarize("Recorder: available webcam constraints are:", navigator.mediaDevices.getSupportedConstraints()));
20185
20362
  const streamPromise = navigator.mediaDevices.getUserMedia(constraints);
20186
20363
  streamPromise.then((localStream)=>{
20187
20364
  if (this.unloaded) return void localStream.getTracks().forEach((track)=>{
@@ -20192,13 +20369,30 @@ var __webpack_exports__ = {};
20192
20369
  if (!this.unloaded) this.userMediaErrorCallback(reason, constraints);
20193
20370
  });
20194
20371
  }
20372
+ configureVideoConstraints(constraints, params) {
20373
+ const videoConstraints = "object" == typeof constraints.video ? constraints.video : void 0;
20374
+ if (!videoConstraints) return;
20375
+ if (null == params ? void 0 : params.switchingFacingMode) videoConstraints.facingMode = params.switchingFacingMode;
20376
+ if (this.options.video.width) videoConstraints.width = {
20377
+ ideal: this.options.video.width
20378
+ };
20379
+ else {
20380
+ const limitedWidth = this.limitWidth();
20381
+ if (null == limitedWidth ? void 0 : limitedWidth.value) videoConstraints.width = {
20382
+ ideal: limitedWidth.value
20383
+ };
20384
+ }
20385
+ if (this.options.video.height) videoConstraints.height = {
20386
+ ideal: this.options.video.height
20387
+ };
20388
+ }
20195
20389
  loadUserMedia(params) {
20196
20390
  if (this.userMediaLoaded) {
20197
20391
  this.options.logger.debug("Recorder: skipping loadUserMedia() because it is already loaded");
20198
20392
  this.onUserMediaReady(params);
20199
20393
  return;
20200
20394
  } else if (this.userMediaLoading) return void this.options.logger.debug("Recorder: skipping loadUserMedia() because it is already asking for permission");
20201
- this.options.logger.debug(`Recorder: loadUserMedia(${params ? util_pretty(params) : ""})`);
20395
+ this.options.logger.debug(`Recorder: loadUserMedia(${params ? string_pretty(params) : ""})`);
20202
20396
  this.emit("LOADING_USER_MEDIA");
20203
20397
  try {
20204
20398
  if (!navigator.mediaDevices) throw new Error("No media devices are available.");
@@ -20231,7 +20425,7 @@ var __webpack_exports__ = {};
20231
20425
  if (this.unloaded) return;
20232
20426
  try {
20233
20427
  if (command.args) {
20234
- const debugLine = util_summarize(`Server commanded: ${command.command} with:`, command.args);
20428
+ const debugLine = string_summarize(`Server commanded: ${command.command} with:`, command.args);
20235
20429
  this.options.logger.debug(debugLine);
20236
20430
  } else this.options.logger.debug(`Server commanded: ${command.command}`);
20237
20431
  switch(command.command){
@@ -20298,7 +20492,7 @@ var __webpack_exports__ = {};
20298
20492
  writeCommand(command, args, cb) {
20299
20493
  if (this.connected) {
20300
20494
  if (this.stream) {
20301
- if (args) this.options.logger.debug(`$ ${command} with ${util_pretty(args)}`);
20495
+ if (args) this.options.logger.debug(`$ ${command} with ${string_pretty(args)}`);
20302
20496
  else this.options.logger.debug(`$ ${command}`);
20303
20497
  const commandObj = {
20304
20498
  command,
@@ -20326,15 +20520,20 @@ var __webpack_exports__ = {};
20326
20520
  return this.loop.getElapsedTime();
20327
20521
  }
20328
20522
  getAvgInterval() {
20329
- const intervalSum = this.getIntervalSum();
20330
- if (void 0 === intervalSum || intervalSum <= 0) return;
20523
+ var _this_getIntervalSum;
20524
+ const intervalSum = null != (_this_getIntervalSum = this.getIntervalSum()) ? _this_getIntervalSum : 0;
20525
+ if (!this.hasValidInterval(intervalSum)) return;
20331
20526
  return intervalSum / this.framesCount;
20332
20527
  }
20333
20528
  getAvgFps() {
20334
- const intervalSum = this.getIntervalSum();
20335
- if (void 0 === intervalSum || intervalSum <= 0) return;
20529
+ var _this_getIntervalSum;
20530
+ const intervalSum = null != (_this_getIntervalSum = this.getIntervalSum()) ? _this_getIntervalSum : 0;
20531
+ if (!this.hasValidInterval(intervalSum)) return;
20336
20532
  return this.framesCount / intervalSum * 1000;
20337
20533
  }
20534
+ hasValidInterval(intervalSum) {
20535
+ return intervalSum > 0;
20536
+ }
20338
20537
  getRecordingStats() {
20339
20538
  return this.recordingStats;
20340
20539
  }
@@ -20345,7 +20544,8 @@ var __webpack_exports__ = {};
20345
20544
  stop(params) {
20346
20545
  var _this_loop;
20347
20546
  if (!this.userMedia) throw new Error("No user media defined, unable to stop");
20348
- this.options.logger.debug(`Recorder: stop(${params ? util_pretty(params) : ""})`);
20547
+ this.options.logger.debug(`Recorder: stop(${params ? string_pretty(params) : ""})`);
20548
+ this.recordingActive = false;
20349
20549
  const limitReached = null == params ? void 0 : params.limitReached;
20350
20550
  this.emit("STOPPING", {
20351
20551
  limitReached
@@ -20402,6 +20602,8 @@ var __webpack_exports__ = {};
20402
20602
  if (e) cause = e.type;
20403
20603
  const prettyCause = cause ? `, cause: ${cause}` : "";
20404
20604
  this.options.logger.debug(`Recorder: unload()${prettyCause}`);
20605
+ this.recordingActive = false;
20606
+ this.mediaTransmissionStarted = false;
20405
20607
  this.reset();
20406
20608
  this.recordingDimensions = void 0;
20407
20609
  this.clearUserMediaTimeout();
@@ -20452,7 +20654,7 @@ var __webpack_exports__ = {};
20452
20654
  }
20453
20655
  pause(params) {
20454
20656
  var _this_userMedia;
20455
- if (params) this.options.logger.debug(`pause() at frame ${this.framesCount} with ${util_pretty(params)}`);
20657
+ if (params) this.options.logger.debug(`pause() at frame ${this.framesCount} with ${string_pretty(params)}`);
20456
20658
  else this.options.logger.debug(`pause() at frame ${this.framesCount}`);
20457
20659
  null == (_this_userMedia = this.userMedia) || _this_userMedia.pause();
20458
20660
  this.loop.stop();
@@ -20465,13 +20667,15 @@ var __webpack_exports__ = {};
20465
20667
  this.stopPings();
20466
20668
  this.emit("RESUMING");
20467
20669
  null == (_this_userMedia = this.userMedia) || _this_userMedia.resume();
20468
- this.loop.start();
20670
+ if (this.streamBackpressured) this.resumeAfterDrain = true;
20671
+ else this.loop.start();
20469
20672
  }
20470
20673
  onFlushed(opts) {
20471
20674
  const frameNumber = opts.frameNumber;
20472
20675
  if (1 === frameNumber) this.emit("FIRST_FRAME_SENT");
20473
20676
  }
20474
20677
  draw(_deltaTime, elapsedTime) {
20678
+ if (this.recordingTransportFailed) return;
20475
20679
  if (!this.userMedia) throw new Error("No user media defined, unable to draw on canvas");
20476
20680
  try {
20477
20681
  if (!this.isPaused() && this.stream && this.ctx) {
@@ -20492,6 +20696,7 @@ var __webpack_exports__ = {};
20492
20696
  this.recordingBuffer,
20493
20697
  frameControlBuffer
20494
20698
  ]);
20699
+ this.mediaTransmissionStarted = true;
20495
20700
  this.writeStream(frameBuffer, {
20496
20701
  frameNumber: this.framesCount,
20497
20702
  onFlushedCallback: this.onFlushed.bind(this)
@@ -20587,6 +20792,9 @@ var __webpack_exports__ = {};
20587
20792
  };
20588
20793
  this.frame = new canvas_to_buffer_modern_r(this.canvas, this.options.image.types, this.options.image.quality);
20589
20794
  this.options.logger.debug("Recorder: record()");
20795
+ this.recordingActive = true;
20796
+ this.recordingTransportFailed = false;
20797
+ this.mediaTransmissionStarted = false;
20590
20798
  this.userMedia.record();
20591
20799
  this.emit("RECORDING", {
20592
20800
  framesCount: this.framesCount
@@ -20651,7 +20859,7 @@ var __webpack_exports__ = {};
20651
20859
  if (!util_getBrowser(this.options).isMobile()) return;
20652
20860
  if ("user" === this.facingMode) this.facingMode = "environment";
20653
20861
  else if ("environment" === this.facingMode) this.facingMode = "user";
20654
- else this.options.logger.warn(`Recorder: unsupported facing mode ${util_pretty(this.facingMode)}`);
20862
+ else this.options.logger.warn(`Recorder: unsupported facing mode ${string_pretty(this.facingMode)}`);
20655
20863
  this.loadGenuineUserMedia({
20656
20864
  switchingFacingMode: this.facingMode
20657
20865
  });
@@ -20840,7 +21048,7 @@ var __webpack_exports__ = {};
20840
21048
  return this.userMediaLoaded;
20841
21049
  }
20842
21050
  constructor(visuals, replay, options){
20843
- super("Recorder", options), recorder_define_property(this, "visuals", void 0), recorder_define_property(this, "replay", void 0), recorder_define_property(this, "loop", void 0), recorder_define_property(this, "originalAnimationFrameObject", void 0), recorder_define_property(this, "samplesCount", 0), recorder_define_property(this, "framesCount", 0), recorder_define_property(this, "recordingStats", void 0), recorder_define_property(this, "confirmedFrameNumber", 0), recorder_define_property(this, "confirmedSampleNumber", 0), recorder_define_property(this, "recorderElement", void 0), recorder_define_property(this, "userMedia", void 0), recorder_define_property(this, "userMediaTimeout", void 0), recorder_define_property(this, "retryTimeout", void 0), recorder_define_property(this, "reconnectTimeout", void 0), recorder_define_property(this, "connectionTimeout", void 0), recorder_define_property(this, "stopTimeout", void 0), recorder_define_property(this, "frameProgress", void 0), recorder_define_property(this, "sampleProgress", void 0), recorder_define_property(this, "canvas", void 0), recorder_define_property(this, "recordingDimensions", void 0), recorder_define_property(this, "ctx", void 0), recorder_define_property(this, "userMediaLoaded", void 0), recorder_define_property(this, "userMediaLoading", false), recorder_define_property(this, "submitting", false), recorder_define_property(this, "unloaded", void 0), recorder_define_property(this, "stopTime", void 0), recorder_define_property(this, "stream", void 0), recorder_define_property(this, "connecting", false), recorder_define_property(this, "connected", false), recorder_define_property(this, "connectionFailed", false), recorder_define_property(this, "reconnecting", false), recorder_define_property(this, "reconnectAttempts", 0), recorder_define_property(this, "blocking", false), recorder_define_property(this, "built", false), recorder_define_property(this, "key", void 0), recorder_define_property(this, "waitingTime", void 0), recorder_define_property(this, "connectingStartedAt", void 0), recorder_define_property(this, "lastCloseEvent", void 0), recorder_define_property(this, "lastSocketError", void 0), recorder_define_property(this, "pingInterval", void 0), recorder_define_property(this, "frame", void 0), recorder_define_property(this, "recordingBuffer", void 0), recorder_define_property(this, "facingMode", void 0);
21051
+ super("Recorder", options), recorder_define_property(this, "visuals", void 0), recorder_define_property(this, "replay", void 0), recorder_define_property(this, "pendingWrites", new boundedWriteQueue()), recorder_define_property(this, "loop", void 0), recorder_define_property(this, "originalAnimationFrameObject", void 0), recorder_define_property(this, "samplesCount", 0), recorder_define_property(this, "framesCount", 0), recorder_define_property(this, "recordingStats", void 0), recorder_define_property(this, "confirmedFrameNumber", 0), recorder_define_property(this, "confirmedSampleNumber", 0), recorder_define_property(this, "recorderElement", void 0), recorder_define_property(this, "userMedia", void 0), recorder_define_property(this, "userMediaTimeout", void 0), recorder_define_property(this, "retryTimeout", void 0), recorder_define_property(this, "reconnectTimeout", void 0), recorder_define_property(this, "connectionTimeout", void 0), recorder_define_property(this, "backpressureTimeout", void 0), recorder_define_property(this, "stopTimeout", void 0), recorder_define_property(this, "frameProgress", void 0), recorder_define_property(this, "sampleProgress", void 0), recorder_define_property(this, "canvas", void 0), recorder_define_property(this, "recordingDimensions", void 0), recorder_define_property(this, "ctx", void 0), recorder_define_property(this, "userMediaLoaded", void 0), recorder_define_property(this, "userMediaLoading", false), recorder_define_property(this, "submitting", false), recorder_define_property(this, "unloaded", void 0), recorder_define_property(this, "stopTime", void 0), recorder_define_property(this, "stream", void 0), recorder_define_property(this, "streamBackpressured", false), recorder_define_property(this, "resumeAfterDrain", false), recorder_define_property(this, "mediaTransmissionStarted", false), recorder_define_property(this, "recordingActive", false), recorder_define_property(this, "recordingTransportFailed", false), recorder_define_property(this, "connecting", false), recorder_define_property(this, "connected", false), recorder_define_property(this, "connectionFailed", false), recorder_define_property(this, "reconnecting", false), recorder_define_property(this, "reconnectAttempts", 0), recorder_define_property(this, "blocking", false), recorder_define_property(this, "built", false), recorder_define_property(this, "key", void 0), recorder_define_property(this, "waitingTime", void 0), recorder_define_property(this, "connectingStartedAt", void 0), recorder_define_property(this, "lastCloseEvent", void 0), recorder_define_property(this, "lastSocketError", void 0), recorder_define_property(this, "pingInterval", void 0), recorder_define_property(this, "frame", void 0), recorder_define_property(this, "recordingBuffer", void 0), recorder_define_property(this, "facingMode", void 0);
20844
21052
  this.visuals = visuals;
20845
21053
  this.replay = replay;
20846
21054
  this.facingMode = options.video.facingMode;
@@ -20949,7 +21157,7 @@ var __webpack_exports__ = {};
20949
21157
  }
20950
21158
  build(replayParentElement) {
20951
21159
  var _this_visuals_getElement;
20952
- this.options.logger.debug(`Replay: build (replayParentElement="${util_pretty(replayParentElement)}")`);
21160
+ this.options.logger.debug(`Replay: build (replayParentElement="${string_pretty(replayParentElement)}")`);
20953
21161
  this.replayElement = null == (_this_visuals_getElement = this.visuals.getElement()) ? void 0 : _this_visuals_getElement.querySelector(`video.${this.options.selectors.replayClass}`);
20954
21162
  if (!this.replayElement) this.buildElement(replayParentElement);
20955
21163
  if (!this.replayElement) throw new Error("There is no replayElement to build on");
@@ -21136,7 +21344,7 @@ var __webpack_exports__ = {};
21136
21344
  }
21137
21345
  buildChildren(playerOnly = false, visualsElement) {
21138
21346
  if (!visualsElement) throw new Error("Unable to build children without a visuals element");
21139
- this.options.logger.debug(`Visuals: buildChildren (playerOnly = ${playerOnly}, visualsElement="${util_pretty(visualsElement)}"})`);
21347
+ this.options.logger.debug(`Visuals: buildChildren (playerOnly = ${playerOnly}, visualsElement="${string_pretty(visualsElement)}"})`);
21140
21348
  this.buildNoScriptTag();
21141
21349
  if (!playerOnly) {
21142
21350
  this.notifier.build();
@@ -21206,7 +21414,7 @@ var __webpack_exports__ = {};
21206
21414
  return this.recorderInsides.isCountingDown();
21207
21415
  }
21208
21416
  build(playerOnly = false, parentElement) {
21209
- const parentElementInfo = parentElement ? `, parentElement="${util_pretty(parentElement)}"` : "";
21417
+ const parentElementInfo = parentElement ? `, parentElement="${string_pretty(parentElement)}"` : "";
21210
21418
  this.options.logger.debug(`Visuals: build (playerOnly = ${playerOnly}${parentElementInfo})`);
21211
21419
  if (parentElement) this.visualsElement = parentElement.querySelector(`.${this.options.selectors.visualsClass}`);
21212
21420
  else this.visualsElement = this.container.querySelector(`.${this.options.selectors.visualsClass}`);
@@ -21267,7 +21475,7 @@ var __webpack_exports__ = {};
21267
21475
  unload(params) {
21268
21476
  if (!this.built) return;
21269
21477
  const e = null == params ? void 0 : params.e;
21270
- this.options.logger.debug(`Visuals: unload(${e ? util_pretty(e) : ""})`);
21478
+ this.options.logger.debug(`Visuals: unload(${e ? string_pretty(e) : ""})`);
21271
21479
  this.recorder.unload(params);
21272
21480
  this.recorderInsides.unload();
21273
21481
  this.replay.unload(params);
@@ -21457,14 +21665,14 @@ var __webpack_exports__ = {};
21457
21665
  }
21458
21666
  class Container extends util_Despot {
21459
21667
  buildChildren(playerOnly = false, parentElement) {
21460
- const parentElementInfo = parentElement ? `, parentElement="${util_pretty(parentElement)}"` : "";
21668
+ const parentElementInfo = parentElement ? `, parentElement="${string_pretty(parentElement)}"` : "";
21461
21669
  this.options.logger.debug(`Container: buildChildren (playerOnly = ${playerOnly}${parentElementInfo})`);
21462
21670
  if (this.containerElement) this.containerElement.classList.add(this.options.selectors.containerClass);
21463
21671
  if (!playerOnly) this.buttons.build();
21464
21672
  this.visuals.build(playerOnly, parentElement);
21465
21673
  }
21466
21674
  build(buildOptions) {
21467
- this.options.logger.debug(`Container: build (${buildOptions ? util_pretty(buildOptions) : ""})`);
21675
+ this.options.logger.debug(`Container: build (${buildOptions ? string_pretty(buildOptions) : ""})`);
21468
21676
  try {
21469
21677
  var _this_containerElement;
21470
21678
  const containerId = this.options.selectors.containerId;
@@ -21659,7 +21867,7 @@ var __webpack_exports__ = {};
21659
21867
  try {
21660
21868
  if (!this.built) return;
21661
21869
  const e = null == params ? void 0 : params.e;
21662
- this.options.logger.debug(`Container: unload(${e ? util_pretty(e) : ""})`);
21870
+ this.options.logger.debug(`Container: unload(${e ? string_pretty(e) : ""})`);
21663
21871
  this.emit("UNLOADING");
21664
21872
  this.unloadChildren(params);
21665
21873
  this.hide();