videomail-client 16.1.1 → 16.2.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.
@@ -1648,7 +1648,7 @@ var __webpack_modules__ = {
1648
1648
  return 0 === comparison || comparison & DOCUMENT_POSITION_CONTAINED_BY;
1649
1649
  }
1650
1650
  },
1651
- T (__unused_rspack_module, exports1, __webpack_require__) {
1651
+ TU (__unused_rspack_module, exports1, __webpack_require__) {
1652
1652
  function isArray(arg) {
1653
1653
  if (Array.isArray) return Array.isArray(arg);
1654
1654
  return '[object Array]' === objectToString(arg);
@@ -2113,7 +2113,7 @@ var __webpack_modules__ = {
2113
2113
  return keys;
2114
2114
  };
2115
2115
  module.exports = Duplex;
2116
- var util = Object.create(__webpack_require__("T"));
2116
+ var util = Object.create(__webpack_require__("TU"));
2117
2117
  util.inherits = __webpack_require__("c5");
2118
2118
  var Readable = __webpack_require__("rp");
2119
2119
  var Writable = __webpack_require__("pv");
@@ -2167,7 +2167,7 @@ var __webpack_modules__ = {
2167
2167
  "use strict";
2168
2168
  module.exports = PassThrough;
2169
2169
  var Transform = __webpack_require__("It");
2170
- var util = Object.create(__webpack_require__("T"));
2170
+ var util = Object.create(__webpack_require__("TU"));
2171
2171
  util.inherits = __webpack_require__("c5");
2172
2172
  util.inherits(PassThrough, Transform);
2173
2173
  function PassThrough(options) {
@@ -2199,7 +2199,7 @@ var __webpack_modules__ = {
2199
2199
  function _isUint8Array(obj) {
2200
2200
  return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
2201
2201
  }
2202
- var util = Object.create(__webpack_require__("T"));
2202
+ var util = Object.create(__webpack_require__("TU"));
2203
2203
  util.inherits = __webpack_require__("c5");
2204
2204
  var debugUtil = __webpack_require__("AN");
2205
2205
  var debug = void 0;
@@ -2826,7 +2826,7 @@ var __webpack_modules__ = {
2826
2826
  "use strict";
2827
2827
  module.exports = Transform;
2828
2828
  var Duplex = __webpack_require__("OO");
2829
- var util = Object.create(__webpack_require__("T"));
2829
+ var util = Object.create(__webpack_require__("TU"));
2830
2830
  util.inherits = __webpack_require__("c5");
2831
2831
  util.inherits(Transform, Duplex);
2832
2832
  function afterTransform(er, data) {
@@ -2926,7 +2926,7 @@ var __webpack_modules__ = {
2926
2926
  ].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
2927
2927
  var Duplex;
2928
2928
  Writable.WritableState = WritableState;
2929
- var util = Object.create(__webpack_require__("T"));
2929
+ var util = Object.create(__webpack_require__("TU"));
2930
2930
  util.inherits = __webpack_require__("c5");
2931
2931
  var internalUtil = {
2932
2932
  deprecate: __webpack_require__("NQ")
@@ -8248,7 +8248,7 @@ var __webpack_modules__ = {
8248
8248
  });
8249
8249
  });
8250
8250
  },
8251
- Sy (__unused_rspack_module, exports1, __webpack_require__) {
8251
+ S (__unused_rspack_module, exports1, __webpack_require__) {
8252
8252
  var process = __webpack_require__("zT");
8253
8253
  var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors || function(obj) {
8254
8254
  var keys = Object.keys(obj);
@@ -8727,7 +8727,7 @@ var __webpack_modules__ = {
8727
8727
  return keys;
8728
8728
  };
8729
8729
  module.exports = Duplex;
8730
- var util = Object.create(__webpack_require__("T"));
8730
+ var util = Object.create(__webpack_require__("TU"));
8731
8731
  util.inherits = __webpack_require__("c5");
8732
8732
  var Readable = __webpack_require__("w");
8733
8733
  var Writable = __webpack_require__("S5");
@@ -8781,7 +8781,7 @@ var __webpack_modules__ = {
8781
8781
  "use strict";
8782
8782
  module.exports = PassThrough;
8783
8783
  var Transform = __webpack_require__("Ge");
8784
- var util = Object.create(__webpack_require__("T"));
8784
+ var util = Object.create(__webpack_require__("TU"));
8785
8785
  util.inherits = __webpack_require__("c5");
8786
8786
  util.inherits(PassThrough, Transform);
8787
8787
  function PassThrough(options) {
@@ -8813,7 +8813,7 @@ var __webpack_modules__ = {
8813
8813
  function _isUint8Array(obj) {
8814
8814
  return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
8815
8815
  }
8816
- var util = Object.create(__webpack_require__("T"));
8816
+ var util = Object.create(__webpack_require__("TU"));
8817
8817
  util.inherits = __webpack_require__("c5");
8818
8818
  var debugUtil = __webpack_require__("eD");
8819
8819
  var debug = void 0;
@@ -9440,7 +9440,7 @@ var __webpack_modules__ = {
9440
9440
  "use strict";
9441
9441
  module.exports = Transform;
9442
9442
  var Duplex = __webpack_require__("S7");
9443
- var util = Object.create(__webpack_require__("T"));
9443
+ var util = Object.create(__webpack_require__("TU"));
9444
9444
  util.inherits = __webpack_require__("c5");
9445
9445
  util.inherits(Transform, Duplex);
9446
9446
  function afterTransform(er, data) {
@@ -9540,7 +9540,7 @@ var __webpack_modules__ = {
9540
9540
  ].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
9541
9541
  var Duplex;
9542
9542
  Writable.WritableState = WritableState;
9543
- var util = Object.create(__webpack_require__("T"));
9543
+ var util = Object.create(__webpack_require__("TU"));
9544
9544
  util.inherits = __webpack_require__("c5");
9545
9545
  var internalUtil = {
9546
9546
  deprecate: __webpack_require__("NQ")
@@ -11115,7 +11115,7 @@ var __webpack_exports__ = {};
11115
11115
  var client = __webpack_require__("Q");
11116
11116
  var client_default = /*#__PURE__*/ __webpack_require__.n(client);
11117
11117
  var package_namespaceObject = {
11118
- rE: "16.1.1"
11118
+ rE: "16.2.0"
11119
11119
  };
11120
11120
  function isAudioEnabled(options) {
11121
11121
  return Boolean(options.audio.enabled);
@@ -11127,7 +11127,7 @@ var __webpack_exports__ = {};
11127
11127
  function isAutoPauseEnabled(options) {
11128
11128
  return options.enableAutoPause && options.enablePause;
11129
11129
  }
11130
- var util = __webpack_require__("Sy");
11130
+ var util = __webpack_require__("S");
11131
11131
  var util_default = /*#__PURE__*/ __webpack_require__.n(util);
11132
11132
  function getEventDetails(event) {
11133
11133
  const eventWithErrorDetails = event;
@@ -15017,6 +15017,14 @@ var __webpack_exports__ = {};
15017
15017
  }
15018
15018
  Despot_define_property(Despot, "emitters", new WeakMap());
15019
15019
  const util_Despot = Despot;
15020
+ const EMAIL_SEPARATOR_REGEX = /[ ,]+/gu;
15021
+ function trimEmail(email) {
15022
+ return email.replace(EMAIL_SEPARATOR_REGEX, "");
15023
+ }
15024
+ function trimEmails(emails) {
15025
+ const trimmedEmails = emails.split(EMAIL_SEPARATOR_REGEX).map((item)=>item.trim()).filter(Boolean);
15026
+ return trimmedEmails;
15027
+ }
15020
15028
  function getValidity(element) {
15021
15029
  const validity = "validity" in element ? element.validity : void 0;
15022
15030
  return validity;
@@ -15036,14 +15044,6 @@ var __webpack_exports__ = {};
15036
15044
  element.style.removeProperty("display");
15037
15045
  }
15038
15046
  const html_showElement = showElement;
15039
- const EMAIL_SEPARATOR_REGEX = /[ ,]+/gu;
15040
- function trimEmail(email) {
15041
- return email.replace(EMAIL_SEPARATOR_REGEX, "");
15042
- }
15043
- function trimEmails(emails) {
15044
- const trimmedEmails = emails.split(EMAIL_SEPARATOR_REGEX).map((item)=>item.trim()).filter(Boolean);
15045
- return trimmedEmails;
15046
- }
15047
15047
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
15048
15048
  try {
15049
15049
  var info = gen[key](arg);
@@ -16837,11 +16837,11 @@ var __webpack_exports__ = {};
16837
16837
  const originalDocument = document1;
16838
16838
  const currentScript = originalDocument.currentScript;
16839
16839
  window1.DocumentFragment;
16840
- const HTMLTemplateElement = window1.HTMLTemplateElement, Node = window1.Node, Element = window1.Element, NodeFilter = window1.NodeFilter;
16840
+ const HTMLTemplateElement = window1.HTMLTemplateElement, Node = window1.Node, Element1 = window1.Element, NodeFilter = window1.NodeFilter;
16841
16841
  void 0 === window1.NamedNodeMap && (window1.NamedNodeMap || window1.MozNamedAttrMap);
16842
16842
  window1.HTMLFormElement;
16843
16843
  const DOMParser = window1.DOMParser, trustedTypes = window1.trustedTypes;
16844
- const ElementPrototype = Element.prototype;
16844
+ const ElementPrototype = Element1.prototype;
16845
16845
  const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
16846
16846
  const remove = lookupGetter(ElementPrototype, "remove");
16847
16847
  const removeAttributeNode = lookupGetter(ElementPrototype, "removeAttributeNode");
@@ -17924,6 +17924,20 @@ var __webpack_exports__ = {};
17924
17924
  return DOMPurify;
17925
17925
  }
17926
17926
  var purify_default = createDOMPurify();
17927
+ function isRecipientSelectionValid(recipients) {
17928
+ var _recipients_to, _recipients_cc, _recipients_bcc;
17929
+ const hasTo = Boolean(null == (_recipients_to = recipients.to) ? void 0 : _recipients_to.length);
17930
+ const hasCc = Boolean(null == (_recipients_cc = recipients.cc) ? void 0 : _recipients_cc.length);
17931
+ const hasBcc = Boolean(null == (_recipients_bcc = recipients.bcc) ? void 0 : _recipients_bcc.length);
17932
+ const hasConfiguredTo = "to" in recipients;
17933
+ const hasConfiguredCc = "cc" in recipients;
17934
+ const hasConfiguredBcc = "bcc" in recipients;
17935
+ let isValid = true;
17936
+ if (hasConfiguredTo) isValid = hasTo || hasConfiguredCc && hasCc || hasConfiguredBcc && hasBcc;
17937
+ else if (hasConfiguredCc) isValid = hasCc || !hasConfiguredBcc || hasBcc;
17938
+ return isValid;
17939
+ }
17940
+ const email_isRecipientSelectionValid = isRecipientSelectionValid;
17927
17941
  function limitHeight(height, options, calledFrom) {
17928
17942
  const dimension = {
17929
17943
  unit: "px"
@@ -18557,7 +18571,7 @@ var __webpack_exports__ = {};
18557
18571
  this.visuals = visuals;
18558
18572
  }
18559
18573
  }
18560
- const facingMode = FacingMode;
18574
+ const recorder_facingMode = FacingMode;
18561
18575
  function pausedNote_define_property(obj, key, value) {
18562
18576
  if (key in obj) Object.defineProperty(obj, key, {
18563
18577
  value: value,
@@ -18924,7 +18938,7 @@ var __webpack_exports__ = {};
18924
18938
  this.recordTimer = new recordTimer(visuals, this.recordNote, options);
18925
18939
  const browser = util_getBrowser(options);
18926
18940
  if (options.video.countdown) this.countdown = new countdown(visuals, options);
18927
- if (options.video.facingModeButton && browser.isMobile()) this.facingMode = new facingMode(visuals, options);
18941
+ if (options.video.facingModeButton && browser.isMobile()) this.facingMode = new recorder_facingMode(visuals, options);
18928
18942
  if (options.enablePause) this.pausedNote = new pausedNote(visuals, options);
18929
18943
  }
18930
18944
  }
@@ -19175,6 +19189,18 @@ var __webpack_exports__ = {};
19175
19189
  }
19176
19190
  }
19177
19191
  const notifier = Notifier;
19192
+ function summarize(title, contents) {
19193
+ const lines = Object.entries(contents).sort(([keyA], [keyB])=>keyA.localeCompare(keyB)).map(([key, value])=>{
19194
+ const formattedValue = void 0 === value ? "undefined" : "object" == typeof value ? string_pretty(value) : value;
19195
+ return ` • ${key}: ${formattedValue}`;
19196
+ });
19197
+ const line = [
19198
+ `🔎 ${title}`,
19199
+ ...lines
19200
+ ].join("\n");
19201
+ return line;
19202
+ }
19203
+ const string_summarize = summarize;
19178
19204
  var animitter = __webpack_require__("b6");
19179
19205
  var animitter_default = /*#__PURE__*/ __webpack_require__.n(animitter);
19180
19206
  var typedarray_to_buffer = __webpack_require__("E");
@@ -19238,46 +19264,6 @@ var __webpack_exports__ = {};
19238
19264
  canvas_to_buffer_modern_r.atob = void 0;
19239
19265
  var websocket_stream_stream = __webpack_require__("U");
19240
19266
  var stream_default = /*#__PURE__*/ __webpack_require__.n(websocket_stream_stream);
19241
- function boundedWriteQueue_define_property(obj, key, value) {
19242
- if (key in obj) Object.defineProperty(obj, key, {
19243
- value: value,
19244
- enumerable: true,
19245
- configurable: true,
19246
- writable: true
19247
- });
19248
- else obj[key] = value;
19249
- return obj;
19250
- }
19251
- const DEFAULT_MAX_QUEUED_BYTES = 1048576;
19252
- class BoundedWriteQueue {
19253
- enqueue(buffer, params) {
19254
- if (this.queuedBytes + buffer.length > this.maxBytes) return false;
19255
- this.writes.push({
19256
- buffer,
19257
- params
19258
- });
19259
- this.queuedBytes += buffer.length;
19260
- return true;
19261
- }
19262
- dequeue() {
19263
- const write = this.writes.shift();
19264
- if (write) this.queuedBytes -= write.buffer.length;
19265
- return write;
19266
- }
19267
- clear() {
19268
- this.writes.length = 0;
19269
- this.queuedBytes = 0;
19270
- }
19271
- constructor(maxBytes = DEFAULT_MAX_QUEUED_BYTES){
19272
- boundedWriteQueue_define_property(this, "maxBytes", void 0);
19273
- boundedWriteQueue_define_property(this, "writes", void 0);
19274
- boundedWriteQueue_define_property(this, "queuedBytes", void 0);
19275
- this.maxBytes = maxBytes;
19276
- this.writes = [];
19277
- this.queuedBytes = 0;
19278
- }
19279
- }
19280
- const boundedWriteQueue = BoundedWriteQueue;
19281
19267
  function getEdgeCodes(value, amount, fromEnd) {
19282
19268
  const chars = fromEnd ? value.slice(-amount) : value.slice(0, amount);
19283
19269
  const codes = Array.from(chars, (char)=>String(char.codePointAt(0))).join(".");
@@ -19357,117 +19343,11 @@ var __webpack_exports__ = {};
19357
19343
  };
19358
19344
  }
19359
19345
  const error_getWebSocketDiagnostic = getWebSocketDiagnostic;
19360
- function figureMinHeight(height, options) {
19361
- let minHeight;
19362
- if (options.video.height) {
19363
- minHeight = height ? Math.min(options.video.height, height) : options.video.height;
19364
- if (minHeight < 1) throw error_createError({
19365
- message: `Got a min height less than 1 (${minHeight})!`,
19366
- options
19367
- });
19368
- } else minHeight = height;
19369
- return minHeight;
19370
- }
19371
- const dimensions_figureMinHeight = figureMinHeight;
19372
- function getRatio(options, videoHeight, videoWidth) {
19373
- let ratio = 1;
19374
- const hasVideoDimensions = videoHeight && videoWidth;
19375
- const desiredHeight = options.video.height;
19376
- const desiredWidth = options.video.width;
19377
- const hasDesiredDimensions = desiredHeight && desiredWidth;
19378
- if (hasDesiredDimensions) ratio = hasVideoDimensions ? videoHeight < desiredHeight || videoWidth < desiredWidth ? videoHeight / videoWidth : desiredHeight / desiredWidth : desiredHeight / desiredWidth;
19379
- else if (hasVideoDimensions) ratio = videoHeight / videoWidth;
19380
- return ratio;
19381
- }
19382
- const dimensions_getRatio = getRatio;
19383
- function calculateHeight(responsive, videoWidth, options, ratio, element) {
19384
- const dimension = {
19385
- unit: "px"
19386
- };
19387
- let width = videoWidth;
19388
- if (responsive && element) {
19389
- const limitedDimension = dimensions_limitWidth(element, options, width);
19390
- width = limitedDimension.value;
19391
- }
19392
- const chosenRatio = null != ratio ? ratio : dimensions_getRatio(options, void 0, videoWidth);
19393
- const height = width ? Math.round(width * chosenRatio) : void 0;
19394
- if (height && Number.isInteger(height) && height < 1) throw error_createError({
19395
- message: "Just calculated a height less than 1 which is wrong.",
19396
- options
19397
- });
19398
- const minHeight = dimensions_figureMinHeight(height, options);
19399
- dimension.value = minHeight;
19400
- return dimension;
19401
- }
19402
- const dimensions_calculateHeight = calculateHeight;
19403
- function calculateWidth(responsive, options, videoHeight, ratio) {
19404
- const dimension = {
19405
- unit: "px"
19406
- };
19407
- let height = dimensions_figureMinHeight(videoHeight, options);
19408
- if (responsive) {
19409
- const limitedDimension = dimensions_limitHeight(height, options, "calculateWidth");
19410
- height = limitedDimension.value;
19411
- }
19412
- if (!height || height < 1) throw error_createError({
19413
- message: `Height ${height} cannot be smaller than 1 when calculating width.`,
19414
- options
19415
- });
19416
- const chosenRatio = null != ratio ? ratio : dimensions_getRatio(options, videoHeight);
19417
- const calculatedWidth = Math.round(height / chosenRatio);
19418
- if (calculatedWidth < 1) throw error_createError({
19419
- message: "Calculated width cannot be smaller than 1!",
19420
- options
19421
- });
19422
- dimension.value = calculatedWidth;
19423
- return dimension;
19424
- }
19425
- const dimensions_calculateWidth = calculateWidth;
19426
19346
  function isAutomatedUserAgent(userAgent = navigator.userAgent) {
19427
19347
  return /bot|crawler|spider|headlesschrome|phantomjs|puppeteer|playwright/iu.test(userAgent);
19428
19348
  }
19429
19349
  const util_isAutomatedUserAgent = isAutomatedUserAgent;
19430
- function summarize(title, contents) {
19431
- const lines = Object.entries(contents).sort(([keyA], [keyB])=>keyA.localeCompare(keyB)).map(([key, value])=>{
19432
- const formattedValue = void 0 === value ? "undefined" : "object" == typeof value ? string_pretty(value) : value;
19433
- return ` • ${key}: ${formattedValue}`;
19434
- });
19435
- const line = [
19436
- `🔎 ${title}`,
19437
- ...lines
19438
- ].join("\n");
19439
- return line;
19440
- }
19441
- const string_summarize = summarize;
19442
- function getFirstVideoTrack(localMediaStream) {
19443
- const videoTracks = localMediaStream.getVideoTracks();
19444
- let videoTrack;
19445
- if (videoTracks[0]) videoTrack = videoTracks[0];
19446
- return videoTrack;
19447
- }
19448
- const media_getFirstVideoTrack = getFirstVideoTrack;
19449
- const MEDIA_EVENTS = [
19450
- "loadstart",
19451
- "suspend",
19452
- "progress",
19453
- "abort",
19454
- "emptied",
19455
- "stalled",
19456
- "pause",
19457
- "loadeddata",
19458
- "waiting",
19459
- "playing",
19460
- "canplay",
19461
- "canplaythrough",
19462
- "seeking",
19463
- "seeked",
19464
- "ended",
19465
- "ratechange",
19466
- "durationchange",
19467
- "volumechange"
19468
- ];
19469
- const mediaEvents = MEDIA_EVENTS;
19470
- function esm_define_property(obj, key, value) {
19350
+ function boundedWriteQueue_define_property(obj, key, value) {
19471
19351
  if (key in obj) Object.defineProperty(obj, key, {
19472
19352
  value: value,
19473
19353
  enumerable: true,
@@ -19477,52 +19357,37 @@ var __webpack_exports__ = {};
19477
19357
  else obj[key] = value;
19478
19358
  return obj;
19479
19359
  }
19480
- class AudioSample {
19481
- toBuffer() {
19482
- const l = this.float32Array.length;
19483
- const arr = new Int16Array(l);
19484
- this.float32Array.forEach((sample, i)=>{
19485
- const clampedSample = Number.isFinite(sample) ? Math.max(-1, sample) : sample;
19486
- arr[i] = 0x7fff * Math.min(1, clampedSample);
19360
+ const DEFAULT_MAX_QUEUED_BYTES = 1048576;
19361
+ class BoundedWriteQueue {
19362
+ enqueue(buffer, params) {
19363
+ if (this.queuedBytes + buffer.length > this.maxBytes) return false;
19364
+ this.writes.push({
19365
+ buffer,
19366
+ params
19487
19367
  });
19488
- return typedarray_to_buffer(arr);
19368
+ this.queuedBytes += buffer.length;
19369
+ return true;
19489
19370
  }
19490
- constructor(float32Array){
19491
- esm_define_property(this, "float32Array", void 0);
19492
- this.float32Array = float32Array;
19371
+ dequeue() {
19372
+ const write = this.writes.shift();
19373
+ if (write) this.queuedBytes -= write.buffer.length;
19374
+ return write;
19493
19375
  }
19494
- }
19495
- const esm_src = AudioSample;
19496
- const esm = esm_src;
19497
- var is_power_of_two = __webpack_require__("dZ");
19498
- var is_power_of_two_default = /*#__PURE__*/ __webpack_require__.n(is_power_of_two);
19499
- function AudioRecorder_asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
19500
- try {
19501
- var info = gen[key](arg);
19502
- var value = info.value;
19503
- } catch (error) {
19504
- reject(error);
19505
- return;
19376
+ clear() {
19377
+ this.writes.length = 0;
19378
+ this.queuedBytes = 0;
19379
+ }
19380
+ constructor(maxBytes = DEFAULT_MAX_QUEUED_BYTES){
19381
+ boundedWriteQueue_define_property(this, "maxBytes", void 0);
19382
+ boundedWriteQueue_define_property(this, "writes", void 0);
19383
+ boundedWriteQueue_define_property(this, "queuedBytes", void 0);
19384
+ this.maxBytes = maxBytes;
19385
+ this.writes = [];
19386
+ this.queuedBytes = 0;
19506
19387
  }
19507
- if (info.done) resolve(value);
19508
- else Promise.resolve(value).then(_next, _throw);
19509
- }
19510
- function AudioRecorder_async_to_generator(fn) {
19511
- return function() {
19512
- var self1 = this, args = arguments;
19513
- return new Promise(function(resolve, reject) {
19514
- var gen = fn.apply(self1, args);
19515
- function _next(value) {
19516
- AudioRecorder_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
19517
- }
19518
- function _throw(err) {
19519
- AudioRecorder_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
19520
- }
19521
- _next(void 0);
19522
- });
19523
- };
19524
19388
  }
19525
- function AudioRecorder_define_property(obj, key, value) {
19389
+ const boundedWriteQueue = BoundedWriteQueue;
19390
+ function streamWriter_define_property(obj, key, value) {
19526
19391
  if (key in obj) Object.defineProperty(obj, key, {
19527
19392
  value: value,
19528
19393
  enumerable: true,
@@ -19532,520 +19397,183 @@ var __webpack_exports__ = {};
19532
19397
  else obj[key] = value;
19533
19398
  return obj;
19534
19399
  }
19535
- const CHANNELS = 1;
19536
- function getAudioContextClass() {
19537
- return window.AudioContext;
19538
- }
19539
- class AudioRecorder {
19540
- hasAudioContext() {
19541
- return Boolean(getAudioContextClass()) && Boolean(this.getAudioContext());
19400
+ const PIPE_SYMBOL = "°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸ ";
19401
+ class RecorderStreamWriter extends util_Despot {
19402
+ hasExceededWebSocketSendBuffer(buffer, opts) {
19403
+ return buffer.length > 0 && !this.pendingWrites.enqueue(buffer, opts);
19542
19404
  }
19543
- getAudioContext() {
19544
- if (!this.vcAudioContext) {
19545
- const AudioContext = getAudioContextClass();
19546
- this.vcAudioContext = new AudioContext();
19547
- }
19548
- return this.vcAudioContext;
19549
- }
19550
- onAudioProcess(e, cb) {
19551
- if (!this.userMedia.isRecording() || this.userMedia.isPaused()) return;
19552
- const float32Array = e.inputBuffer.getChannelData(0);
19553
- cb(new esm(float32Array));
19554
- }
19555
- disconnect() {
19556
- var _this_audioInput, _this_volume;
19557
- if (this.scriptProcessor) {
19558
- this.scriptProcessor.onaudioprocess = null;
19559
- this.scriptProcessor.disconnect();
19560
- }
19561
- null == (_this_audioInput = this.audioInput) || _this_audioInput.disconnect();
19562
- null == (_this_volume = this.volume) || _this_volume.disconnect();
19563
- }
19564
- init(localMediaStream) {
19565
- this.options.logger.debug("AudioRecorder: init()");
19566
- this.disconnect();
19567
- const volume = this.getAudioContext().createGain();
19568
- this.volume = volume;
19569
- try {
19570
- this.audioInput = this.getAudioContext().createMediaStreamSource(localMediaStream);
19571
- } catch (exc) {
19572
- throw error_createError({
19573
- message: "Webcam has no audio",
19574
- exc,
19405
+ writeStream(buffer, opts) {
19406
+ if (this.stream) if (this.stream.destroyed) {
19407
+ this.stopPings();
19408
+ const err = error_createError({
19409
+ message: "Already disconnected",
19410
+ explanation: "Sorry, connection to the server has been destroyed. Please reload.",
19575
19411
  options: this.options
19576
19412
  });
19577
- }
19578
- let { bufferSize } = this.options.audio;
19579
- if ("auto" === bufferSize) bufferSize = util_getBrowser(this.options).isFirefox() ? 512 : 2048;
19580
- if (void 0 === bufferSize || !is_power_of_two_default()(bufferSize)) throw error_createError({
19581
- message: `Audio buffer size must be a power of two. The current buffer size is ${bufferSize}.`,
19582
- options: this.options
19583
- });
19584
- if (!Number.isFinite(this.options.audio.volume) || this.options.audio.volume < 0 || this.options.audio.volume > 1) throw error_createError({
19585
- message: `Audio volume must be between zero and one. The current volume is ${this.options.audio.volume}.`,
19586
- options: this.options
19587
- });
19588
- volume.gain.value = this.options.audio.volume;
19589
- this.scriptProcessor = this.getAudioContext().createScriptProcessor(bufferSize, CHANNELS, CHANNELS);
19590
- this.audioInput.connect(volume);
19591
- volume.connect(this.scriptProcessor);
19592
- this.scriptProcessor.connect(this.getAudioContext().destination);
19593
- }
19594
- record(cb) {
19595
- this.options.logger.debug("AudioRecorder: record()");
19596
- if (this.scriptProcessor) this.scriptProcessor.onaudioprocess = (e)=>{
19597
- this.onAudioProcess(e, cb);
19598
- };
19599
- }
19600
- resume() {
19601
- return AudioRecorder_async_to_generator(function*() {
19602
- const context = this.getAudioContext();
19603
- if ("running" !== context.state) yield context.resume();
19604
- }).call(this);
19605
- }
19606
- stop() {
19607
- this.options.logger.debug("AudioRecorder: stop()");
19608
- this.disconnect();
19609
- if (this.hasAudioContext()) this.getAudioContext().close().then(()=>{
19610
- this.options.logger.debug("AudioRecorder: audio context is closed");
19611
- this.vcAudioContext = void 0;
19612
- }).catch((err)=>{
19613
- if (err instanceof Error) return void this.options.logger.error(error_createError({
19614
- err,
19413
+ this.handleWriteFailure(err);
19414
+ } else if (this.streamBackpressured) {
19415
+ if (this.hasExceededWebSocketSendBuffer(buffer, opts)) this.failMediaTransmission(error_createError({
19416
+ message: "WebSocket send buffer limit exceeded",
19417
+ 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.",
19615
19418
  options: this.options
19616
19419
  }));
19617
- this.options.logger.error(err);
19618
- });
19619
- }
19620
- getSampleRate() {
19621
- if (this.hasAudioContext()) return this.getAudioContext().sampleRate;
19622
- return -1;
19623
- }
19624
- constructor(userMedia, options){
19625
- AudioRecorder_define_property(this, "scriptProcessor", void 0);
19626
- AudioRecorder_define_property(this, "audioInput", void 0);
19627
- AudioRecorder_define_property(this, "volume", void 0);
19628
- AudioRecorder_define_property(this, "vcAudioContext", void 0);
19629
- AudioRecorder_define_property(this, "userMedia", void 0);
19630
- AudioRecorder_define_property(this, "options", void 0);
19631
- this.options = options;
19632
- this.userMedia = userMedia;
19633
- }
19634
- }
19635
- const media_AudioRecorder = AudioRecorder;
19636
- const VIRTUAL_KEYWORDS = [
19637
- "obs",
19638
- "virtual",
19639
- "manycam",
19640
- "vcam",
19641
- "splitcam",
19642
- "droidcam"
19643
- ];
19644
- function isVirtualCamera(videoTrack) {
19645
- const capabilities = videoTrack.getCapabilities();
19646
- if (!capabilities.frameRate) return true;
19647
- const isVirtual = VIRTUAL_KEYWORDS.some((keyword)=>videoTrack.label.toLowerCase().includes(keyword));
19648
- return isVirtual;
19649
- }
19650
- const util_isVirtualCamera = isVirtualCamera;
19651
- function userMedia_asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
19652
- try {
19653
- var info = gen[key](arg);
19654
- var value = info.value;
19655
- } catch (error) {
19656
- reject(error);
19657
- return;
19420
+ } else this.writeToStream(this.stream, buffer, opts);
19658
19421
  }
19659
- if (info.done) resolve(value);
19660
- else Promise.resolve(value).then(_next, _throw);
19661
- }
19662
- function userMedia_async_to_generator(fn) {
19663
- return function() {
19664
- var self1 = this, args = arguments;
19665
- return new Promise(function(resolve, reject) {
19666
- var gen = fn.apply(self1, args);
19667
- function _next(value) {
19668
- userMedia_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
19669
- }
19670
- function _throw(err) {
19671
- userMedia_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
19422
+ writeToStream(stream, buffer, opts) {
19423
+ const onFlushedCallback = null == opts ? void 0 : opts.onFlushedCallback;
19424
+ try {
19425
+ const canContinue = stream.write(buffer, ()=>{
19426
+ if (!onFlushedCallback) return;
19427
+ try {
19428
+ onFlushedCallback(opts);
19429
+ } catch (exc) {
19430
+ const err = error_createError({
19431
+ message: "Failed to write stream buffer",
19432
+ explanation: `stream.write() failed because of ${string_pretty(exc)}`,
19433
+ options: this.options,
19434
+ exc
19435
+ });
19436
+ this.emit("ERROR", {
19437
+ err
19438
+ });
19439
+ }
19440
+ });
19441
+ if (!canContinue) {
19442
+ this.streamBackpressured = true;
19443
+ this.startBackpressureTimeout();
19444
+ this.pauseForBackpressure();
19445
+ return false;
19672
19446
  }
19673
- _next(void 0);
19674
- });
19675
- };
19676
- }
19677
- function userMedia_define_property(obj, key, value) {
19678
- if (key in obj) Object.defineProperty(obj, key, {
19679
- value: value,
19680
- enumerable: true,
19681
- configurable: true,
19682
- writable: true
19683
- });
19684
- else obj[key] = value;
19685
- return obj;
19686
- }
19687
- const EVENT_ASCII = "|—O—|";
19688
- class UserMedia extends util_Despot {
19689
- attachMediaStream(stream) {
19690
- if (this.rawVisualUserMedia) {
19691
- this.rawVisualUserMedia.srcObject = stream;
19692
- const previousStream = this.currentVisualStream;
19693
- this.currentVisualStream = stream;
19694
- if (previousStream && previousStream !== stream) previousStream.getTracks().forEach((track)=>{
19695
- track.stop();
19447
+ return true;
19448
+ } catch (exc) {
19449
+ const err = error_createError({
19450
+ message: "Failed writing to server",
19451
+ explanation: `stream.write() failed because of ${string_pretty(exc)}`,
19452
+ options: this.options,
19453
+ exc
19696
19454
  });
19697
- } else throw error_createError({
19698
- message: "Error attaching stream to element.",
19699
- explanation: "Contact the developer about this",
19700
- options: this.options
19701
- });
19455
+ this.handleWriteFailure(err);
19456
+ return false;
19457
+ }
19702
19458
  }
19703
- setVisualStream(localMediaStream) {
19704
- if (localMediaStream) this.attachMediaStream(localMediaStream);
19705
- else {
19706
- if (this.rawVisualUserMedia) {
19707
- this.rawVisualUserMedia.srcObject = null;
19708
- this.rawVisualUserMedia.removeAttribute("src");
19709
- }
19710
- this.currentVisualStream = void 0;
19459
+ flushPendingWrites(stream) {
19460
+ if (this.isStaleStream(stream)) return;
19461
+ this.streamBackpressured = false;
19462
+ this.clearBackpressureTimeout();
19463
+ let pendingWrite = this.pendingWrites.dequeue();
19464
+ while(pendingWrite){
19465
+ if (!this.writeToStream(stream, pendingWrite.buffer, pendingWrite.params)) return;
19466
+ pendingWrite = this.pendingWrites.dequeue();
19711
19467
  }
19468
+ this.resumeRecordingAfterDrain();
19712
19469
  }
19713
- restorePlayback() {
19714
- return userMedia_async_to_generator(function*() {
19715
- var _this_audioRecorder;
19716
- if (!this.rawVisualUserMedia) throw new Error("No camera preview is available.");
19717
- yield this.rawVisualUserMedia.play();
19718
- yield null == (_this_audioRecorder = this.audioRecorder) ? void 0 : _this_audioRecorder.resume();
19719
- }).call(this);
19470
+ isStaleStream(stream) {
19471
+ return this.stream !== stream || stream.destroyed;
19720
19472
  }
19721
- hasLiveStream() {
19722
- var _this_currentVisualStream, _this_currentVisualStream1, _this_currentVisualStream2;
19723
- const videoReady = null == (_this_currentVisualStream = this.currentVisualStream) ? void 0 : _this_currentVisualStream.getVideoTracks().some((track)=>"live" === track.readyState && track.enabled && !track.muted);
19724
- const audioReady = !isAudioEnabled(this.options) || (null == (_this_currentVisualStream1 = this.currentVisualStream) ? void 0 : _this_currentVisualStream1.getAudioTracks().some((track)=>"live" === track.readyState && track.enabled && !track.muted));
19725
- return Boolean((null == (_this_currentVisualStream2 = this.currentVisualStream) ? void 0 : _this_currentVisualStream2.active) && videoReady && audioReady);
19473
+ canPauseForBackpressure() {
19474
+ return this.recordingActive && !this.isUserMediaPaused() && this.isCaptureLoopRunning();
19726
19475
  }
19727
- hasEnded() {
19728
- var _this_rawVisualUserMedia, _this_currentVisualStream;
19729
- if (null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.ended) return this.rawVisualUserMedia.ended;
19730
- return !(null == (_this_currentVisualStream = this.currentVisualStream) ? void 0 : _this_currentVisualStream.active);
19476
+ pauseForBackpressure() {
19477
+ if (!this.canPauseForBackpressure()) return;
19478
+ this.resumeAfterDrain = true;
19479
+ this.stopCaptureLoop();
19731
19480
  }
19732
- hasInvalidDimensions() {
19733
- if (!this.rawVisualUserMedia) return false;
19734
- const { videoWidth, videoHeight } = this.rawVisualUserMedia;
19735
- return videoWidth > 0 && videoWidth < 3 || videoHeight > 0 && videoHeight < 3;
19481
+ resumeRecordingAfterDrain() {
19482
+ if (!this.resumeAfterDrain) return;
19483
+ this.resumeAfterDrain = false;
19484
+ if (this.canResumeAfterDrain()) this.startCaptureLoop();
19736
19485
  }
19737
- logEvent(eventType, params) {
19738
- this.options.logger.debug(`UserMedia: ... ${EVENT_ASCII} event ${eventType}: ${string_pretty(params)}`);
19486
+ canResumeAfterDrain() {
19487
+ return this.recordingActive && !this.isUserMediaPaused();
19739
19488
  }
19740
- unloadRemainingEventListeners() {
19741
- var _this_clearInitializationListeners, _this, _this_rawVisualUserMedia;
19742
- this.options.logger.debug("UserMedia: unloadRemainingEventListeners()");
19743
- null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
19744
- mediaEvents.forEach((eventName)=>{
19745
- var _this_rawVisualUserMedia;
19746
- null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.removeEventListener(eventName, this.outputEvent);
19489
+ handleWriteFailure(err) {
19490
+ if (this.mediaTransmissionStarted) return void this.failMediaTransmission(err);
19491
+ this.emit("ERROR", {
19492
+ err
19747
19493
  });
19748
- null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.removeEventListener("error", this.handleMediaError);
19749
19494
  }
19750
- audioRecord(audioCallback) {
19751
- var _this_audioRecorder;
19752
- this.removeListener("SENDING_FIRST_FRAME");
19753
- null == (_this_audioRecorder = this.audioRecorder) || _this_audioRecorder.record(audioCallback);
19754
- }
19755
- init(localMediaStream, videoCallback, audioCallback, endedEarlyCallback, params) {
19756
- var _this_clearInitializationListeners, _this;
19757
- null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
19758
- this.stop(localMediaStream, {
19759
- aboutToInitialize: true,
19760
- preserveRecordingState: Boolean((null == params ? void 0 : params.switchingFacingMode) || (null == params ? void 0 : params.recovering))
19495
+ failMediaTransmission(err) {
19496
+ if (this.recordingTransportFailed) return;
19497
+ this.recordingTransportFailed = true;
19498
+ this.recordingActive = false;
19499
+ this.mediaTransmissionStarted = false;
19500
+ this.streamBackpressured = false;
19501
+ this.resumeAfterDrain = false;
19502
+ this.pendingWrites.clear();
19503
+ this.connected = false;
19504
+ this.connecting = false;
19505
+ this.reconnecting = false;
19506
+ this.clearReconnectTimeout();
19507
+ this.clearBackpressureTimeout();
19508
+ this.discardSocket();
19509
+ this.reset();
19510
+ this.framesCount = this.samplesCount = 0;
19511
+ this.confirmedFrameNumber = this.confirmedSampleNumber = 0;
19512
+ delete this.recordingStats;
19513
+ this.recordingDimensions = void 0;
19514
+ this.emit("ERROR", {
19515
+ err
19761
19516
  });
19762
- const initializationId = ++this.initializationId;
19763
- this.onPlayReached = false;
19764
- this.onLoadedMetaDataReached = false;
19765
- this.playingPromiseReached = false;
19766
- this.videoTrackLabel = void 0;
19767
- if (isAudioEnabled(this.options)) null != this.audioRecorder || (this.audioRecorder = new media_AudioRecorder(this, this.options));
19768
- const unloadAllEventListeners = ()=>{
19769
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
19770
- this.options.logger.debug("UserMedia: unloadAllEventListeners()");
19771
- this.unloadRemainingEventListeners();
19772
- this.removeListener("SENDING_FIRST_FRAME");
19773
- null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.removeEventListener("play", onPlay);
19774
- null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.removeEventListener("loadedmetadata", onLoadedMetaData);
19775
- };
19776
- this.clearInitializationListeners = ()=>{
19777
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
19778
- null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.removeEventListener("play", onPlay);
19779
- null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.removeEventListener("loadedmetadata", onLoadedMetaData);
19780
- this.clearInitializationListeners = void 0;
19781
- };
19782
- const play = ()=>{
19783
- try {
19784
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
19785
- null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.load();
19786
- if (null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.paused) {
19787
- 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)}`);
19788
- this.rawVisualUserMedia.play().then(()=>{
19789
- if (initializationId !== this.initializationId) return;
19790
- if (!this.playingPromiseReached) {
19791
- this.options.logger.debug("UserMedia: play promise successful. Playing now.");
19792
- this.playingPromiseReached = true;
19793
- }
19794
- }).catch((exc)=>{
19795
- if (initializationId !== this.initializationId) return;
19796
- if (exc instanceof Error && !(null == params ? void 0 : params.recovering)) this.options.logger.warn(`Caught pending user media promise exception: ${exc.toString()}`);
19797
- else {
19798
- unloadAllEventListeners();
19799
- endedEarlyCallback(error_createError({
19800
- message: "Failed to play user media upon play event.",
19801
- exc,
19802
- options: this.options
19803
- }));
19804
- }
19805
- });
19806
- }
19807
- } catch (exc) {
19808
- unloadAllEventListeners();
19809
- endedEarlyCallback(exc);
19810
- }
19811
- };
19812
- const fireCallbacks = ()=>{
19813
- var _this_rawVisualUserMedia;
19814
- const readyState = null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.readyState;
19815
- this.options.logger.debug(`UserMedia: fireCallbacks(readyState=${readyState}, onPlayReached=${this.onPlayReached}, onLoadedMetaDataReached=${this.onLoadedMetaDataReached})`);
19816
- if (this.onPlayReached && this.onLoadedMetaDataReached) if (this.audioRecorder) try {
19817
- this.audioRecorder.init(localMediaStream);
19818
- const onAudioReady = ()=>{
19819
- var _this_clearInitializationListeners, _this;
19820
- if (initializationId !== this.initializationId || this.currentVisualStream !== localMediaStream) return;
19821
- if (this.recording) this.audioRecord(audioCallback);
19822
- else this.on("SENDING_FIRST_FRAME", ()=>{
19823
- this.audioRecord(audioCallback);
19824
- });
19825
- null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
19826
- videoCallback();
19827
- };
19828
- if (null == params ? void 0 : params.recovering) this.audioRecorder.resume().then(onAudioReady).catch(endedEarlyCallback);
19829
- else onAudioReady();
19830
- } catch (exc) {
19831
- unloadAllEventListeners();
19832
- this.stop(void 0, {
19833
- preserveRecordingState: Boolean(null == params ? void 0 : params.recovering)
19834
- });
19835
- endedEarlyCallback(exc);
19836
- }
19837
- else {
19838
- var _this_clearInitializationListeners, _this;
19839
- null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
19840
- videoCallback();
19841
- }
19842
- };
19843
- const onPlay = ()=>{
19844
- try {
19845
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1, _this_rawVisualUserMedia2, _this_rawVisualUserMedia3, _this_rawVisualUserMedia4, _this_rawVisualUserMedia5;
19846
- this.logEvent("play", {
19847
- readyState: null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.readyState,
19848
- audio: isAudioEnabled(this.options),
19849
- width: null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.width,
19850
- height: null == (_this_rawVisualUserMedia2 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia2.height,
19851
- videoWidth: null == (_this_rawVisualUserMedia3 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia3.videoWidth,
19852
- videoHeight: null == (_this_rawVisualUserMedia4 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia4.videoHeight
19853
- });
19854
- null == (_this_rawVisualUserMedia5 = this.rawVisualUserMedia) || _this_rawVisualUserMedia5.removeEventListener("play", onPlay);
19855
- if (this.hasEnded() || this.hasInvalidDimensions()) endedEarlyCallback(error_createError({
19856
- message: "Already busy",
19857
- explanation: "Probably another browser window is using your webcam?",
19858
- options: this.options
19859
- }));
19860
- else {
19861
- this.onPlayReached = true;
19862
- fireCallbacks();
19863
- }
19864
- } catch (exc) {
19865
- unloadAllEventListeners();
19866
- endedEarlyCallback(exc);
19867
- }
19868
- };
19869
- const onLoadedMetaData = ()=>{
19870
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1, _this_rawVisualUserMedia2, _this_rawVisualUserMedia3, _this_rawVisualUserMedia4, _this_rawVisualUserMedia5, _this_rawVisualUserMedia6;
19871
- this.logEvent("loadedmetadata", {
19872
- readyState: null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.readyState,
19873
- paused: null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.paused,
19874
- width: null == (_this_rawVisualUserMedia2 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia2.width,
19875
- height: null == (_this_rawVisualUserMedia3 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia3.height,
19876
- videoWidth: null == (_this_rawVisualUserMedia4 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia4.videoWidth,
19877
- videoHeight: null == (_this_rawVisualUserMedia5 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia5.videoHeight
19878
- });
19879
- null == (_this_rawVisualUserMedia6 = this.rawVisualUserMedia) || _this_rawVisualUserMedia6.removeEventListener("loadedmetadata", onLoadedMetaData);
19880
- if (!this.hasEnded() && !this.hasInvalidDimensions()) {
19881
- this.emit("LOADED_META_DATA");
19882
- this.onLoadedMetaDataReached = true;
19883
- fireCallbacks();
19884
- }
19885
- };
19886
- try {
19887
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1, _this_rawVisualUserMedia2, _this_rawVisualUserMedia3;
19888
- const videoTrack = media_getFirstVideoTrack(localMediaStream);
19889
- this.videoTrackLabel = null == videoTrack ? void 0 : videoTrack.label;
19890
- if (videoTrack) if (videoTrack.enabled) if (util_isVirtualCamera(videoTrack)) throw error_createError({
19891
- message: "Virtual cameras are not allowed.",
19892
- explanation: `Please use a real camera, not "${videoTrack.label}".`,
19893
- options: this.options
19894
- });
19895
- else {
19896
- let description = "";
19897
- if (videoTrack.label.length > 0) description = description.concat(videoTrack.label);
19898
- description = description.concat(` with enabled=${videoTrack.enabled}, muted=${videoTrack.muted}, readyState=${videoTrack.readyState}`);
19899
- this.options.logger.debug(`UserMedia: ${videoTrack.kind} detected. ${description}`);
19900
- }
19901
- else throw error_createError({
19902
- message: "Webcam is disabled",
19903
- explanation: "The video track seems to be disabled. Enable it in your system.",
19517
+ }
19518
+ startBackpressureTimeout() {
19519
+ if (!this.shouldStartBackpressureTimeout()) return;
19520
+ this.backpressureTimeout = window.setTimeout(()=>{
19521
+ this.backpressureTimeout = void 0;
19522
+ if (this.shouldIgnoreBackpressureTimeout()) return;
19523
+ const err = error_createError({
19524
+ message: "WebSocket write timed out",
19525
+ explanation: "The server stopped accepting recording data. The recording has been stopped; please check your connection and start a new one.",
19904
19526
  options: this.options
19905
19527
  });
19906
- else this.options.logger.debug("UserMedia: detected (but no video tracks exist");
19907
- null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.addEventListener("loadedmetadata", onLoadedMetaData);
19908
- null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.addEventListener("play", onPlay);
19909
- null == (_this_rawVisualUserMedia2 = this.rawVisualUserMedia) || _this_rawVisualUserMedia2.removeEventListener("error", this.handleMediaError);
19910
- null == (_this_rawVisualUserMedia3 = this.rawVisualUserMedia) || _this_rawVisualUserMedia3.addEventListener("error", this.handleMediaError);
19911
- this.setVisualStream(localMediaStream);
19912
- play();
19913
- } catch (exc) {
19914
- unloadAllEventListeners();
19915
- endedEarlyCallback(exc);
19916
- }
19528
+ this.failMediaTransmission(err);
19529
+ }, this.options.timeouts.connection);
19917
19530
  }
19918
- getVideoTrackLabel() {
19919
- return this.videoTrackLabel;
19531
+ shouldStartBackpressureTimeout() {
19532
+ return void 0 === this.backpressureTimeout && this.mediaTransmissionStarted;
19920
19533
  }
19921
- isReady() {
19922
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
19923
- return Boolean((null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.srcObject) || (null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.currentSrc));
19534
+ shouldIgnoreBackpressureTimeout() {
19535
+ return !this.streamBackpressured || this.recordingTransportFailed;
19924
19536
  }
19925
- stop(visualStream, params) {
19926
- try {
19927
- let chosenStream = visualStream;
19928
- if (!(null == params ? void 0 : params.aboutToInitialize)) {
19929
- var _this_clearInitializationListeners, _this, _this_audioRecorder;
19930
- this.initializationId++;
19931
- null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
19932
- null != chosenStream || (chosenStream = this.currentVisualStream);
19933
- const tracks = null == chosenStream ? void 0 : chosenStream.getTracks();
19934
- if (tracks) tracks.forEach((track)=>{
19935
- track.stop();
19936
- });
19937
- this.setVisualStream();
19938
- null == (_this_audioRecorder = this.audioRecorder) || _this_audioRecorder.stop();
19939
- this.audioRecorder = void 0;
19537
+ failInterruptedRecording() {
19538
+ const unconfirmedFrames = Math.max(0, this.framesCount - this.confirmedFrameNumber);
19539
+ const unconfirmedSamples = Math.max(0, this.samplesCount - this.confirmedSampleNumber);
19540
+ const err = error_createError({
19541
+ message: "Recording interrupted",
19542
+ explanation: "The server connection closed before this recording completed. It cannot be safely resumed, so it has been stopped. Please start a new recording.",
19543
+ options: this.options,
19544
+ cause: {
19545
+ unconfirmedFrames,
19546
+ unconfirmedSamples
19940
19547
  }
19941
- if (!(null == params ? void 0 : params.preserveRecordingState)) this.paused = this.recording = false;
19942
- } catch (exc) {
19943
- this.emit("ERROR", {
19944
- exc
19945
- });
19946
- }
19548
+ });
19549
+ this.failMediaTransmission(err);
19947
19550
  }
19948
- createCanvas() {
19949
- const canvas = document.createElement("canvas");
19950
- const rawWidthDimension = this.getRawWidth(true);
19951
- if (rawWidthDimension.value) canvas.width = rawWidthDimension.value;
19952
- const rawHeight = this.getRawHeight(true);
19953
- if (rawHeight) canvas.height = rawHeight;
19954
- return canvas;
19551
+ handleStreamDrain(stream) {
19552
+ this.options.logger.debug(`${PIPE_SYMBOL}Stream *drain* event emitted`);
19553
+ this.flushPendingWrites(stream);
19955
19554
  }
19956
- getVideoHeight() {
19957
- if (!this.rawVisualUserMedia) return;
19958
- return this.rawVisualUserMedia.videoHeight || this.rawVisualUserMedia.height;
19555
+ clearBackpressureTimeout() {
19556
+ if (void 0 === this.backpressureTimeout) return;
19557
+ window.clearTimeout(this.backpressureTimeout);
19558
+ this.backpressureTimeout = void 0;
19959
19559
  }
19960
- getVideoWidth() {
19961
- if (!this.rawVisualUserMedia) return;
19962
- return this.rawVisualUserMedia.videoWidth || this.rawVisualUserMedia.width;
19963
- }
19964
- hasVideoWidth() {
19965
- const videoWidth = this.getVideoWidth();
19966
- return videoWidth && videoWidth > 0;
19967
- }
19968
- getRawWidth(responsive) {
19969
- let rawWidth;
19970
- const widthDimension = {
19971
- unit: "px"
19972
- };
19973
- rawWidth = responsive ? this.getVideoWidth() : this.options.video.width ? this.options.video.width : this.getVideoWidth();
19974
- if (responsive) {
19975
- const widthDimension = this.recorder.limitWidth(rawWidth);
19976
- rawWidth = null == widthDimension ? void 0 : widthDimension.value;
19977
- }
19978
- widthDimension.value = rawWidth;
19979
- return widthDimension;
19980
- }
19981
- getRawHeight(responsive) {
19982
- let rawHeight;
19983
- if (responsive) {
19984
- rawHeight = this.options.video.height || this.getVideoHeight();
19985
- const ratio = this.recorder.getRatio();
19986
- const rawWidth = this.getRawWidth(responsive);
19987
- if (void 0 !== ratio && rawWidth.value) rawHeight = rawWidth.value * ratio;
19988
- } else rawHeight = this.options.video.height ? this.options.video.height : this.getVideoHeight();
19989
- if (responsive) {
19990
- const heightDimension = this.recorder.limitHeight(rawHeight);
19991
- rawHeight = heightDimension.value;
19992
- }
19993
- return rawHeight;
19994
- }
19995
- getRawVisuals() {
19996
- return this.rawVisualUserMedia;
19997
- }
19998
- pause() {
19999
- this.paused = true;
20000
- }
20001
- isPaused() {
20002
- return this.paused;
20003
- }
20004
- resume() {
20005
- this.paused = false;
20006
- }
20007
- record() {
20008
- this.recording = true;
20009
- }
20010
- isRecording() {
20011
- return this.recording;
20012
- }
20013
- getAudioSampleRate() {
20014
- if (this.audioRecorder) return this.audioRecorder.getSampleRate();
20015
- return -1;
20016
- }
20017
- getCharacteristics() {
20018
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1, _this_rawVisualUserMedia2, _this_rawVisualUserMedia3, _this_rawVisualUserMedia4;
20019
- return {
20020
- audioSampleRate: this.getAudioSampleRate(),
20021
- muted: null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.muted,
20022
- width: null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.width,
20023
- height: null == (_this_rawVisualUserMedia2 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia2.height,
20024
- videoWidth: null == (_this_rawVisualUserMedia3 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia3.videoWidth,
20025
- videoHeight: null == (_this_rawVisualUserMedia4 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia4.videoHeight
20026
- };
19560
+ discardSocket() {
19561
+ this.options.logger.debug("Recorder: discarding socket stream ...");
19562
+ this.clearBackpressureTimeout();
19563
+ this.pendingWrites.clear();
19564
+ this.streamBackpressured = false;
19565
+ this.resumeAfterDrain = false;
19566
+ const stream = this.stream;
19567
+ this.stream = void 0;
19568
+ if (stream && !stream.destroyed) stream.destroy();
20027
19569
  }
20028
- constructor(recorder, options){
20029
- super("UserMedia", options), userMedia_define_property(this, "recorder", void 0), userMedia_define_property(this, "rawVisualUserMedia", void 0), userMedia_define_property(this, "paused", false), userMedia_define_property(this, "recording", false), userMedia_define_property(this, "audioRecorder", void 0), userMedia_define_property(this, "currentVisualStream", void 0), userMedia_define_property(this, "onPlayReached", false), userMedia_define_property(this, "onLoadedMetaDataReached", false), userMedia_define_property(this, "playingPromiseReached", false), userMedia_define_property(this, "videoTrackLabel", void 0), userMedia_define_property(this, "clearInitializationListeners", void 0), userMedia_define_property(this, "initializationId", 0), userMedia_define_property(this, "outputEvent", (e)=>{
20030
- var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
20031
- this.logEvent(e.type, {
20032
- readyState: null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.readyState
20033
- });
20034
- null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.removeEventListener(e.type, this.outputEvent);
20035
- }), userMedia_define_property(this, "handleMediaError", (event)=>{
20036
- this.options.logger.warn(`Caught video element error event: ${string_pretty(event)}`);
20037
- });
20038
- this.recorder = recorder;
20039
- this.rawVisualUserMedia = recorder.getRawVisualUserMedia();
20040
- mediaEvents.forEach((eventName)=>{
20041
- var _this_rawVisualUserMedia;
20042
- null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.addEventListener(eventName, this.outputEvent, false);
20043
- });
19570
+ constructor(options){
19571
+ super("Recorder", options), streamWriter_define_property(this, "pendingWrites", new boundedWriteQueue()), streamWriter_define_property(this, "samplesCount", 0), streamWriter_define_property(this, "framesCount", 0), streamWriter_define_property(this, "recordingStats", void 0), streamWriter_define_property(this, "confirmedFrameNumber", 0), streamWriter_define_property(this, "confirmedSampleNumber", 0), streamWriter_define_property(this, "backpressureTimeout", void 0), streamWriter_define_property(this, "recordingDimensions", void 0), streamWriter_define_property(this, "stream", void 0), streamWriter_define_property(this, "streamBackpressured", false), streamWriter_define_property(this, "resumeAfterDrain", false), streamWriter_define_property(this, "mediaTransmissionStarted", false), streamWriter_define_property(this, "recordingActive", false), streamWriter_define_property(this, "recordingTransportFailed", false), streamWriter_define_property(this, "connecting", false), streamWriter_define_property(this, "connected", false), streamWriter_define_property(this, "reconnecting", false);
20044
19572
  }
20045
19573
  }
20046
- const visuals_userMedia = UserMedia;
19574
+ const streamWriter = RecorderStreamWriter;
20047
19575
  var Buffer = __webpack_require__("dY").Buffer;
20048
- function recorder_define_property(obj, key, value) {
19576
+ function connection_define_property(obj, key, value) {
20049
19577
  if (key in obj) Object.defineProperty(obj, key, {
20050
19578
  value: value,
20051
19579
  enumerable: true,
@@ -20055,316 +19583,91 @@ var __webpack_exports__ = {};
20055
19583
  else obj[key] = value;
20056
19584
  return obj;
20057
19585
  }
20058
- function recorder_object_spread(target) {
20059
- for(var i = 1; i < arguments.length; i++){
20060
- var source = null != arguments[i] ? arguments[i] : {};
20061
- var ownKeys = Object.keys(source);
20062
- if ("function" == typeof Object.getOwnPropertySymbols) ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
20063
- return Object.getOwnPropertyDescriptor(source, sym).enumerable;
20064
- }));
20065
- ownKeys.forEach(function(key) {
20066
- recorder_define_property(target, key, source[key]);
20067
- });
19586
+ class RecorderConnection extends streamWriter {
19587
+ canReconnectAfterStreamClose() {
19588
+ return Boolean(this.connected && this.userMediaLoaded);
20068
19589
  }
20069
- return target;
20070
- }
20071
- const PIPE_SYMBOL = "°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸ ";
20072
- class Recorder extends util_Despot {
20073
- hasExceededWebSocketSendBuffer(buffer, opts) {
20074
- return buffer.length > 0 && !this.pendingWrites.enqueue(buffer, opts);
19590
+ shouldReportStreamClose() {
19591
+ return !this.connecting && !this.blocking;
20075
19592
  }
20076
- writeStream(buffer, opts) {
20077
- if (this.stream) if (this.stream.destroyed) {
20078
- this.stopPings();
20079
- const err = error_createError({
20080
- message: "Already disconnected",
20081
- explanation: "Sorry, connection to the server has been destroyed. Please reload.",
20082
- options: this.options
19593
+ handleStreamClose(url2Connect) {
19594
+ const debugLine = string_summarize(`${PIPE_SYMBOL}Stream has closed:`, {
19595
+ connecting: this.connecting,
19596
+ connected: this.connected,
19597
+ userMediaLoaded: this.userMediaLoaded,
19598
+ blocking: this.blocking
19599
+ });
19600
+ this.options.logger.debug(debugLine);
19601
+ const canReconnect = this.canReconnectAfterStreamClose();
19602
+ this.connected = false;
19603
+ this.stopPings();
19604
+ if (this.shouldIgnoreStreamClose()) return;
19605
+ if (this.mediaTransmissionStarted) this.failInterruptedRecording();
19606
+ else if (canReconnect) {
19607
+ this.pendingWrites.clear();
19608
+ this.streamBackpressured = false;
19609
+ this.resumeAfterDrain = false;
19610
+ this.reconnecting = true;
19611
+ this.initSocket();
19612
+ } else if (this.shouldReportStreamClose()) window.setTimeout(()=>{
19613
+ this.handleConnectionFailure({
19614
+ url2Connect,
19615
+ cause: "closed"
20083
19616
  });
20084
- this.handleWriteFailure(err);
20085
- } else if (this.streamBackpressured) {
20086
- if (this.hasExceededWebSocketSendBuffer(buffer, opts)) this.failMediaTransmission(error_createError({
20087
- message: "WebSocket send buffer limit exceeded",
20088
- 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.",
20089
- options: this.options
20090
- }));
20091
- } else this.writeToStream(this.stream, buffer, opts);
19617
+ }, 0);
20092
19618
  }
20093
- writeToStream(stream, buffer, opts) {
20094
- const onFlushedCallback = null == opts ? void 0 : opts.onFlushedCallback;
20095
- try {
20096
- const canContinue = stream.write(buffer, ()=>{
20097
- if (!onFlushedCallback) return;
20098
- try {
20099
- onFlushedCallback(opts);
20100
- } catch (exc) {
20101
- const err = error_createError({
20102
- message: "Failed to write stream buffer",
20103
- explanation: `stream.write() failed because of ${string_pretty(exc)}`,
20104
- options: this.options,
20105
- exc
20106
- });
20107
- this.emit("ERROR", {
20108
- err
20109
- });
20110
- }
20111
- });
20112
- if (!canContinue) {
20113
- this.streamBackpressured = true;
20114
- this.startBackpressureTimeout();
20115
- this.pauseForBackpressure();
20116
- return false;
20117
- }
20118
- return true;
20119
- } catch (exc) {
20120
- const err = error_createError({
20121
- message: "Failed writing to server",
20122
- explanation: `stream.write() failed because of ${string_pretty(exc)}`,
20123
- options: this.options,
20124
- exc
20125
- });
20126
- this.handleWriteFailure(err);
20127
- return false;
20128
- }
19619
+ shouldIgnoreStreamClose() {
19620
+ return this.recordingTransportFailed || Boolean(this.unloaded) || this.validate();
20129
19621
  }
20130
- flushPendingWrites(stream) {
20131
- if (this.isStaleStream(stream)) return;
20132
- this.streamBackpressured = false;
20133
- this.clearBackpressureTimeout();
20134
- let pendingWrite = this.pendingWrites.dequeue();
20135
- while(pendingWrite){
20136
- if (!this.writeToStream(stream, pendingWrite.buffer, pendingWrite.params)) return;
20137
- pendingWrite = this.pendingWrites.dequeue();
19622
+ handleStreamError(url2Connect, err) {
19623
+ var _this_lastSocketError;
19624
+ if ("u" > typeof Event && err instanceof Event) this.lastSocketError = error_getEventDetails(err);
19625
+ else this.lastSocketError = serializeError(err);
19626
+ const debugLine = string_summarize(`${PIPE_SYMBOL}Stream *error* event emitted:`, {
19627
+ error: serializeError(err)
19628
+ });
19629
+ this.options.logger.debug(debugLine);
19630
+ if (this.validate()) {
19631
+ this.connected = false;
19632
+ this.stopPings();
19633
+ this.discardSocket();
19634
+ return;
20138
19635
  }
20139
- this.resumeRecordingAfterDrain();
20140
- }
20141
- isStaleStream(stream) {
20142
- return this.stream !== stream || stream.destroyed;
19636
+ if (!this.connected) return void this.handleConnectionFailure({
19637
+ url2Connect,
19638
+ cause: "error"
19639
+ });
19640
+ const streamError = err instanceof Error ? err : new Error("WebSocket stream emitted an error event", {
19641
+ cause: null != (_this_lastSocketError = this.lastSocketError) ? _this_lastSocketError : err
19642
+ });
19643
+ if (this.mediaTransmissionStarted) return void this.failInterruptedRecording();
19644
+ this.emit("ERROR", {
19645
+ err: error_createError({
19646
+ message: "WebSocket stream error",
19647
+ explanation: `The WebSocket stream emitted an error event. Details: ${string_pretty(err)}`,
19648
+ options: this.options,
19649
+ exc: streamError
19650
+ })
19651
+ });
20143
19652
  }
20144
- canPauseForBackpressure() {
20145
- var _this_userMedia, _this_loop;
20146
- return Boolean(this.recordingActive && !(null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isPaused()) && (null == (_this_loop = this.loop) ? void 0 : _this_loop.isRunning()));
19653
+ sendPings() {
19654
+ this.stopPings();
19655
+ this.pingInterval = window.setInterval(()=>{
19656
+ this.options.logger.debug("Recorder: pinging...");
19657
+ this.writeStream(Buffer.from(""));
19658
+ }, this.options.timeouts.pingInterval);
20147
19659
  }
20148
- pauseForBackpressure() {
20149
- if (!this.canPauseForBackpressure()) return;
20150
- this.resumeAfterDrain = true;
20151
- this.loop.stop();
19660
+ stopPings() {
19661
+ if (void 0 === this.pingInterval) return;
19662
+ this.options.logger.debug("Recorder: stopping pings...");
19663
+ window.clearInterval(this.pingInterval);
19664
+ this.pingInterval = void 0;
20152
19665
  }
20153
- resumeRecordingAfterDrain() {
20154
- if (!this.resumeAfterDrain) return;
20155
- this.resumeAfterDrain = false;
20156
- if (this.canResumeAfterDrain()) {
20157
- var _this_loop;
20158
- null == (_this_loop = this.loop) || _this_loop.start();
20159
- }
20160
- }
20161
- canResumeAfterDrain() {
20162
- var _this_userMedia;
20163
- return this.recordingActive && !(null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isPaused());
20164
- }
20165
- handleWriteFailure(err) {
20166
- if (this.mediaTransmissionStarted) return void this.failMediaTransmission(err);
20167
- this.emit("ERROR", {
20168
- err
20169
- });
20170
- }
20171
- failMediaTransmission(err) {
20172
- if (this.recordingTransportFailed) return;
20173
- this.recordingTransportFailed = true;
20174
- this.recordingActive = false;
20175
- this.mediaTransmissionStarted = false;
20176
- this.streamBackpressured = false;
20177
- this.resumeAfterDrain = false;
20178
- this.pendingWrites.clear();
20179
- this.connected = false;
20180
- this.connecting = false;
20181
- this.reconnecting = false;
20182
- this.clearReconnectTimeout();
20183
- this.clearBackpressureTimeout();
20184
- this.discardSocket();
20185
- this.reset();
20186
- this.framesCount = this.samplesCount = 0;
20187
- this.confirmedFrameNumber = this.confirmedSampleNumber = 0;
20188
- delete this.recordingStats;
20189
- this.recordingDimensions = void 0;
20190
- this.emit("ERROR", {
20191
- err
20192
- });
20193
- }
20194
- startBackpressureTimeout() {
20195
- if (!this.shouldStartBackpressureTimeout()) return;
20196
- this.backpressureTimeout = window.setTimeout(()=>{
20197
- this.backpressureTimeout = void 0;
20198
- if (this.shouldIgnoreBackpressureTimeout()) return;
20199
- const err = error_createError({
20200
- message: "WebSocket write timed out",
20201
- explanation: "The server stopped accepting recording data. The recording has been stopped; please check your connection and start a new one.",
20202
- options: this.options
20203
- });
20204
- this.failMediaTransmission(err);
20205
- }, this.options.timeouts.connection);
20206
- }
20207
- shouldStartBackpressureTimeout() {
20208
- return void 0 === this.backpressureTimeout && this.mediaTransmissionStarted;
20209
- }
20210
- shouldIgnoreBackpressureTimeout() {
20211
- return !this.streamBackpressured || this.recordingTransportFailed;
20212
- }
20213
- failInterruptedRecording() {
20214
- const unconfirmedFrames = Math.max(0, this.framesCount - this.confirmedFrameNumber);
20215
- const unconfirmedSamples = Math.max(0, this.samplesCount - this.confirmedSampleNumber);
20216
- const err = error_createError({
20217
- message: "Recording interrupted",
20218
- explanation: "The server connection closed before this recording completed. It cannot be safely resumed, so it has been stopped. Please start a new recording.",
20219
- options: this.options,
20220
- cause: {
20221
- unconfirmedFrames,
20222
- unconfirmedSamples
20223
- }
20224
- });
20225
- this.failMediaTransmission(err);
20226
- }
20227
- handleStreamDrain(stream) {
20228
- this.options.logger.debug(`${PIPE_SYMBOL}Stream *drain* event emitted`);
20229
- this.flushPendingWrites(stream);
20230
- }
20231
- canReconnectAfterStreamClose() {
20232
- return Boolean(this.connected && this.userMediaLoaded);
20233
- }
20234
- shouldReportStreamClose() {
20235
- return !this.connecting && !this.blocking;
20236
- }
20237
- handleStreamClose(url2Connect) {
20238
- const debugLine = string_summarize(`${PIPE_SYMBOL}Stream has closed:`, {
20239
- connecting: this.connecting,
20240
- connected: this.connected,
20241
- userMediaLoaded: this.userMediaLoaded,
20242
- blocking: this.blocking
20243
- });
20244
- this.options.logger.debug(debugLine);
20245
- const canReconnect = this.canReconnectAfterStreamClose();
20246
- this.connected = false;
20247
- this.stopPings();
20248
- if (this.shouldIgnoreStreamClose()) return;
20249
- if (this.mediaTransmissionStarted) this.failInterruptedRecording();
20250
- else if (canReconnect) {
20251
- this.pendingWrites.clear();
20252
- this.streamBackpressured = false;
20253
- this.resumeAfterDrain = false;
20254
- this.reconnecting = true;
20255
- this.initSocket();
20256
- } else if (this.shouldReportStreamClose()) window.setTimeout(()=>{
20257
- this.handleConnectionFailure({
20258
- url2Connect,
20259
- cause: "closed"
20260
- });
20261
- }, 0);
20262
- }
20263
- shouldIgnoreStreamClose() {
20264
- return this.recordingTransportFailed || Boolean(this.unloaded) || this.validate();
20265
- }
20266
- handleStreamError(url2Connect, err) {
20267
- var _this_lastSocketError;
20268
- if ("u" > typeof Event && err instanceof Event) this.lastSocketError = error_getEventDetails(err);
20269
- else this.lastSocketError = serializeError(err);
20270
- const debugLine = string_summarize(`${PIPE_SYMBOL}Stream *error* event emitted:`, {
20271
- error: serializeError(err)
20272
- });
20273
- this.options.logger.debug(debugLine);
20274
- if (this.validate()) {
20275
- this.connected = false;
20276
- this.stopPings();
20277
- this.discardSocket();
20278
- return;
20279
- }
20280
- if (!this.connected) return void this.handleConnectionFailure({
20281
- url2Connect,
20282
- cause: "error"
20283
- });
20284
- const streamError = err instanceof Error ? err : new Error("WebSocket stream emitted an error event", {
20285
- cause: null != (_this_lastSocketError = this.lastSocketError) ? _this_lastSocketError : err
20286
- });
20287
- if (this.mediaTransmissionStarted) return void this.failInterruptedRecording();
20288
- this.emit("ERROR", {
20289
- err: error_createError({
20290
- message: "WebSocket stream error",
20291
- explanation: `The WebSocket stream emitted an error event. Details: ${string_pretty(err)}`,
20292
- options: this.options,
20293
- exc: streamError
20294
- })
20295
- });
20296
- }
20297
- sendPings() {
20298
- this.stopPings();
20299
- this.pingInterval = window.setInterval(()=>{
20300
- this.options.logger.debug("Recorder: pinging...");
20301
- this.writeStream(Buffer.from(""));
20302
- }, this.options.timeouts.pingInterval);
20303
- }
20304
- stopPings() {
20305
- if (void 0 === this.pingInterval) return;
20306
- this.options.logger.debug("Recorder: stopping pings...");
20307
- window.clearInterval(this.pingInterval);
20308
- this.pingInterval = void 0;
20309
- }
20310
- onAudioSample(audioSample) {
20311
- var _this_userMedia;
20312
- if (this.recordingTransportFailed || this.cameraRecovery) return;
20313
- const sampleRate = null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.getAudioSampleRate();
20314
- if (sampleRate && sampleRate > 0) null != this.recordingAudioSampleRate || (this.recordingAudioSampleRate = sampleRate);
20315
- this.samplesCount++;
20316
- this.mediaTransmissionStarted = true;
20317
- const audioBuffer = audioSample.toBuffer();
20318
- this.writeStream(audioBuffer);
20319
- }
20320
- show() {
20321
- html_showElement(this.recorderElement);
20322
- }
20323
- onUserMediaReady(params) {
20324
- try {
20325
- this.options.logger.debug(`Recorder: onUserMediaReady(${params ? string_pretty(params) : ""})`);
20326
- const switchingFacingMode = null == params ? void 0 : params.switchingFacingMode;
20327
- if (null == params ? void 0 : params.recovering) {
20328
- var _this_userMedia;
20329
- if (!(null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.hasLiveStream())) return void this.failCameraRecovery(new Error("The restored camera has no live tracks."));
20330
- if (void 0 !== this.recordingAudioSampleRate && this.userMedia.getAudioSampleRate() !== this.recordingAudioSampleRate) return void this.failCameraRecovery(new Error("The audio sample rate changed during recovery."));
20331
- }
20332
- this.userMediaLoading = this.blocking = this.unloaded = this.submitting = false;
20333
- this.userMediaLoaded = true;
20334
- this.clearUserMediaTimeout();
20335
- if (!switchingFacingMode && !(null == params ? void 0 : params.recovering)) this.loop = this.createLoop();
20336
- this.show();
20337
- if (null == params ? void 0 : params.recordWhenReady) this.record();
20338
- this.emit("USER_MEDIA_READY", {
20339
- switchingFacingMode: null == params ? void 0 : params.switchingFacingMode,
20340
- recovering: null == params ? void 0 : params.recovering,
20341
- paused: this.isPaused(),
20342
- recordWhenReady: null == params ? void 0 : params.recordWhenReady
20343
- });
20344
- if (null == params ? void 0 : params.recovering) this.finishCameraRecovery(true);
20345
- } catch (exc) {
20346
- if (null == params ? void 0 : params.recovering) this.failCameraRecovery(exc);
20347
- else this.emit("ERROR", {
20348
- exc
20349
- });
20350
- }
20351
- }
20352
- clearRetryTimeout() {
20353
- if (void 0 === this.retryTimeout) return;
20354
- this.options.logger.debug("Recorder: clearRetryTimeout()");
20355
- window.clearTimeout(this.retryTimeout);
20356
- this.retryTimeout = void 0;
20357
- }
20358
- clearConnectionTimeout() {
20359
- if (void 0 === this.connectionTimeout) return;
20360
- this.options.logger.debug("Recorder: clearConnectionTimeout()");
20361
- window.clearTimeout(this.connectionTimeout);
20362
- this.connectionTimeout = void 0;
20363
- }
20364
- clearBackpressureTimeout() {
20365
- if (void 0 === this.backpressureTimeout) return;
20366
- window.clearTimeout(this.backpressureTimeout);
20367
- this.backpressureTimeout = void 0;
19666
+ clearConnectionTimeout() {
19667
+ if (void 0 === this.connectionTimeout) return;
19668
+ this.options.logger.debug("Recorder: clearConnectionTimeout()");
19669
+ window.clearTimeout(this.connectionTimeout);
19670
+ this.connectionTimeout = void 0;
20368
19671
  }
20369
19672
  clearReconnectTimeout() {
20370
19673
  if (void 0 === this.reconnectTimeout) return;
@@ -20397,16 +19700,6 @@ var __webpack_exports__ = {};
20397
19700
  shouldContinueReconnect() {
20398
19701
  return this.reconnecting && !this.unloaded && !this.blocking;
20399
19702
  }
20400
- discardSocket() {
20401
- this.options.logger.debug("Recorder: discarding socket stream ...");
20402
- this.clearBackpressureTimeout();
20403
- this.pendingWrites.clear();
20404
- this.streamBackpressured = false;
20405
- this.resumeAfterDrain = false;
20406
- const stream = this.stream;
20407
- this.stream = void 0;
20408
- if (stream && !stream.destroyed) stream.destroy();
20409
- }
20410
19703
  isOnline() {
20411
19704
  return navigator.onLine;
20412
19705
  }
@@ -20469,78 +19762,6 @@ var __webpack_exports__ = {};
20469
19762
  shouldIgnoreConnectionFailure() {
20470
19763
  return this.connectionFailed || this.connected || Boolean(this.unloaded) || this.validate();
20471
19764
  }
20472
- calculateFrameProgress() {
20473
- return `${(this.confirmedFrameNumber / (this.framesCount || 1) * 100).toFixed(2)}%`;
20474
- }
20475
- calculateSampleProgress() {
20476
- return `${(this.confirmedSampleNumber / (this.samplesCount || 1) * 100).toFixed(2)}%`;
20477
- }
20478
- updateOverallProgress() {
20479
- this.frameProgress = this.calculateFrameProgress();
20480
- if (isAudioEnabled(this.options)) this.sampleProgress = this.calculateSampleProgress();
20481
- this.emit("PROGRESS", {
20482
- frameProgress: this.frameProgress,
20483
- sampleProgress: this.sampleProgress
20484
- });
20485
- }
20486
- updateFrameProgress(args) {
20487
- if (args) {
20488
- if (!args.frame) throw error_createError({
20489
- message: "The frame number is missing",
20490
- options: this.options
20491
- });
20492
- } else throw error_createError({
20493
- message: "Arguments are missing for updating the frame progress",
20494
- options: this.options
20495
- });
20496
- this.confirmedFrameNumber = args.frame;
20497
- this.frameProgress = this.calculateFrameProgress();
20498
- this.updateOverallProgress();
20499
- }
20500
- updateSampleProgress(args) {
20501
- if (args) {
20502
- if (!args.sample) throw error_createError({
20503
- message: "The audio sample number is missing",
20504
- options: this.options
20505
- });
20506
- } else throw error_createError({
20507
- message: "Arguments are missing for updating the audio sample progress",
20508
- options: this.options
20509
- });
20510
- this.confirmedSampleNumber = args.sample;
20511
- this.sampleProgress = this.calculateSampleProgress();
20512
- this.updateOverallProgress();
20513
- }
20514
- preview(args) {
20515
- var _args_duration;
20516
- if (!args) throw error_createError({
20517
- message: "Preview arguments are missing.",
20518
- options: this.options
20519
- });
20520
- const hasAudio = this.samplesCount > 0;
20521
- this.mediaTransmissionStarted = false;
20522
- this.recordingActive = false;
20523
- this.recordingTransportFailed = false;
20524
- this.confirmedFrameNumber = this.confirmedSampleNumber = this.samplesCount = this.framesCount = 0;
20525
- this.sampleProgress = this.frameProgress = void 0;
20526
- this.key = args.key;
20527
- if (args.mp4) this.replay.setMp4Source(`${args.mp4 + constants.WHITELIST_KEY_LABEL}/${this.options.whitelistKey}/videomail.mp4`, true);
20528
- if (args.webm) this.replay.setWebMSource(`${args.webm + constants.WHITELIST_KEY_LABEL}/${this.options.whitelistKey}/videomail.webm`, true);
20529
- this.hide();
20530
- const widthDimension = this.getRecorderWidth(true);
20531
- const heightDimension = this.getRecorderHeight(true);
20532
- const duration = null != (_args_duration = args.duration) ? _args_duration : -1;
20533
- this.emit("PREVIEW", {
20534
- key: this.key,
20535
- width: null == widthDimension ? void 0 : widthDimension.value,
20536
- height: null == heightDimension ? void 0 : heightDimension.value,
20537
- hasAudio,
20538
- duration
20539
- });
20540
- if (this.stopTime) this.waitingTime = Date.now() - this.stopTime;
20541
- null != this.recordingStats || (this.recordingStats = {});
20542
- this.recordingStats.waitingTime = this.waitingTime;
20543
- }
20544
19765
  initSocket(cb) {
20545
19766
  if (this.connected) {
20546
19767
  this.options.logger.debug("Recorder: already **connected**. Not going to initialize a new WebSocket connection.");
@@ -20709,6 +19930,75 @@ var __webpack_exports__ = {};
20709
19930
  });
20710
19931
  }
20711
19932
  }
19933
+ writeCommand(command, args, cb) {
19934
+ if (this.connected) {
19935
+ if (this.stream) {
19936
+ if (args) this.options.logger.debug(`$ ${command} with ${string_pretty(args)}`);
19937
+ else this.options.logger.debug(`$ ${command}`);
19938
+ const commandObj = {
19939
+ command,
19940
+ args
19941
+ };
19942
+ this.writeStream(Buffer.from(JSON.stringify(commandObj)), cb ? {
19943
+ onFlushedCallback: ()=>{
19944
+ queueMicrotask(cb);
19945
+ }
19946
+ } : void 0);
19947
+ }
19948
+ } else {
19949
+ this.options.logger.debug(`Reconnecting for the command ${command} …`);
19950
+ this.initSocket(()=>{
19951
+ this.writeCommand(command, args, cb);
19952
+ });
19953
+ }
19954
+ }
19955
+ constructor(options){
19956
+ super(options), connection_define_property(this, "reconnectTimeout", void 0), connection_define_property(this, "connectionTimeout", void 0), connection_define_property(this, "userMediaLoaded", void 0), connection_define_property(this, "userMediaLoading", false), connection_define_property(this, "unloaded", void 0), connection_define_property(this, "connectionFailed", false), connection_define_property(this, "reconnectAttempts", 0), connection_define_property(this, "blocking", false), connection_define_property(this, "connectingStartedAt", void 0), connection_define_property(this, "lastCloseEvent", void 0), connection_define_property(this, "lastSocketError", void 0), connection_define_property(this, "pingInterval", void 0);
19957
+ }
19958
+ }
19959
+ const connection = RecorderConnection;
19960
+ function createUserMediaConstraints({ options, facingMode, limitedWidth, userMediaParams }) {
19961
+ const video = {
19962
+ frameRate: {
19963
+ ideal: options.video.fps
19964
+ }
19965
+ };
19966
+ if ((null == userMediaParams ? void 0 : userMediaParams.switchingFacingMode) || (null == userMediaParams ? void 0 : userMediaParams.recovering)) video.facingMode = userMediaParams.switchingFacingMode || facingMode;
19967
+ if (options.video.width) video.width = {
19968
+ ideal: options.video.width
19969
+ };
19970
+ else if (null == limitedWidth ? void 0 : limitedWidth.value) video.width = {
19971
+ ideal: limitedWidth.value
19972
+ };
19973
+ if (options.video.height) video.height = {
19974
+ ideal: options.video.height
19975
+ };
19976
+ return {
19977
+ audio: isAudioEnabled(options),
19978
+ video
19979
+ };
19980
+ }
19981
+ const mediaConstraints = createUserMediaConstraints;
19982
+ function media_define_property(obj, key, value) {
19983
+ if (key in obj) Object.defineProperty(obj, key, {
19984
+ value: value,
19985
+ enumerable: true,
19986
+ configurable: true,
19987
+ writable: true
19988
+ });
19989
+ else obj[key] = value;
19990
+ return obj;
19991
+ }
19992
+ class RecorderMedia extends connection {
19993
+ show() {
19994
+ html_showElement(this.recorderElement);
19995
+ }
19996
+ clearRetryTimeout() {
19997
+ if (void 0 === this.retryTimeout) return;
19998
+ this.options.logger.debug("Recorder: clearRetryTimeout()");
19999
+ window.clearTimeout(this.retryTimeout);
20000
+ this.retryTimeout = void 0;
20001
+ }
20712
20002
  showUserMedia() {
20713
20003
  if (!this.connected) return false;
20714
20004
  const hidden = this.isHidden();
@@ -20794,15 +20084,13 @@ var __webpack_exports__ = {};
20794
20084
  this.emit("ASKING_WEBCAM_PERMISSION");
20795
20085
  this.userMediaLoading = true;
20796
20086
  const requestId = ++this.mediaRequestId;
20797
- const constraints = {
20798
- video: {
20799
- frameRate: {
20800
- ideal: this.options.video.fps
20801
- }
20802
- },
20803
- audio: isAudioEnabled(this.options)
20804
- };
20805
- this.configureVideoConstraints(constraints, params);
20087
+ const limitedWidth = this.options.video.width ? void 0 : this.visuals.limitWidth();
20088
+ const constraints = mediaConstraints({
20089
+ facingMode: this.facingMode,
20090
+ limitedWidth,
20091
+ options: this.options,
20092
+ userMediaParams: params
20093
+ });
20806
20094
  this.options.logger.debug(string_summarize("Recorder: our webcam constraints are:", constraints));
20807
20095
  this.options.logger.debug(string_summarize("Recorder: available webcam constraints are:", navigator.mediaDevices.getSupportedConstraints()));
20808
20096
  const streamPromise = navigator.mediaDevices.getUserMedia(constraints);
@@ -20815,23 +20103,6 @@ var __webpack_exports__ = {};
20815
20103
  if (!this.unloaded && requestId === this.mediaRequestId) this.userMediaErrorCallback(reason, constraints);
20816
20104
  });
20817
20105
  }
20818
- configureVideoConstraints(constraints, params) {
20819
- const videoConstraints = "object" == typeof constraints.video ? constraints.video : void 0;
20820
- if (!videoConstraints) return;
20821
- if ((null == params ? void 0 : params.switchingFacingMode) || (null == params ? void 0 : params.recovering)) videoConstraints.facingMode = params.switchingFacingMode || this.facingMode;
20822
- if (this.options.video.width) videoConstraints.width = {
20823
- ideal: this.options.video.width
20824
- };
20825
- else {
20826
- const limitedWidth = this.limitWidth();
20827
- if (null == limitedWidth ? void 0 : limitedWidth.value) videoConstraints.width = {
20828
- ideal: limitedWidth.value
20829
- };
20830
- }
20831
- if (this.options.video.height) videoConstraints.height = {
20832
- ideal: this.options.video.height
20833
- };
20834
- }
20835
20106
  loadUserMedia(params) {
20836
20107
  if (this.userMediaLoaded) {
20837
20108
  this.options.logger.debug("Recorder: skipping loadUserMedia() because it is already loaded");
@@ -20841,393 +20112,1478 @@ var __webpack_exports__ = {};
20841
20112
  this.options.logger.debug(`Recorder: loadUserMedia(${params ? string_pretty(params) : ""})`);
20842
20113
  this.emit("LOADING_USER_MEDIA");
20843
20114
  try {
20844
- if (!navigator.mediaDevices) throw new Error("No media devices are available.");
20845
- this.userMediaTimeout = window.setTimeout(()=>{
20846
- if (!this.userMediaLoaded) {
20847
- this.userMediaLoading = false;
20848
- const err = util_getBrowser(this.options).getNoAccessIssue();
20849
- this.userMediaErrorCallback(err, {
20850
- audio: isAudioEnabled(this.options)
20851
- });
20852
- }
20853
- }, this.options.timeouts.userMedia);
20854
- this.userMediaLoading = true;
20855
- this.loadGenuineUserMedia(params);
20856
- } catch (exc) {
20857
- this.clearUserMediaTimeout();
20858
- this.options.logger.debug("Recorder: failed to load genuine user media");
20859
- this.userMediaLoading = false;
20860
- if (this.cameraRecovery) return void this.failCameraRecovery(exc);
20861
- const errorListeners = this.getListeners("ERROR");
20862
- if (null == errorListeners ? void 0 : errorListeners.length) this.emit("ERROR", {
20863
- exc
20115
+ if (!navigator.mediaDevices) throw new Error("No media devices are available.");
20116
+ this.userMediaTimeout = window.setTimeout(()=>{
20117
+ if (!this.userMediaLoaded) {
20118
+ this.userMediaLoading = false;
20119
+ const err = util_getBrowser(this.options).getNoAccessIssue();
20120
+ this.userMediaErrorCallback(err, {
20121
+ audio: isAudioEnabled(this.options)
20122
+ });
20123
+ }
20124
+ }, this.options.timeouts.userMedia);
20125
+ this.userMediaLoading = true;
20126
+ this.loadGenuineUserMedia(params);
20127
+ } catch (exc) {
20128
+ this.clearUserMediaTimeout();
20129
+ this.options.logger.debug("Recorder: failed to load genuine user media");
20130
+ this.userMediaLoading = false;
20131
+ if (this.cameraRecovery) return void this.failCameraRecovery(exc);
20132
+ const errorListeners = this.getListeners("ERROR");
20133
+ if (null == errorListeners ? void 0 : errorListeners.length) this.emit("ERROR", {
20134
+ exc
20135
+ });
20136
+ else {
20137
+ this.options.logger.debug("Recorder: no error listeners attached but throwing exception further");
20138
+ throw exc;
20139
+ }
20140
+ }
20141
+ }
20142
+ isNotifying() {
20143
+ return this.visuals.isNotifying();
20144
+ }
20145
+ isHidden() {
20146
+ return !this.recorderElement || html_isHidden(this.recorderElement);
20147
+ }
20148
+ clearUserMediaTimeout() {
20149
+ if (void 0 !== this.userMediaTimeout) {
20150
+ this.options.logger.debug("Recorder: clearUserMediaTimeout()");
20151
+ window.clearTimeout(this.userMediaTimeout);
20152
+ this.userMediaTimeout = void 0;
20153
+ }
20154
+ }
20155
+ clearStopTimeout() {
20156
+ if (void 0 === this.stopTimeout) return;
20157
+ window.clearTimeout(this.stopTimeout);
20158
+ this.stopTimeout = void 0;
20159
+ }
20160
+ isReady() {
20161
+ var _this_userMedia;
20162
+ return null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isReady();
20163
+ }
20164
+ finishCameraRecovery(restored) {
20165
+ this.clearUserMediaTimeout();
20166
+ const resolve = this.resolveCameraRecovery;
20167
+ const resumeRequested = restored && this.resumeAfterCameraRecovery;
20168
+ this.cameraRecovery = void 0;
20169
+ this.resolveCameraRecovery = void 0;
20170
+ this.resumeAfterCameraRecovery = false;
20171
+ null == resolve || resolve(restored);
20172
+ if (resumeRequested && this.isPaused()) this.resume();
20173
+ }
20174
+ cancelCameraRecovery() {
20175
+ var _this_userMedia;
20176
+ if (!this.cameraRecovery) return;
20177
+ this.mediaRequestId++;
20178
+ this.userMediaLoading = false;
20179
+ this.userMediaLoaded = false;
20180
+ this.clearUserMediaTimeout();
20181
+ null == (_this_userMedia = this.userMedia) || _this_userMedia.stop(void 0, {
20182
+ preserveRecordingState: true
20183
+ });
20184
+ this.finishCameraRecovery(false);
20185
+ }
20186
+ failCameraRecovery(exc) {
20187
+ this.cancelCameraRecovery();
20188
+ const err = error_createError({
20189
+ message: "Camera recovery failed",
20190
+ explanation: "Your recording is still paused. Check camera permissions, then try Resume again or stop to keep the recorded part.",
20191
+ exc,
20192
+ options: this.options
20193
+ });
20194
+ this.emit("CAMERA_RECOVERY_FAILED", {
20195
+ err
20196
+ });
20197
+ }
20198
+ recoverCamera() {
20199
+ if (this.cameraRecovery) return this.cameraRecovery;
20200
+ if (!this.built || this.unloaded || !this.userMedia || this.userMediaLoading || this.submitting || this.key || void 0 !== this.stopTimeout || this.recordingTransportFailed) return Promise.resolve(false);
20201
+ const liveStream = this.userMedia.hasLiveStream();
20202
+ if (liveStream && this.isRecording()) return Promise.resolve(true);
20203
+ if (!liveStream && this.recordingActive && !this.isPaused()) this.pause();
20204
+ const recovery = new Promise((resolve)=>{
20205
+ this.resolveCameraRecovery = resolve;
20206
+ });
20207
+ this.cameraRecovery = recovery;
20208
+ this.emit("CAMERA_RECOVERING");
20209
+ if (liveStream) {
20210
+ this.userMediaTimeout = window.setTimeout(()=>{
20211
+ this.failCameraRecovery(new Error("Camera playback recovery timed out."));
20212
+ }, this.options.timeouts.userMedia);
20213
+ this.userMedia.restorePlayback().then(()=>{
20214
+ if (this.cameraRecovery === recovery) this.finishCameraRecovery(true);
20215
+ }).catch((exc)=>{
20216
+ if (this.cameraRecovery === recovery) this.failCameraRecovery(exc);
20217
+ });
20218
+ } else {
20219
+ this.userMediaLoaded = false;
20220
+ this.loadUserMedia({
20221
+ recovering: true
20222
+ });
20223
+ }
20224
+ return recovery;
20225
+ }
20226
+ switchFacingMode() {
20227
+ if (this.cameraRecovery || !util_getBrowser(this.options).isMobile()) return;
20228
+ if ("user" === this.facingMode) this.facingMode = "environment";
20229
+ else if ("environment" === this.facingMode) this.facingMode = "user";
20230
+ else this.options.logger.warn(`Recorder: unsupported facing mode ${string_pretty(this.facingMode)}`);
20231
+ this.loadGenuineUserMedia({
20232
+ switchingFacingMode: this.facingMode
20233
+ });
20234
+ }
20235
+ hide() {
20236
+ if (!this.isHidden()) {
20237
+ if (this.recorderElement) html_hideElement(this.recorderElement);
20238
+ this.clearUserMediaTimeout();
20239
+ this.clearRetryTimeout();
20240
+ }
20241
+ }
20242
+ isUnloaded() {
20243
+ return this.unloaded;
20244
+ }
20245
+ isUserMediaLoaded() {
20246
+ return this.userMediaLoaded;
20247
+ }
20248
+ constructor(visuals, options){
20249
+ super(options), media_define_property(this, "visuals", void 0), media_define_property(this, "recorderElement", void 0), media_define_property(this, "userMedia", void 0), media_define_property(this, "userMediaTimeout", void 0), media_define_property(this, "retryTimeout", void 0), media_define_property(this, "stopTimeout", void 0), media_define_property(this, "mediaRequestId", 0), media_define_property(this, "cameraRecovery", void 0), media_define_property(this, "resolveCameraRecovery", void 0), media_define_property(this, "resumeAfterCameraRecovery", false), media_define_property(this, "submitting", false), media_define_property(this, "built", false), media_define_property(this, "key", void 0), media_define_property(this, "facingMode", void 0);
20250
+ this.visuals = visuals;
20251
+ this.facingMode = options.video.facingMode;
20252
+ }
20253
+ }
20254
+ const media = RecorderMedia;
20255
+ function calculateProgress(confirmedCount, totalCount) {
20256
+ return `${(confirmedCount / (totalCount || 1) * 100).toFixed(2)}%`;
20257
+ }
20258
+ function getConfirmedProgressNumber({ args, kind, options }) {
20259
+ const label = "frame" === kind ? "frame" : "audio sample";
20260
+ if (!args) throw error_createError({
20261
+ message: `Arguments are missing for updating the ${label} progress`,
20262
+ options
20263
+ });
20264
+ const confirmedNumber = args[kind];
20265
+ if (!confirmedNumber) throw error_createError({
20266
+ message: `The ${label} number is missing`,
20267
+ options
20268
+ });
20269
+ return confirmedNumber;
20270
+ }
20271
+ var capture_Buffer = __webpack_require__("dY").Buffer;
20272
+ function capture_define_property(obj, key, value) {
20273
+ if (key in obj) Object.defineProperty(obj, key, {
20274
+ value: value,
20275
+ enumerable: true,
20276
+ configurable: true,
20277
+ writable: true
20278
+ });
20279
+ else obj[key] = value;
20280
+ return obj;
20281
+ }
20282
+ function capture_object_spread(target) {
20283
+ for(var i = 1; i < arguments.length; i++){
20284
+ var source = null != arguments[i] ? arguments[i] : {};
20285
+ var ownKeys = Object.keys(source);
20286
+ if ("function" == typeof Object.getOwnPropertySymbols) ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
20287
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
20288
+ }));
20289
+ ownKeys.forEach(function(key) {
20290
+ capture_define_property(target, key, source[key]);
20291
+ });
20292
+ }
20293
+ return target;
20294
+ }
20295
+ class RecorderCapture extends media {
20296
+ onAudioSample(audioSample) {
20297
+ var _this_userMedia;
20298
+ if (this.recordingTransportFailed || this.cameraRecovery) return;
20299
+ const sampleRate = null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.getAudioSampleRate();
20300
+ if (sampleRate && sampleRate > 0) null != this.recordingAudioSampleRate || (this.recordingAudioSampleRate = sampleRate);
20301
+ this.samplesCount++;
20302
+ this.mediaTransmissionStarted = true;
20303
+ const audioBuffer = audioSample.toBuffer();
20304
+ this.writeStream(audioBuffer);
20305
+ }
20306
+ onUserMediaReady(params) {
20307
+ try {
20308
+ this.options.logger.debug(`Recorder: onUserMediaReady(${params ? string_pretty(params) : ""})`);
20309
+ const switchingFacingMode = null == params ? void 0 : params.switchingFacingMode;
20310
+ if (null == params ? void 0 : params.recovering) {
20311
+ var _this_userMedia;
20312
+ if (!(null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.hasLiveStream())) return void this.failCameraRecovery(new Error("The restored camera has no live tracks."));
20313
+ if (void 0 !== this.recordingAudioSampleRate && this.userMedia.getAudioSampleRate() !== this.recordingAudioSampleRate) return void this.failCameraRecovery(new Error("The audio sample rate changed during recovery."));
20314
+ }
20315
+ this.userMediaLoading = this.blocking = this.unloaded = this.submitting = false;
20316
+ this.userMediaLoaded = true;
20317
+ this.clearUserMediaTimeout();
20318
+ if (!switchingFacingMode && !(null == params ? void 0 : params.recovering)) this.loop = this.createLoop();
20319
+ this.show();
20320
+ if (null == params ? void 0 : params.recordWhenReady) this.record();
20321
+ this.emit("USER_MEDIA_READY", {
20322
+ switchingFacingMode: null == params ? void 0 : params.switchingFacingMode,
20323
+ recovering: null == params ? void 0 : params.recovering,
20324
+ paused: this.isPaused(),
20325
+ recordWhenReady: null == params ? void 0 : params.recordWhenReady
20326
+ });
20327
+ if (null == params ? void 0 : params.recovering) this.finishCameraRecovery(true);
20328
+ } catch (exc) {
20329
+ if (null == params ? void 0 : params.recovering) this.failCameraRecovery(exc);
20330
+ else this.emit("ERROR", {
20331
+ exc
20332
+ });
20333
+ }
20334
+ }
20335
+ calculateFrameProgress() {
20336
+ return calculateProgress(this.confirmedFrameNumber, this.framesCount);
20337
+ }
20338
+ calculateSampleProgress() {
20339
+ return calculateProgress(this.confirmedSampleNumber, this.samplesCount);
20340
+ }
20341
+ updateOverallProgress() {
20342
+ this.frameProgress = this.calculateFrameProgress();
20343
+ if (isAudioEnabled(this.options)) this.sampleProgress = this.calculateSampleProgress();
20344
+ this.emit("PROGRESS", {
20345
+ frameProgress: this.frameProgress,
20346
+ sampleProgress: this.sampleProgress
20347
+ });
20348
+ }
20349
+ updateFrameProgress(args) {
20350
+ this.confirmedFrameNumber = getConfirmedProgressNumber({
20351
+ args,
20352
+ kind: "frame",
20353
+ options: this.options
20354
+ });
20355
+ this.frameProgress = this.calculateFrameProgress();
20356
+ this.updateOverallProgress();
20357
+ }
20358
+ updateSampleProgress(args) {
20359
+ this.confirmedSampleNumber = getConfirmedProgressNumber({
20360
+ args,
20361
+ kind: "sample",
20362
+ options: this.options
20363
+ });
20364
+ this.sampleProgress = this.calculateSampleProgress();
20365
+ this.updateOverallProgress();
20366
+ }
20367
+ preview(args) {
20368
+ var _args_duration;
20369
+ if (!args) throw error_createError({
20370
+ message: "Preview arguments are missing.",
20371
+ options: this.options
20372
+ });
20373
+ const hasAudio = this.samplesCount > 0;
20374
+ this.mediaTransmissionStarted = false;
20375
+ this.recordingActive = false;
20376
+ this.recordingTransportFailed = false;
20377
+ this.confirmedFrameNumber = this.confirmedSampleNumber = this.samplesCount = this.framesCount = 0;
20378
+ this.sampleProgress = this.frameProgress = void 0;
20379
+ this.key = args.key;
20380
+ if (args.mp4) this.replay.setMp4Source(`${args.mp4 + constants.WHITELIST_KEY_LABEL}/${this.options.whitelistKey}/videomail.mp4`, true);
20381
+ if (args.webm) this.replay.setWebMSource(`${args.webm + constants.WHITELIST_KEY_LABEL}/${this.options.whitelistKey}/videomail.webm`, true);
20382
+ this.hide();
20383
+ const widthDimension = this.getRecorderWidth(true);
20384
+ const heightDimension = this.getRecorderHeight(true);
20385
+ const duration = null != (_args_duration = args.duration) ? _args_duration : -1;
20386
+ this.emit("PREVIEW", {
20387
+ key: this.key,
20388
+ width: null == widthDimension ? void 0 : widthDimension.value,
20389
+ height: null == heightDimension ? void 0 : heightDimension.value,
20390
+ hasAudio,
20391
+ duration
20392
+ });
20393
+ if (this.stopTime) this.waitingTime = Date.now() - this.stopTime;
20394
+ null != this.recordingStats || (this.recordingStats = {});
20395
+ this.recordingStats.waitingTime = this.waitingTime;
20396
+ }
20397
+ cancelAnimationFrame() {
20398
+ var _this_loop;
20399
+ null == (_this_loop = this.loop) || _this_loop.dispose();
20400
+ }
20401
+ getIntervalSum() {
20402
+ if (!this.loop) return;
20403
+ return this.loop.getElapsedTime();
20404
+ }
20405
+ getAvgInterval() {
20406
+ var _this_getIntervalSum;
20407
+ const intervalSum = null != (_this_getIntervalSum = this.getIntervalSum()) ? _this_getIntervalSum : 0;
20408
+ if (!this.hasValidInterval(intervalSum)) return;
20409
+ return intervalSum / this.framesCount;
20410
+ }
20411
+ getAvgFps() {
20412
+ var _this_getIntervalSum;
20413
+ const intervalSum = null != (_this_getIntervalSum = this.getIntervalSum()) ? _this_getIntervalSum : 0;
20414
+ if (!this.hasValidInterval(intervalSum)) return;
20415
+ return this.framesCount / intervalSum * 1000;
20416
+ }
20417
+ hasValidInterval(intervalSum) {
20418
+ return intervalSum > 0;
20419
+ }
20420
+ getRecordingStats() {
20421
+ return this.recordingStats;
20422
+ }
20423
+ getAudioSampleRate() {
20424
+ var _this_recordingAudioSampleRate;
20425
+ var _this_userMedia;
20426
+ return null != (_this_recordingAudioSampleRate = this.recordingAudioSampleRate) ? _this_recordingAudioSampleRate : null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.getAudioSampleRate();
20427
+ }
20428
+ stop(params) {
20429
+ var _this_loop_complete, _this_loop;
20430
+ this.cancelCameraRecovery();
20431
+ if (!this.userMedia) throw new Error("No user media defined, unable to stop");
20432
+ this.options.logger.debug(`Recorder: stop(${params ? string_pretty(params) : ""})`);
20433
+ this.recordingActive = false;
20434
+ const limitReached = null == params ? void 0 : params.limitReached;
20435
+ this.emit("STOPPING", {
20436
+ limitReached
20437
+ });
20438
+ null == (_this_loop = this.loop) || null == (_this_loop_complete = _this_loop.complete) || _this_loop_complete.call(_this_loop);
20439
+ this.stopTimeout = window.setTimeout(()=>{
20440
+ this.stopTimeout = void 0;
20441
+ this.stopTime = Date.now();
20442
+ const videoType = this.replay.getVideoType();
20443
+ if (!videoType) throw new Error("Unable to video record when no video type is defined.");
20444
+ this.recordingStats = {
20445
+ avgFps: this.getAvgFps(),
20446
+ wantedFps: this.options.video.fps,
20447
+ avgInterval: this.getAvgInterval(),
20448
+ wantedInterval: 1e3 / this.options.video.fps,
20449
+ intervalSum: this.getIntervalSum(),
20450
+ framesCount: this.framesCount,
20451
+ videoType
20452
+ };
20453
+ if (this.userMedia) this.recordingStats.videoTrackLabel = this.userMedia.getVideoTrackLabel();
20454
+ if (isAudioEnabled(this.options) && this.userMedia) {
20455
+ var _this_recordingAudioSampleRate;
20456
+ this.recordingStats.samplesCount = this.samplesCount;
20457
+ this.recordingStats.sampleRate = null != (_this_recordingAudioSampleRate = this.recordingAudioSampleRate) ? _this_recordingAudioSampleRate : this.userMedia.getAudioSampleRate();
20458
+ }
20459
+ this.writeCommand("stop", this.recordingStats, ()=>{
20460
+ this.emit("STOPPED", {
20461
+ recordingStats: this.recordingStats
20462
+ });
20463
+ });
20464
+ this.reset();
20465
+ }, 60);
20466
+ }
20467
+ back(cb) {
20468
+ this.emit("GOING_BACK");
20469
+ this.key = void 0;
20470
+ this.recordingDimensions = void 0;
20471
+ this.unloaded = false;
20472
+ this.show();
20473
+ this.writeCommand("back", void 0, cb);
20474
+ }
20475
+ reInitializeAudio() {
20476
+ var _this_userMedia;
20477
+ this.options.logger.debug("Recorder: reInitializeAudio()");
20478
+ this.clearUserMediaTimeout();
20479
+ this.userMediaLoading = false;
20480
+ null == (_this_userMedia = this.userMedia) || _this_userMedia.stop();
20481
+ this.recordingDimensions = void 0;
20482
+ this.userMediaLoaded = this.key = this.canvas = this.ctx = void 0;
20483
+ this.loadUserMedia();
20484
+ }
20485
+ reset() {
20486
+ this.cancelCameraRecovery();
20487
+ if (!this.unloaded) {
20488
+ var _this_userMedia;
20489
+ this.options.logger.debug("Recorder: reset()");
20490
+ this.emit("RESETTING");
20491
+ this.cancelAnimationFrame();
20492
+ null == (_this_userMedia = this.userMedia) || _this_userMedia.stop();
20493
+ this.replay.reset();
20494
+ this.userMediaLoaded = this.key = this.canvas = this.ctx = this.recordingBuffer = void 0;
20495
+ }
20496
+ }
20497
+ validate() {
20498
+ return Boolean(this.key) && void 0 === this.canvas;
20499
+ }
20500
+ pause(params) {
20501
+ var _this_userMedia;
20502
+ this.cancelCameraRecovery();
20503
+ this.resumeAfterDrain = false;
20504
+ const loop = this.loop;
20505
+ if (!loop) throw new Error("No recording loop defined");
20506
+ if (params) this.options.logger.debug(`pause() at frame ${this.framesCount} with ${string_pretty(params)}`);
20507
+ else this.options.logger.debug(`pause() at frame ${this.framesCount}`);
20508
+ null == (_this_userMedia = this.userMedia) || _this_userMedia.pause();
20509
+ loop.stop();
20510
+ this.emit("PAUSED");
20511
+ this.sendPings();
20512
+ }
20513
+ resume() {
20514
+ var _this_userMedia;
20515
+ if (this.cameraRecovery || !(null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.hasLiveStream())) {
20516
+ this.recoverCamera();
20517
+ this.resumeAfterCameraRecovery = Boolean(this.cameraRecovery);
20518
+ return;
20519
+ }
20520
+ const loop = this.loop;
20521
+ if (!loop) throw new Error("No recording loop defined");
20522
+ this.options.logger.debug(`Recorder: resume() with frame ${this.framesCount}`);
20523
+ this.stopPings();
20524
+ this.emit("RESUMING");
20525
+ this.userMedia.resume();
20526
+ if (this.streamBackpressured) this.resumeAfterDrain = true;
20527
+ else loop.start();
20528
+ }
20529
+ onFlushed(opts) {
20530
+ const frameNumber = opts.frameNumber;
20531
+ if (1 === frameNumber) this.emit("FIRST_FRAME_SENT");
20532
+ }
20533
+ draw(_deltaTime, elapsedTime) {
20534
+ if (this.recordingTransportFailed) return;
20535
+ if (!this.userMedia) throw new Error("No user media defined, unable to draw on canvas");
20536
+ try {
20537
+ if (!this.isPaused() && this.stream && this.ctx) {
20538
+ var _this_frame, _this_recordingBuffer;
20539
+ if (0 === this.framesCount) this.emit("SENDING_FIRST_FRAME");
20540
+ this.framesCount++;
20541
+ const imageSource = this.userMedia.getRawVisuals();
20542
+ if (this.canvas && imageSource) this.ctx.drawImage(imageSource, 0, 0, this.canvas.width, this.canvas.height);
20543
+ else throw new Error("Unable to draw an image without a defined canvas");
20544
+ this.recordingBuffer = null == (_this_frame = this.frame) ? void 0 : _this_frame.toBuffer();
20545
+ const recordingBufferLength = null == (_this_recordingBuffer = this.recordingBuffer) ? void 0 : _this_recordingBuffer.length;
20546
+ if (recordingBufferLength) {
20547
+ if (this.recordingBuffer) {
20548
+ const frameControlBuffer = capture_Buffer.from(JSON.stringify({
20549
+ frameNumber: this.framesCount
20550
+ }));
20551
+ const frameBuffer = capture_Buffer.concat([
20552
+ this.recordingBuffer,
20553
+ frameControlBuffer
20554
+ ]);
20555
+ this.mediaTransmissionStarted = true;
20556
+ this.writeStream(frameBuffer, {
20557
+ frameNumber: this.framesCount,
20558
+ onFlushedCallback: this.onFlushed.bind(this)
20559
+ });
20560
+ this.visuals.checkTimer(elapsedTime);
20561
+ }
20562
+ } else throw error_createError({
20563
+ message: "Failed to extract webcam data.",
20564
+ options: this.options
20565
+ });
20566
+ }
20567
+ } catch (exc) {
20568
+ this.emit("ERROR", {
20569
+ exc
20570
+ });
20571
+ }
20572
+ }
20573
+ createLoop() {
20574
+ const newLoop = animitter_default()({
20575
+ fps: this.options.video.fps
20576
+ }, this.draw.bind(this));
20577
+ this.originalAnimationFrameObject = newLoop.getRequestAnimationFrameObject();
20578
+ return newLoop;
20579
+ }
20580
+ record() {
20581
+ if (this.unloaded || this.cameraRecovery) return;
20582
+ if (!this.connected) {
20583
+ this.options.logger.debug("Recorder: reconnecting before recording …");
20584
+ this.initSocket(()=>{
20585
+ this.once("SERVER_READY", ()=>{
20586
+ if (this.unloaded) return;
20587
+ if (this.userMediaLoaded || this.options.loadUserMediaOnRecord) this.record();
20588
+ else this.once("USER_MEDIA_READY", ()=>{
20589
+ if (!this.unloaded) this.record();
20590
+ });
20591
+ });
20592
+ });
20593
+ return;
20594
+ }
20595
+ if (!this.userMediaLoaded) {
20596
+ if (this.options.loadUserMediaOnRecord) this.loadUserMedia({
20597
+ recordWhenReady: true
20598
+ });
20599
+ else {
20600
+ const err = error_createError({
20601
+ message: "Load and enable your camera first",
20602
+ options: this.options
20603
+ });
20604
+ this.emit("ERROR", {
20605
+ err
20606
+ });
20607
+ }
20608
+ return;
20609
+ }
20610
+ const loop = this.loop;
20611
+ if (!loop) throw new Error("No recording loop defined");
20612
+ this.recordingDimensions = void 0;
20613
+ try {
20614
+ if (!this.userMedia) throw new Error("No user media defined, unable to create canvas");
20615
+ this.canvas = this.userMedia.createCanvas();
20616
+ } catch (exc) {
20617
+ const err = error_createError({
20618
+ exc,
20619
+ options: this.options
20620
+ });
20621
+ this.emit("ERROR", {
20622
+ err
20623
+ });
20624
+ return;
20625
+ }
20626
+ this.ctx = this.canvas.getContext("2d");
20627
+ if (!this.canvas.width) {
20628
+ const err = error_createError({
20629
+ message: "Canvas has an invalid width.",
20630
+ options: this.options
20631
+ });
20632
+ this.emit("ERROR", {
20633
+ err
20634
+ });
20635
+ return;
20636
+ }
20637
+ if (!this.canvas.height) {
20638
+ const err = error_createError({
20639
+ message: "Canvas has an invalid height.",
20640
+ options: this.options
20641
+ });
20642
+ this.emit("ERROR", {
20643
+ err
20644
+ });
20645
+ return;
20646
+ }
20647
+ this.recordingDimensions = {
20648
+ width: this.canvas.width,
20649
+ height: this.canvas.height
20650
+ };
20651
+ this.frame = new canvas_to_buffer_modern_r(this.canvas, this.options.image.types, this.options.image.quality);
20652
+ this.options.logger.debug("Recorder: record()");
20653
+ this.recordingActive = true;
20654
+ this.recordingTransportFailed = false;
20655
+ this.mediaTransmissionStarted = false;
20656
+ this.recordingAudioSampleRate = void 0;
20657
+ this.userMedia.record();
20658
+ this.emit("RECORDING", {
20659
+ framesCount: this.framesCount
20660
+ });
20661
+ loop.on("update", (_deltaTime, elapsedTime)=>{
20662
+ let avgFPS;
20663
+ avgFPS = 0 !== elapsedTime ? Math.round(this.framesCount / elapsedTime * 1000) : void 0;
20664
+ this.options.logger.debug(`Recorder updates avgFps = ${avgFPS} at frame ${this.framesCount}`);
20665
+ });
20666
+ loop.start();
20667
+ }
20668
+ setAnimationFrameObject(newObj) {
20669
+ if (this.loop) {
20670
+ const isRecording = this.isRecording();
20671
+ this.loop.stop();
20672
+ this.loop.setRequestAnimationFrameObject(newObj);
20673
+ if (isRecording) this.loop.start();
20674
+ }
20675
+ }
20676
+ restoreAnimationFrameObject() {
20677
+ this.options.logger.debug("Recorder: restoreAnimationFrameObject()");
20678
+ if (this.originalAnimationFrameObject) this.setAnimationFrameObject(this.originalAnimationFrameObject);
20679
+ }
20680
+ loopWithTimeouts() {
20681
+ this.options.logger.debug("Recorder: loopWithTimeouts()");
20682
+ const wantedInterval = 1e3 / this.options.video.fps;
20683
+ let processingTime = 0;
20684
+ const raf = (fn)=>window.setTimeout(()=>{
20685
+ const start = Date.now();
20686
+ fn();
20687
+ processingTime = Date.now() - start;
20688
+ }, wantedInterval - processingTime);
20689
+ const cancel = (id)=>{
20690
+ window.clearTimeout(id);
20691
+ };
20692
+ this.setAnimationFrameObject({
20693
+ requestAnimationFrame: raf,
20694
+ cancelAnimationFrame: cancel
20695
+ });
20696
+ }
20697
+ isPaused() {
20698
+ var _this_userMedia, _this_loop;
20699
+ return (null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isPaused()) && !(null == (_this_loop = this.loop) ? void 0 : _this_loop.isRunning());
20700
+ }
20701
+ isUserMediaPaused() {
20702
+ var _ref;
20703
+ var _this_userMedia;
20704
+ return null != (_ref = null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isPaused()) ? _ref : false;
20705
+ }
20706
+ isCaptureLoopRunning() {
20707
+ var _ref;
20708
+ var _this_loop;
20709
+ return null != (_ref = null == (_this_loop = this.loop) ? void 0 : _this_loop.isRunning()) ? _ref : false;
20710
+ }
20711
+ stopCaptureLoop() {
20712
+ var _this_loop;
20713
+ null == (_this_loop = this.loop) || _this_loop.stop();
20714
+ }
20715
+ startCaptureLoop() {
20716
+ var _this_loop;
20717
+ null == (_this_loop = this.loop) || _this_loop.start();
20718
+ }
20719
+ isRecording() {
20720
+ var _this_loop;
20721
+ return Boolean((null == (_this_loop = this.loop) ? void 0 : _this_loop.isRunning()) && !this.isPaused() && !this.isNotifying() && this.stream && !this.stream.destroyed);
20722
+ }
20723
+ getRecordingDimensions() {
20724
+ return this.recordingDimensions && capture_object_spread({}, this.recordingDimensions);
20725
+ }
20726
+ constructor(visuals, replay, options){
20727
+ super(visuals, options), capture_define_property(this, "replay", void 0), capture_define_property(this, "loop", void 0), capture_define_property(this, "originalAnimationFrameObject", void 0), capture_define_property(this, "recordingAudioSampleRate", void 0), capture_define_property(this, "frameProgress", void 0), capture_define_property(this, "sampleProgress", void 0), capture_define_property(this, "canvas", void 0), capture_define_property(this, "ctx", void 0), capture_define_property(this, "stopTime", void 0), capture_define_property(this, "waitingTime", void 0), capture_define_property(this, "frame", void 0), capture_define_property(this, "recordingBuffer", void 0);
20728
+ this.replay = replay;
20729
+ }
20730
+ }
20731
+ const capture = RecorderCapture;
20732
+ function figureMinHeight(height, options) {
20733
+ let minHeight;
20734
+ if (options.video.height) {
20735
+ minHeight = height ? Math.min(options.video.height, height) : options.video.height;
20736
+ if (minHeight < 1) throw error_createError({
20737
+ message: `Got a min height less than 1 (${minHeight})!`,
20738
+ options
20739
+ });
20740
+ } else minHeight = height;
20741
+ return minHeight;
20742
+ }
20743
+ const dimensions_figureMinHeight = figureMinHeight;
20744
+ function getRatio(options, videoHeight, videoWidth) {
20745
+ let ratio = 1;
20746
+ const hasVideoDimensions = videoHeight && videoWidth;
20747
+ const desiredHeight = options.video.height;
20748
+ const desiredWidth = options.video.width;
20749
+ const hasDesiredDimensions = desiredHeight && desiredWidth;
20750
+ if (hasDesiredDimensions) ratio = hasVideoDimensions ? videoHeight < desiredHeight || videoWidth < desiredWidth ? videoHeight / videoWidth : desiredHeight / desiredWidth : desiredHeight / desiredWidth;
20751
+ else if (hasVideoDimensions) ratio = videoHeight / videoWidth;
20752
+ return ratio;
20753
+ }
20754
+ const dimensions_getRatio = getRatio;
20755
+ function calculateHeight(responsive, videoWidth, options, ratio, element) {
20756
+ const dimension = {
20757
+ unit: "px"
20758
+ };
20759
+ let width = videoWidth;
20760
+ if (responsive && element) {
20761
+ const limitedDimension = dimensions_limitWidth(element, options, width);
20762
+ width = limitedDimension.value;
20763
+ }
20764
+ const chosenRatio = null != ratio ? ratio : dimensions_getRatio(options, void 0, videoWidth);
20765
+ const height = width ? Math.round(width * chosenRatio) : void 0;
20766
+ if (height && Number.isInteger(height) && height < 1) throw error_createError({
20767
+ message: "Just calculated a height less than 1 which is wrong.",
20768
+ options
20769
+ });
20770
+ const minHeight = dimensions_figureMinHeight(height, options);
20771
+ dimension.value = minHeight;
20772
+ return dimension;
20773
+ }
20774
+ const dimensions_calculateHeight = calculateHeight;
20775
+ function calculateWidth(responsive, options, videoHeight, ratio) {
20776
+ const dimension = {
20777
+ unit: "px"
20778
+ };
20779
+ let height = dimensions_figureMinHeight(videoHeight, options);
20780
+ if (responsive) {
20781
+ const limitedDimension = dimensions_limitHeight(height, options, "calculateWidth");
20782
+ height = limitedDimension.value;
20783
+ }
20784
+ if (!height || height < 1) throw error_createError({
20785
+ message: `Height ${height} cannot be smaller than 1 when calculating width.`,
20786
+ options
20787
+ });
20788
+ const chosenRatio = null != ratio ? ratio : dimensions_getRatio(options, videoHeight);
20789
+ const calculatedWidth = Math.round(height / chosenRatio);
20790
+ if (calculatedWidth < 1) throw error_createError({
20791
+ message: "Calculated width cannot be smaller than 1!",
20792
+ options
20793
+ });
20794
+ dimension.value = calculatedWidth;
20795
+ return dimension;
20796
+ }
20797
+ const dimensions_calculateWidth = calculateWidth;
20798
+ function dimensions_define_property(obj, key, value) {
20799
+ if (key in obj) Object.defineProperty(obj, key, {
20800
+ value: value,
20801
+ enumerable: true,
20802
+ configurable: true,
20803
+ writable: true
20804
+ });
20805
+ else obj[key] = value;
20806
+ return obj;
20807
+ }
20808
+ class RecorderDimensions {
20809
+ correctDimensions() {
20810
+ const recorderElement = this.context.getRecorderElement();
20811
+ if (!recorderElement) return;
20812
+ const widthDimension = dimensions_useFullWidth(this.context.options.video.mobileBreakPoint);
20813
+ if (this.context.options.video.stretch || widthDimension) {
20814
+ recorderElement.style.width = "100%";
20815
+ recorderElement.style.removeProperty("height");
20816
+ } else {
20817
+ if (this.context.options.video.width) {
20818
+ const recorderWidth = this.getRecorderWidth(true);
20819
+ if (null == recorderWidth ? void 0 : recorderWidth.value) recorderElement.width = recorderWidth.value;
20820
+ else recorderElement.style.removeProperty("width");
20821
+ }
20822
+ if (this.context.options.video.height) {
20823
+ const recorderHeight = this.getRecorderHeight(true);
20824
+ if (null == recorderHeight ? void 0 : recorderHeight.value) recorderElement.height = recorderHeight.value;
20825
+ else recorderElement.style.removeProperty("height");
20826
+ }
20827
+ }
20828
+ }
20829
+ getRecorderWidth(responsive) {
20830
+ const userMedia = this.context.getUserMedia();
20831
+ if (null == userMedia ? void 0 : userMedia.hasVideoWidth()) return userMedia.getRawWidth(responsive);
20832
+ else if (responsive && this.context.options.video.width) return this.context.visuals.limitWidth(this.context.options.video.width);
20833
+ const dimension = {
20834
+ unit: "px",
20835
+ value: this.context.options.video.width
20836
+ };
20837
+ return dimension;
20838
+ }
20839
+ getRecorderHeight(responsive, useBoundingClientRect) {
20840
+ const recorderElement = this.context.getRecorderElement();
20841
+ const userMedia = this.context.getUserMedia();
20842
+ let recorderHeight;
20843
+ if (recorderElement && useBoundingClientRect) {
20844
+ const height = recorderElement.getBoundingClientRect().height;
20845
+ recorderHeight = {
20846
+ unit: "px",
20847
+ value: height
20848
+ };
20849
+ } else if (userMedia) {
20850
+ let height = userMedia.getRawHeight(responsive);
20851
+ if (void 0 !== height && this.context.options.video.width) {
20852
+ const ratio = this.getRatio();
20853
+ if (void 0 !== ratio) {
20854
+ const idealHeight = this.context.options.video.width * ratio;
20855
+ height = Math.min(idealHeight, height);
20856
+ }
20857
+ }
20858
+ recorderHeight = {
20859
+ unit: "px",
20860
+ value: height
20861
+ };
20862
+ } else if (responsive && this.context.options.video.height) recorderHeight = this.calculateHeight(responsive);
20863
+ else if (this.context.options.video.height) {
20864
+ const height = this.context.options.video.height;
20865
+ recorderHeight = {
20866
+ unit: "px",
20867
+ value: height
20868
+ };
20869
+ }
20870
+ return recorderHeight;
20871
+ }
20872
+ getRatio() {
20873
+ const userMedia = this.context.getUserMedia();
20874
+ let ratio;
20875
+ if (userMedia) {
20876
+ const userMediaVideoWidth = userMedia.getVideoWidth();
20877
+ const userMediaVideoHeight = userMedia.getVideoHeight();
20878
+ if (!userMediaVideoWidth || userMediaVideoWidth < 1) ratio = this.context.visuals.getRatio();
20879
+ else if (userMediaVideoHeight) ratio = userMediaVideoHeight / userMediaVideoWidth;
20880
+ } else ratio = dimensions_getRatio(this.context.options);
20881
+ return ratio;
20882
+ }
20883
+ calculateWidth(responsive) {
20884
+ const userMedia = this.context.getUserMedia();
20885
+ const recorderElement = this.context.getRecorderElement();
20886
+ let videoHeight;
20887
+ if (userMedia) videoHeight = userMedia.getVideoHeight();
20888
+ else if (recorderElement) videoHeight = recorderElement.videoHeight || recorderElement.height;
20889
+ return dimensions_calculateWidth(responsive, this.context.options, videoHeight, this.getRatio());
20890
+ }
20891
+ calculateHeight(responsive) {
20892
+ const userMedia = this.context.getUserMedia();
20893
+ const recorderElement = this.context.getRecorderElement();
20894
+ let videoDimension;
20895
+ if (userMedia) {
20896
+ const videoHeight = userMedia.getVideoHeight();
20897
+ videoDimension = {
20898
+ value: videoHeight,
20899
+ unit: "px"
20900
+ };
20901
+ } else if (recorderElement) {
20902
+ const videoHeight = recorderElement.videoHeight || recorderElement.height;
20903
+ videoDimension = {
20904
+ value: videoHeight,
20905
+ unit: "px"
20906
+ };
20907
+ } else videoDimension = dimensions_calculateHeight(responsive, void 0, this.context.options, this.getRatio(), recorderElement);
20908
+ return videoDimension;
20909
+ }
20910
+ constructor(context){
20911
+ dimensions_define_property(this, "context", void 0);
20912
+ this.context = context;
20913
+ }
20914
+ }
20915
+ const recorder_dimensions = RecorderDimensions;
20916
+ function getFirstVideoTrack(localMediaStream) {
20917
+ const videoTracks = localMediaStream.getVideoTracks();
20918
+ let videoTrack;
20919
+ if (videoTracks[0]) videoTrack = videoTracks[0];
20920
+ return videoTrack;
20921
+ }
20922
+ const media_getFirstVideoTrack = getFirstVideoTrack;
20923
+ const MEDIA_EVENTS = [
20924
+ "loadstart",
20925
+ "suspend",
20926
+ "progress",
20927
+ "abort",
20928
+ "emptied",
20929
+ "stalled",
20930
+ "pause",
20931
+ "loadeddata",
20932
+ "waiting",
20933
+ "playing",
20934
+ "canplay",
20935
+ "canplaythrough",
20936
+ "seeking",
20937
+ "seeked",
20938
+ "ended",
20939
+ "ratechange",
20940
+ "durationchange",
20941
+ "volumechange"
20942
+ ];
20943
+ const mediaEvents = MEDIA_EVENTS;
20944
+ function esm_define_property(obj, key, value) {
20945
+ if (key in obj) Object.defineProperty(obj, key, {
20946
+ value: value,
20947
+ enumerable: true,
20948
+ configurable: true,
20949
+ writable: true
20950
+ });
20951
+ else obj[key] = value;
20952
+ return obj;
20953
+ }
20954
+ class AudioSample {
20955
+ toBuffer() {
20956
+ const l = this.float32Array.length;
20957
+ const arr = new Int16Array(l);
20958
+ this.float32Array.forEach((sample, i)=>{
20959
+ const clampedSample = Number.isFinite(sample) ? Math.max(-1, sample) : sample;
20960
+ arr[i] = 0x7fff * Math.min(1, clampedSample);
20961
+ });
20962
+ return typedarray_to_buffer(arr);
20963
+ }
20964
+ constructor(float32Array){
20965
+ esm_define_property(this, "float32Array", void 0);
20966
+ this.float32Array = float32Array;
20967
+ }
20968
+ }
20969
+ const esm_src = AudioSample;
20970
+ const esm = esm_src;
20971
+ var is_power_of_two = __webpack_require__("dZ");
20972
+ var is_power_of_two_default = /*#__PURE__*/ __webpack_require__.n(is_power_of_two);
20973
+ function AudioRecorder_asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
20974
+ try {
20975
+ var info = gen[key](arg);
20976
+ var value = info.value;
20977
+ } catch (error) {
20978
+ reject(error);
20979
+ return;
20980
+ }
20981
+ if (info.done) resolve(value);
20982
+ else Promise.resolve(value).then(_next, _throw);
20983
+ }
20984
+ function AudioRecorder_async_to_generator(fn) {
20985
+ return function() {
20986
+ var self1 = this, args = arguments;
20987
+ return new Promise(function(resolve, reject) {
20988
+ var gen = fn.apply(self1, args);
20989
+ function _next(value) {
20990
+ AudioRecorder_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
20991
+ }
20992
+ function _throw(err) {
20993
+ AudioRecorder_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
20994
+ }
20995
+ _next(void 0);
20996
+ });
20997
+ };
20998
+ }
20999
+ function AudioRecorder_define_property(obj, key, value) {
21000
+ if (key in obj) Object.defineProperty(obj, key, {
21001
+ value: value,
21002
+ enumerable: true,
21003
+ configurable: true,
21004
+ writable: true
21005
+ });
21006
+ else obj[key] = value;
21007
+ return obj;
21008
+ }
21009
+ const CHANNELS = 1;
21010
+ function getAudioContextClass() {
21011
+ return window.AudioContext;
21012
+ }
21013
+ class AudioRecorder {
21014
+ hasAudioContext() {
21015
+ return Boolean(getAudioContextClass()) && Boolean(this.getAudioContext());
21016
+ }
21017
+ getAudioContext() {
21018
+ if (!this.vcAudioContext) {
21019
+ const AudioContext = getAudioContextClass();
21020
+ this.vcAudioContext = new AudioContext();
21021
+ }
21022
+ return this.vcAudioContext;
21023
+ }
21024
+ onAudioProcess(e, cb) {
21025
+ if (!this.userMedia.isRecording() || this.userMedia.isPaused()) return;
21026
+ const float32Array = e.inputBuffer.getChannelData(0);
21027
+ cb(new esm(float32Array));
21028
+ }
21029
+ disconnect() {
21030
+ var _this_audioInput, _this_volume;
21031
+ if (this.scriptProcessor) {
21032
+ this.scriptProcessor.onaudioprocess = null;
21033
+ this.scriptProcessor.disconnect();
21034
+ }
21035
+ null == (_this_audioInput = this.audioInput) || _this_audioInput.disconnect();
21036
+ null == (_this_volume = this.volume) || _this_volume.disconnect();
21037
+ }
21038
+ init(localMediaStream) {
21039
+ this.options.logger.debug("AudioRecorder: init()");
21040
+ this.disconnect();
21041
+ const volume = this.getAudioContext().createGain();
21042
+ this.volume = volume;
21043
+ try {
21044
+ this.audioInput = this.getAudioContext().createMediaStreamSource(localMediaStream);
21045
+ } catch (exc) {
21046
+ throw error_createError({
21047
+ message: "Webcam has no audio",
21048
+ exc,
21049
+ options: this.options
21050
+ });
21051
+ }
21052
+ let { bufferSize } = this.options.audio;
21053
+ if ("auto" === bufferSize) bufferSize = util_getBrowser(this.options).isFirefox() ? 512 : 2048;
21054
+ if (void 0 === bufferSize || !is_power_of_two_default()(bufferSize)) throw error_createError({
21055
+ message: `Audio buffer size must be a power of two. The current buffer size is ${bufferSize}.`,
21056
+ options: this.options
21057
+ });
21058
+ if (!Number.isFinite(this.options.audio.volume) || this.options.audio.volume < 0 || this.options.audio.volume > 1) throw error_createError({
21059
+ message: `Audio volume must be between zero and one. The current volume is ${this.options.audio.volume}.`,
21060
+ options: this.options
21061
+ });
21062
+ volume.gain.value = this.options.audio.volume;
21063
+ this.scriptProcessor = this.getAudioContext().createScriptProcessor(bufferSize, CHANNELS, CHANNELS);
21064
+ this.audioInput.connect(volume);
21065
+ volume.connect(this.scriptProcessor);
21066
+ this.scriptProcessor.connect(this.getAudioContext().destination);
21067
+ }
21068
+ record(cb) {
21069
+ this.options.logger.debug("AudioRecorder: record()");
21070
+ if (this.scriptProcessor) this.scriptProcessor.onaudioprocess = (e)=>{
21071
+ this.onAudioProcess(e, cb);
21072
+ };
21073
+ }
21074
+ resume() {
21075
+ return AudioRecorder_async_to_generator(function*() {
21076
+ const context = this.getAudioContext();
21077
+ if ("running" !== context.state) yield context.resume();
21078
+ }).call(this);
21079
+ }
21080
+ stop() {
21081
+ this.options.logger.debug("AudioRecorder: stop()");
21082
+ this.disconnect();
21083
+ if (this.hasAudioContext()) this.getAudioContext().close().then(()=>{
21084
+ this.options.logger.debug("AudioRecorder: audio context is closed");
21085
+ this.vcAudioContext = void 0;
21086
+ }).catch((err)=>{
21087
+ if (err instanceof Error) return void this.options.logger.error(error_createError({
21088
+ err,
21089
+ options: this.options
21090
+ }));
21091
+ this.options.logger.error(err);
21092
+ });
21093
+ }
21094
+ getSampleRate() {
21095
+ if (this.hasAudioContext()) return this.getAudioContext().sampleRate;
21096
+ return -1;
21097
+ }
21098
+ constructor(userMedia, options){
21099
+ AudioRecorder_define_property(this, "scriptProcessor", void 0);
21100
+ AudioRecorder_define_property(this, "audioInput", void 0);
21101
+ AudioRecorder_define_property(this, "volume", void 0);
21102
+ AudioRecorder_define_property(this, "vcAudioContext", void 0);
21103
+ AudioRecorder_define_property(this, "userMedia", void 0);
21104
+ AudioRecorder_define_property(this, "options", void 0);
21105
+ this.options = options;
21106
+ this.userMedia = userMedia;
21107
+ }
21108
+ }
21109
+ const media_AudioRecorder = AudioRecorder;
21110
+ const VIRTUAL_KEYWORDS = [
21111
+ "obs",
21112
+ "virtual",
21113
+ "manycam",
21114
+ "vcam",
21115
+ "splitcam",
21116
+ "droidcam"
21117
+ ];
21118
+ function isVirtualCamera(videoTrack) {
21119
+ const capabilities = videoTrack.getCapabilities();
21120
+ if (!capabilities.frameRate) return true;
21121
+ const isVirtual = VIRTUAL_KEYWORDS.some((keyword)=>videoTrack.label.toLowerCase().includes(keyword));
21122
+ return isVirtual;
21123
+ }
21124
+ const util_isVirtualCamera = isVirtualCamera;
21125
+ function userMedia_asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
21126
+ try {
21127
+ var info = gen[key](arg);
21128
+ var value = info.value;
21129
+ } catch (error) {
21130
+ reject(error);
21131
+ return;
21132
+ }
21133
+ if (info.done) resolve(value);
21134
+ else Promise.resolve(value).then(_next, _throw);
21135
+ }
21136
+ function userMedia_async_to_generator(fn) {
21137
+ return function() {
21138
+ var self1 = this, args = arguments;
21139
+ return new Promise(function(resolve, reject) {
21140
+ var gen = fn.apply(self1, args);
21141
+ function _next(value) {
21142
+ userMedia_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
21143
+ }
21144
+ function _throw(err) {
21145
+ userMedia_asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
21146
+ }
21147
+ _next(void 0);
21148
+ });
21149
+ };
21150
+ }
21151
+ function userMedia_define_property(obj, key, value) {
21152
+ if (key in obj) Object.defineProperty(obj, key, {
21153
+ value: value,
21154
+ enumerable: true,
21155
+ configurable: true,
21156
+ writable: true
21157
+ });
21158
+ else obj[key] = value;
21159
+ return obj;
21160
+ }
21161
+ const EVENT_ASCII = "|—O—|";
21162
+ class UserMedia extends util_Despot {
21163
+ attachMediaStream(stream) {
21164
+ if (this.rawVisualUserMedia) {
21165
+ this.rawVisualUserMedia.srcObject = stream;
21166
+ const previousStream = this.currentVisualStream;
21167
+ this.currentVisualStream = stream;
21168
+ if (previousStream && previousStream !== stream) previousStream.getTracks().forEach((track)=>{
21169
+ track.stop();
21170
+ });
21171
+ } else throw error_createError({
21172
+ message: "Error attaching stream to element.",
21173
+ explanation: "Contact the developer about this",
21174
+ options: this.options
21175
+ });
21176
+ }
21177
+ setVisualStream(localMediaStream) {
21178
+ if (localMediaStream) this.attachMediaStream(localMediaStream);
21179
+ else {
21180
+ if (this.rawVisualUserMedia) {
21181
+ this.rawVisualUserMedia.srcObject = null;
21182
+ this.rawVisualUserMedia.removeAttribute("src");
21183
+ }
21184
+ this.currentVisualStream = void 0;
21185
+ }
21186
+ }
21187
+ restorePlayback() {
21188
+ return userMedia_async_to_generator(function*() {
21189
+ var _this_audioRecorder;
21190
+ if (!this.rawVisualUserMedia) throw new Error("No camera preview is available.");
21191
+ yield this.rawVisualUserMedia.play();
21192
+ yield null == (_this_audioRecorder = this.audioRecorder) ? void 0 : _this_audioRecorder.resume();
21193
+ }).call(this);
21194
+ }
21195
+ hasLiveStream() {
21196
+ var _this_currentVisualStream, _this_currentVisualStream1, _this_currentVisualStream2;
21197
+ const videoReady = null == (_this_currentVisualStream = this.currentVisualStream) ? void 0 : _this_currentVisualStream.getVideoTracks().some((track)=>"live" === track.readyState && track.enabled && !track.muted);
21198
+ const audioReady = !isAudioEnabled(this.options) || (null == (_this_currentVisualStream1 = this.currentVisualStream) ? void 0 : _this_currentVisualStream1.getAudioTracks().some((track)=>"live" === track.readyState && track.enabled && !track.muted));
21199
+ return Boolean((null == (_this_currentVisualStream2 = this.currentVisualStream) ? void 0 : _this_currentVisualStream2.active) && videoReady && audioReady);
21200
+ }
21201
+ hasEnded() {
21202
+ var _this_rawVisualUserMedia, _this_currentVisualStream;
21203
+ if (null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.ended) return this.rawVisualUserMedia.ended;
21204
+ return !(null == (_this_currentVisualStream = this.currentVisualStream) ? void 0 : _this_currentVisualStream.active);
21205
+ }
21206
+ hasInvalidDimensions() {
21207
+ if (!this.rawVisualUserMedia) return false;
21208
+ const { videoWidth, videoHeight } = this.rawVisualUserMedia;
21209
+ return videoWidth > 0 && videoWidth < 3 || videoHeight > 0 && videoHeight < 3;
21210
+ }
21211
+ logEvent(eventType, params) {
21212
+ this.options.logger.debug(`UserMedia: ... ${EVENT_ASCII} event ${eventType}: ${string_pretty(params)}`);
21213
+ }
21214
+ unloadRemainingEventListeners() {
21215
+ var _this_clearInitializationListeners, _this, _this_rawVisualUserMedia;
21216
+ this.options.logger.debug("UserMedia: unloadRemainingEventListeners()");
21217
+ null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
21218
+ mediaEvents.forEach((eventName)=>{
21219
+ var _this_rawVisualUserMedia;
21220
+ null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.removeEventListener(eventName, this.outputEvent);
21221
+ });
21222
+ null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.removeEventListener("error", this.handleMediaError);
21223
+ }
21224
+ audioRecord(audioCallback) {
21225
+ var _this_audioRecorder;
21226
+ this.removeListener("SENDING_FIRST_FRAME");
21227
+ null == (_this_audioRecorder = this.audioRecorder) || _this_audioRecorder.record(audioCallback);
21228
+ }
21229
+ init(localMediaStream, videoCallback, audioCallback, endedEarlyCallback, params) {
21230
+ var _this_clearInitializationListeners, _this;
21231
+ null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
21232
+ this.stop(localMediaStream, {
21233
+ aboutToInitialize: true,
21234
+ preserveRecordingState: Boolean((null == params ? void 0 : params.switchingFacingMode) || (null == params ? void 0 : params.recovering))
21235
+ });
21236
+ const initializationId = ++this.initializationId;
21237
+ this.onPlayReached = false;
21238
+ this.onLoadedMetaDataReached = false;
21239
+ this.playingPromiseReached = false;
21240
+ this.videoTrackLabel = void 0;
21241
+ if (isAudioEnabled(this.options)) null != this.audioRecorder || (this.audioRecorder = new media_AudioRecorder(this, this.options));
21242
+ const unloadAllEventListeners = ()=>{
21243
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
21244
+ this.options.logger.debug("UserMedia: unloadAllEventListeners()");
21245
+ this.unloadRemainingEventListeners();
21246
+ this.removeListener("SENDING_FIRST_FRAME");
21247
+ null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.removeEventListener("play", onPlay);
21248
+ null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.removeEventListener("loadedmetadata", onLoadedMetaData);
21249
+ };
21250
+ this.clearInitializationListeners = ()=>{
21251
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
21252
+ null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.removeEventListener("play", onPlay);
21253
+ null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.removeEventListener("loadedmetadata", onLoadedMetaData);
21254
+ this.clearInitializationListeners = void 0;
21255
+ };
21256
+ const play = ()=>{
21257
+ try {
21258
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
21259
+ null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.load();
21260
+ if (null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.paused) {
21261
+ 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)}`);
21262
+ this.rawVisualUserMedia.play().then(()=>{
21263
+ if (initializationId !== this.initializationId) return;
21264
+ if (!this.playingPromiseReached) {
21265
+ this.options.logger.debug("UserMedia: play promise successful. Playing now.");
21266
+ this.playingPromiseReached = true;
21267
+ }
21268
+ }).catch((exc)=>{
21269
+ if (initializationId !== this.initializationId) return;
21270
+ if (exc instanceof Error && !(null == params ? void 0 : params.recovering)) this.options.logger.warn(`Caught pending user media promise exception: ${exc.toString()}`);
21271
+ else {
21272
+ unloadAllEventListeners();
21273
+ endedEarlyCallback(error_createError({
21274
+ message: "Failed to play user media upon play event.",
21275
+ exc,
21276
+ options: this.options
21277
+ }));
21278
+ }
21279
+ });
21280
+ }
21281
+ } catch (exc) {
21282
+ unloadAllEventListeners();
21283
+ endedEarlyCallback(exc);
21284
+ }
21285
+ };
21286
+ const fireCallbacks = ()=>{
21287
+ var _this_rawVisualUserMedia;
21288
+ const readyState = null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.readyState;
21289
+ this.options.logger.debug(`UserMedia: fireCallbacks(readyState=${readyState}, onPlayReached=${this.onPlayReached}, onLoadedMetaDataReached=${this.onLoadedMetaDataReached})`);
21290
+ if (this.onPlayReached && this.onLoadedMetaDataReached) if (this.audioRecorder) try {
21291
+ this.audioRecorder.init(localMediaStream);
21292
+ const onAudioReady = ()=>{
21293
+ var _this_clearInitializationListeners, _this;
21294
+ if (initializationId !== this.initializationId || this.currentVisualStream !== localMediaStream) return;
21295
+ if (this.recording) this.audioRecord(audioCallback);
21296
+ else this.on("SENDING_FIRST_FRAME", ()=>{
21297
+ this.audioRecord(audioCallback);
21298
+ });
21299
+ null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
21300
+ videoCallback();
21301
+ };
21302
+ if (null == params ? void 0 : params.recovering) this.audioRecorder.resume().then(onAudioReady).catch(endedEarlyCallback);
21303
+ else onAudioReady();
21304
+ } catch (exc) {
21305
+ unloadAllEventListeners();
21306
+ this.stop(void 0, {
21307
+ preserveRecordingState: Boolean(null == params ? void 0 : params.recovering)
21308
+ });
21309
+ endedEarlyCallback(exc);
21310
+ }
21311
+ else {
21312
+ var _this_clearInitializationListeners, _this;
21313
+ null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
21314
+ videoCallback();
21315
+ }
21316
+ };
21317
+ const onPlay = ()=>{
21318
+ try {
21319
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1, _this_rawVisualUserMedia2, _this_rawVisualUserMedia3, _this_rawVisualUserMedia4, _this_rawVisualUserMedia5;
21320
+ this.logEvent("play", {
21321
+ readyState: null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.readyState,
21322
+ audio: isAudioEnabled(this.options),
21323
+ width: null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.width,
21324
+ height: null == (_this_rawVisualUserMedia2 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia2.height,
21325
+ videoWidth: null == (_this_rawVisualUserMedia3 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia3.videoWidth,
21326
+ videoHeight: null == (_this_rawVisualUserMedia4 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia4.videoHeight
21327
+ });
21328
+ null == (_this_rawVisualUserMedia5 = this.rawVisualUserMedia) || _this_rawVisualUserMedia5.removeEventListener("play", onPlay);
21329
+ if (this.hasEnded() || this.hasInvalidDimensions()) endedEarlyCallback(error_createError({
21330
+ message: "Already busy",
21331
+ explanation: "Probably another browser window is using your webcam?",
21332
+ options: this.options
21333
+ }));
21334
+ else {
21335
+ this.onPlayReached = true;
21336
+ fireCallbacks();
21337
+ }
21338
+ } catch (exc) {
21339
+ unloadAllEventListeners();
21340
+ endedEarlyCallback(exc);
21341
+ }
21342
+ };
21343
+ const onLoadedMetaData = ()=>{
21344
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1, _this_rawVisualUserMedia2, _this_rawVisualUserMedia3, _this_rawVisualUserMedia4, _this_rawVisualUserMedia5, _this_rawVisualUserMedia6;
21345
+ this.logEvent("loadedmetadata", {
21346
+ readyState: null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.readyState,
21347
+ paused: null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.paused,
21348
+ width: null == (_this_rawVisualUserMedia2 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia2.width,
21349
+ height: null == (_this_rawVisualUserMedia3 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia3.height,
21350
+ videoWidth: null == (_this_rawVisualUserMedia4 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia4.videoWidth,
21351
+ videoHeight: null == (_this_rawVisualUserMedia5 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia5.videoHeight
21352
+ });
21353
+ null == (_this_rawVisualUserMedia6 = this.rawVisualUserMedia) || _this_rawVisualUserMedia6.removeEventListener("loadedmetadata", onLoadedMetaData);
21354
+ if (!this.hasEnded() && !this.hasInvalidDimensions()) {
21355
+ this.emit("LOADED_META_DATA");
21356
+ this.onLoadedMetaDataReached = true;
21357
+ fireCallbacks();
21358
+ }
21359
+ };
21360
+ try {
21361
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1, _this_rawVisualUserMedia2, _this_rawVisualUserMedia3;
21362
+ const videoTrack = media_getFirstVideoTrack(localMediaStream);
21363
+ this.videoTrackLabel = null == videoTrack ? void 0 : videoTrack.label;
21364
+ if (videoTrack) if (videoTrack.enabled) if (util_isVirtualCamera(videoTrack)) throw error_createError({
21365
+ message: "Virtual cameras are not allowed.",
21366
+ explanation: `Please use a real camera, not "${videoTrack.label}".`,
21367
+ options: this.options
20864
21368
  });
20865
21369
  else {
20866
- this.options.logger.debug("Recorder: no error listeners attached but throwing exception further");
20867
- throw exc;
21370
+ let description = "";
21371
+ if (videoTrack.label.length > 0) description = description.concat(videoTrack.label);
21372
+ description = description.concat(` with enabled=${videoTrack.enabled}, muted=${videoTrack.muted}, readyState=${videoTrack.readyState}`);
21373
+ this.options.logger.debug(`UserMedia: ${videoTrack.kind} detected. ${description}`);
20868
21374
  }
21375
+ else throw error_createError({
21376
+ message: "Webcam is disabled",
21377
+ explanation: "The video track seems to be disabled. Enable it in your system.",
21378
+ options: this.options
21379
+ });
21380
+ else this.options.logger.debug("UserMedia: detected (but no video tracks exist");
21381
+ null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.addEventListener("loadedmetadata", onLoadedMetaData);
21382
+ null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.addEventListener("play", onPlay);
21383
+ null == (_this_rawVisualUserMedia2 = this.rawVisualUserMedia) || _this_rawVisualUserMedia2.removeEventListener("error", this.handleMediaError);
21384
+ null == (_this_rawVisualUserMedia3 = this.rawVisualUserMedia) || _this_rawVisualUserMedia3.addEventListener("error", this.handleMediaError);
21385
+ this.setVisualStream(localMediaStream);
21386
+ play();
21387
+ } catch (exc) {
21388
+ unloadAllEventListeners();
21389
+ endedEarlyCallback(exc);
20869
21390
  }
20870
21391
  }
20871
- executeCommand(command) {
20872
- if (this.unloaded) return;
21392
+ getVideoTrackLabel() {
21393
+ return this.videoTrackLabel;
21394
+ }
21395
+ isReady() {
21396
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
21397
+ return Boolean((null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.srcObject) || (null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.currentSrc));
21398
+ }
21399
+ stop(visualStream, params) {
20873
21400
  try {
20874
- if (command.args) {
20875
- const debugLine = string_summarize(`Server commanded: ${command.command} with:`, command.args);
20876
- this.options.logger.debug(debugLine);
20877
- } else this.options.logger.debug(`Server commanded: ${command.command}`);
20878
- switch(command.command){
20879
- case "ready":
20880
- this.emit("SERVER_READY");
20881
- if (!this.userMediaTimeout) if (this.options.loadUserMediaOnRecord) this.show();
20882
- else this.loadUserMedia();
20883
- break;
20884
- case "preview":
20885
- this.preview(command.args);
20886
- break;
20887
- case "error":
20888
- {
20889
- var _command_args_err, _command_args, _command_args1;
20890
- let explanation = "(No explanation given)";
20891
- if (null == (_command_args = command.args) ? void 0 : null == (_command_args_err = _command_args.err) ? void 0 : _command_args_err.message) explanation = command.args.err.message;
20892
- const err = error_createError({
20893
- message: "Websocket error from Videomail server",
20894
- explanation,
20895
- err: deserializeError(null == (_command_args1 = command.args) ? void 0 : _command_args1.err),
20896
- options: this.options
20897
- });
20898
- this.emit("ERROR", {
20899
- err
20900
- });
20901
- break;
20902
- }
20903
- case "confirmFrame":
20904
- this.updateFrameProgress(command.args);
20905
- break;
20906
- case "confirmSample":
20907
- this.updateSampleProgress(command.args);
20908
- break;
20909
- case "beginAudioEncoding":
20910
- this.emit("BEGIN_AUDIO_ENCODING");
20911
- break;
20912
- case "beginVideoEncoding":
20913
- this.emit("BEGIN_VIDEO_ENCODING");
20914
- break;
20915
- default:
20916
- {
20917
- const err = error_createError({
20918
- message: `Unknown server command: ${command.command}`,
20919
- options: this.options
20920
- });
20921
- this.emit("ERROR", {
20922
- err
20923
- });
20924
- break;
20925
- }
21401
+ let chosenStream = visualStream;
21402
+ if (!(null == params ? void 0 : params.aboutToInitialize)) {
21403
+ var _this_clearInitializationListeners, _this, _this_audioRecorder;
21404
+ this.initializationId++;
21405
+ null == (_this_clearInitializationListeners = (_this = this).clearInitializationListeners) || _this_clearInitializationListeners.call(_this);
21406
+ null != chosenStream || (chosenStream = this.currentVisualStream);
21407
+ const tracks = null == chosenStream ? void 0 : chosenStream.getTracks();
21408
+ if (tracks) tracks.forEach((track)=>{
21409
+ track.stop();
21410
+ });
21411
+ this.setVisualStream();
21412
+ null == (_this_audioRecorder = this.audioRecorder) || _this_audioRecorder.stop();
21413
+ this.audioRecorder = void 0;
20926
21414
  }
21415
+ if (!(null == params ? void 0 : params.preserveRecordingState)) this.paused = this.recording = false;
20927
21416
  } catch (exc) {
20928
21417
  this.emit("ERROR", {
20929
21418
  exc
20930
21419
  });
20931
21420
  }
20932
21421
  }
20933
- isNotifying() {
20934
- return this.visuals.isNotifying();
20935
- }
20936
- isHidden() {
20937
- return !this.recorderElement || html_isHidden(this.recorderElement);
20938
- }
20939
- writeCommand(command, args, cb) {
20940
- if (this.connected) {
20941
- if (this.stream) {
20942
- if (args) this.options.logger.debug(`$ ${command} with ${string_pretty(args)}`);
20943
- else this.options.logger.debug(`$ ${command}`);
20944
- const commandObj = {
20945
- command,
20946
- args
20947
- };
20948
- this.writeStream(Buffer.from(JSON.stringify(commandObj)), cb ? {
20949
- onFlushedCallback: ()=>{
20950
- queueMicrotask(cb);
20951
- }
20952
- } : void 0);
20953
- }
20954
- } else {
20955
- this.options.logger.debug(`Reconnecting for the command ${command} …`);
20956
- this.initSocket(()=>{
20957
- this.writeCommand(command, args, cb);
20958
- });
20959
- }
20960
- }
20961
- cancelAnimationFrame() {
20962
- var _this_loop;
20963
- null == (_this_loop = this.loop) || _this_loop.dispose();
20964
- }
20965
- getIntervalSum() {
20966
- if (!this.loop) return;
20967
- return this.loop.getElapsedTime();
20968
- }
20969
- getAvgInterval() {
20970
- var _this_getIntervalSum;
20971
- const intervalSum = null != (_this_getIntervalSum = this.getIntervalSum()) ? _this_getIntervalSum : 0;
20972
- if (!this.hasValidInterval(intervalSum)) return;
20973
- return intervalSum / this.framesCount;
20974
- }
20975
- getAvgFps() {
20976
- var _this_getIntervalSum;
20977
- const intervalSum = null != (_this_getIntervalSum = this.getIntervalSum()) ? _this_getIntervalSum : 0;
20978
- if (!this.hasValidInterval(intervalSum)) return;
20979
- return this.framesCount / intervalSum * 1000;
20980
- }
20981
- hasValidInterval(intervalSum) {
20982
- return intervalSum > 0;
20983
- }
20984
- getRecordingStats() {
20985
- return this.recordingStats;
20986
- }
20987
- getAudioSampleRate() {
20988
- var _this_recordingAudioSampleRate;
20989
- var _this_userMedia;
20990
- return null != (_this_recordingAudioSampleRate = this.recordingAudioSampleRate) ? _this_recordingAudioSampleRate : null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.getAudioSampleRate();
20991
- }
20992
- stop(params) {
20993
- var _this_loop;
20994
- this.cancelCameraRecovery();
20995
- if (!this.userMedia) throw new Error("No user media defined, unable to stop");
20996
- this.options.logger.debug(`Recorder: stop(${params ? string_pretty(params) : ""})`);
20997
- this.recordingActive = false;
20998
- const limitReached = null == params ? void 0 : params.limitReached;
20999
- this.emit("STOPPING", {
21000
- limitReached
21001
- });
21002
- null == (_this_loop = this.loop) || _this_loop.complete();
21003
- this.stopTimeout = window.setTimeout(()=>{
21004
- this.stopTimeout = void 0;
21005
- this.stopTime = Date.now();
21006
- const videoType = this.replay.getVideoType();
21007
- if (!videoType) throw new Error("Unable to video record when no video type is defined.");
21008
- this.recordingStats = {
21009
- avgFps: this.getAvgFps(),
21010
- wantedFps: this.options.video.fps,
21011
- avgInterval: this.getAvgInterval(),
21012
- wantedInterval: 1e3 / this.options.video.fps,
21013
- intervalSum: this.getIntervalSum(),
21014
- framesCount: this.framesCount,
21015
- videoType
21016
- };
21017
- if (this.userMedia) this.recordingStats.videoTrackLabel = this.userMedia.getVideoTrackLabel();
21018
- if (isAudioEnabled(this.options) && this.userMedia) {
21019
- var _this_recordingAudioSampleRate;
21020
- this.recordingStats.samplesCount = this.samplesCount;
21021
- this.recordingStats.sampleRate = null != (_this_recordingAudioSampleRate = this.recordingAudioSampleRate) ? _this_recordingAudioSampleRate : this.userMedia.getAudioSampleRate();
21022
- }
21023
- this.writeCommand("stop", this.recordingStats, ()=>{
21024
- this.emit("STOPPED", {
21025
- recordingStats: this.recordingStats
21026
- });
21027
- });
21028
- this.reset();
21029
- }, 60);
21422
+ createCanvas() {
21423
+ const canvas = document.createElement("canvas");
21424
+ const rawWidthDimension = this.getRawWidth(true);
21425
+ if (rawWidthDimension.value) canvas.width = rawWidthDimension.value;
21426
+ const rawHeight = this.getRawHeight(true);
21427
+ if (rawHeight) canvas.height = rawHeight;
21428
+ return canvas;
21030
21429
  }
21031
- back(cb) {
21032
- this.emit("GOING_BACK");
21033
- this.key = void 0;
21034
- this.recordingDimensions = void 0;
21035
- this.unloaded = false;
21036
- this.show();
21037
- this.writeCommand("back", void 0, cb);
21430
+ getVideoHeight() {
21431
+ if (!this.rawVisualUserMedia) return;
21432
+ return this.rawVisualUserMedia.videoHeight || this.rawVisualUserMedia.height;
21038
21433
  }
21039
- reInitializeAudio() {
21040
- var _this_userMedia;
21041
- this.options.logger.debug("Recorder: reInitializeAudio()");
21042
- this.clearUserMediaTimeout();
21043
- this.userMediaLoading = false;
21044
- null == (_this_userMedia = this.userMedia) || _this_userMedia.stop();
21045
- this.recordingDimensions = void 0;
21046
- this.userMediaLoaded = this.key = this.canvas = this.ctx = void 0;
21047
- this.loadUserMedia();
21434
+ getVideoWidth() {
21435
+ if (!this.rawVisualUserMedia) return;
21436
+ return this.rawVisualUserMedia.videoWidth || this.rawVisualUserMedia.width;
21048
21437
  }
21049
- unload(params) {
21050
- if (this.unloaded || !this.built) return;
21051
- const e = null == params ? void 0 : params.e;
21052
- let cause;
21053
- if (e) cause = e.type;
21054
- const prettyCause = cause ? `, cause: ${cause}` : "";
21055
- this.options.logger.debug(`Recorder: unload()${prettyCause}`);
21056
- this.recordingActive = false;
21057
- this.mediaTransmissionStarted = false;
21058
- this.reset();
21059
- this.recordingDimensions = void 0;
21060
- this.clearUserMediaTimeout();
21061
- this.clearConnectionTimeout();
21062
- this.clearReconnectTimeout();
21063
- this.clearRetryTimeout();
21064
- this.clearStopTimeout();
21065
- this.stopPings();
21066
- this.userMediaLoading = false;
21067
- this.connecting = false;
21068
- this.reconnecting = false;
21069
- this.reconnectAttempts = 0;
21070
- if (this.userMedia) this.userMedia.unloadRemainingEventListeners();
21071
- if (this.submitting) ;
21072
- else if (this.stream) this.discardSocket();
21073
- this.unloaded = true;
21074
- this.built = this.connecting = this.connected = false;
21438
+ hasVideoWidth() {
21439
+ const videoWidth = this.getVideoWidth();
21440
+ return videoWidth && videoWidth > 0;
21075
21441
  }
21076
- reset() {
21077
- this.cancelCameraRecovery();
21078
- if (!this.unloaded) {
21079
- var _this_userMedia;
21080
- this.options.logger.debug("Recorder: reset()");
21081
- this.emit("RESETTING");
21082
- this.cancelAnimationFrame();
21083
- null == (_this_userMedia = this.userMedia) || _this_userMedia.stop();
21084
- this.replay.reset();
21085
- this.userMediaLoaded = this.key = this.canvas = this.ctx = this.recordingBuffer = void 0;
21442
+ getRawWidth(responsive) {
21443
+ let rawWidth;
21444
+ const widthDimension = {
21445
+ unit: "px"
21446
+ };
21447
+ rawWidth = responsive ? this.getVideoWidth() : this.options.video.width ? this.options.video.width : this.getVideoWidth();
21448
+ if (responsive) {
21449
+ const widthDimension = this.recorder.limitWidth(rawWidth);
21450
+ rawWidth = null == widthDimension ? void 0 : widthDimension.value;
21086
21451
  }
21452
+ widthDimension.value = rawWidth;
21453
+ return widthDimension;
21087
21454
  }
21088
- clearUserMediaTimeout() {
21089
- if (void 0 !== this.userMediaTimeout) {
21090
- this.options.logger.debug("Recorder: clearUserMediaTimeout()");
21091
- window.clearTimeout(this.userMediaTimeout);
21092
- this.userMediaTimeout = void 0;
21455
+ getRawHeight(responsive) {
21456
+ let rawHeight;
21457
+ if (responsive) {
21458
+ rawHeight = this.options.video.height || this.getVideoHeight();
21459
+ const ratio = this.recorder.getRatio();
21460
+ const rawWidth = this.getRawWidth(responsive);
21461
+ if (void 0 !== ratio && rawWidth.value) rawHeight = rawWidth.value * ratio;
21462
+ } else rawHeight = this.options.video.height ? this.options.video.height : this.getVideoHeight();
21463
+ if (responsive) {
21464
+ const heightDimension = this.recorder.limitHeight(rawHeight);
21465
+ rawHeight = heightDimension.value;
21093
21466
  }
21467
+ return rawHeight;
21094
21468
  }
21095
- clearStopTimeout() {
21096
- if (void 0 === this.stopTimeout) return;
21097
- window.clearTimeout(this.stopTimeout);
21098
- this.stopTimeout = void 0;
21099
- }
21100
- validate() {
21101
- return Boolean(this.key) && void 0 === this.canvas;
21469
+ getRawVisuals() {
21470
+ return this.rawVisualUserMedia;
21102
21471
  }
21103
- isReady() {
21104
- var _this_userMedia;
21105
- return null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isReady();
21472
+ pause() {
21473
+ this.paused = true;
21106
21474
  }
21107
- finishCameraRecovery(restored) {
21108
- this.clearUserMediaTimeout();
21109
- const resolve = this.resolveCameraRecovery;
21110
- const resumeRequested = restored && this.resumeAfterCameraRecovery;
21111
- this.cameraRecovery = void 0;
21112
- this.resolveCameraRecovery = void 0;
21113
- this.resumeAfterCameraRecovery = false;
21114
- null == resolve || resolve(restored);
21115
- if (resumeRequested && this.isPaused()) this.resume();
21475
+ isPaused() {
21476
+ return this.paused;
21116
21477
  }
21117
- cancelCameraRecovery() {
21118
- var _this_userMedia;
21119
- if (!this.cameraRecovery) return;
21120
- this.mediaRequestId++;
21121
- this.userMediaLoading = false;
21122
- this.userMediaLoaded = false;
21123
- this.clearUserMediaTimeout();
21124
- null == (_this_userMedia = this.userMedia) || _this_userMedia.stop(void 0, {
21125
- preserveRecordingState: true
21126
- });
21127
- this.finishCameraRecovery(false);
21478
+ resume() {
21479
+ this.paused = false;
21128
21480
  }
21129
- failCameraRecovery(exc) {
21130
- this.cancelCameraRecovery();
21131
- const err = error_createError({
21132
- message: "Camera recovery failed",
21133
- explanation: "Your recording is still paused. Check camera permissions, then try Resume again or stop to keep the recorded part.",
21134
- exc,
21135
- options: this.options
21136
- });
21137
- this.emit("CAMERA_RECOVERY_FAILED", {
21138
- err
21139
- });
21481
+ record() {
21482
+ this.recording = true;
21140
21483
  }
21141
- recoverCamera() {
21142
- if (this.cameraRecovery) return this.cameraRecovery;
21143
- if (!this.built || this.unloaded || !this.userMedia || this.userMediaLoading || this.submitting || this.key || void 0 !== this.stopTimeout || this.recordingTransportFailed) return Promise.resolve(false);
21144
- const liveStream = this.userMedia.hasLiveStream();
21145
- if (liveStream && this.isRecording()) return Promise.resolve(true);
21146
- if (!liveStream && this.recordingActive && !this.isPaused()) this.pause();
21147
- const recovery = new Promise((resolve)=>{
21148
- this.resolveCameraRecovery = resolve;
21149
- });
21150
- this.cameraRecovery = recovery;
21151
- this.emit("CAMERA_RECOVERING");
21152
- if (liveStream) {
21153
- this.userMediaTimeout = window.setTimeout(()=>{
21154
- this.failCameraRecovery(new Error("Camera playback recovery timed out."));
21155
- }, this.options.timeouts.userMedia);
21156
- this.userMedia.restorePlayback().then(()=>{
21157
- if (this.cameraRecovery === recovery) this.finishCameraRecovery(true);
21158
- }).catch((exc)=>{
21159
- if (this.cameraRecovery === recovery) this.failCameraRecovery(exc);
21160
- });
21161
- } else {
21162
- this.userMediaLoaded = false;
21163
- this.loadUserMedia({
21164
- recovering: true
21165
- });
21166
- }
21167
- return recovery;
21484
+ isRecording() {
21485
+ return this.recording;
21168
21486
  }
21169
- pause(params) {
21170
- var _this_userMedia;
21171
- this.cancelCameraRecovery();
21172
- this.resumeAfterDrain = false;
21173
- if (params) this.options.logger.debug(`pause() at frame ${this.framesCount} with ${string_pretty(params)}`);
21174
- else this.options.logger.debug(`pause() at frame ${this.framesCount}`);
21175
- null == (_this_userMedia = this.userMedia) || _this_userMedia.pause();
21176
- this.loop.stop();
21177
- this.emit("PAUSED");
21178
- this.sendPings();
21487
+ getAudioSampleRate() {
21488
+ if (this.audioRecorder) return this.audioRecorder.getSampleRate();
21489
+ return -1;
21179
21490
  }
21180
- resume() {
21181
- var _this_userMedia;
21182
- if (this.cameraRecovery || !(null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.hasLiveStream())) {
21183
- this.recoverCamera();
21184
- this.resumeAfterCameraRecovery = Boolean(this.cameraRecovery);
21185
- return;
21186
- }
21187
- this.options.logger.debug(`Recorder: resume() with frame ${this.framesCount}`);
21188
- this.stopPings();
21189
- this.emit("RESUMING");
21190
- this.userMedia.resume();
21191
- if (this.streamBackpressured) this.resumeAfterDrain = true;
21192
- else this.loop.start();
21491
+ getCharacteristics() {
21492
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1, _this_rawVisualUserMedia2, _this_rawVisualUserMedia3, _this_rawVisualUserMedia4;
21493
+ return {
21494
+ audioSampleRate: this.getAudioSampleRate(),
21495
+ muted: null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.muted,
21496
+ width: null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia1.width,
21497
+ height: null == (_this_rawVisualUserMedia2 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia2.height,
21498
+ videoWidth: null == (_this_rawVisualUserMedia3 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia3.videoWidth,
21499
+ videoHeight: null == (_this_rawVisualUserMedia4 = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia4.videoHeight
21500
+ };
21193
21501
  }
21194
- onFlushed(opts) {
21195
- const frameNumber = opts.frameNumber;
21196
- if (1 === frameNumber) this.emit("FIRST_FRAME_SENT");
21502
+ constructor(recorder, options){
21503
+ super("UserMedia", options), userMedia_define_property(this, "recorder", void 0), userMedia_define_property(this, "rawVisualUserMedia", void 0), userMedia_define_property(this, "paused", false), userMedia_define_property(this, "recording", false), userMedia_define_property(this, "audioRecorder", void 0), userMedia_define_property(this, "currentVisualStream", void 0), userMedia_define_property(this, "onPlayReached", false), userMedia_define_property(this, "onLoadedMetaDataReached", false), userMedia_define_property(this, "playingPromiseReached", false), userMedia_define_property(this, "videoTrackLabel", void 0), userMedia_define_property(this, "clearInitializationListeners", void 0), userMedia_define_property(this, "initializationId", 0), userMedia_define_property(this, "outputEvent", (e)=>{
21504
+ var _this_rawVisualUserMedia, _this_rawVisualUserMedia1;
21505
+ this.logEvent(e.type, {
21506
+ readyState: null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) ? void 0 : _this_rawVisualUserMedia.readyState
21507
+ });
21508
+ null == (_this_rawVisualUserMedia1 = this.rawVisualUserMedia) || _this_rawVisualUserMedia1.removeEventListener(e.type, this.outputEvent);
21509
+ }), userMedia_define_property(this, "handleMediaError", (event)=>{
21510
+ this.options.logger.warn(`Caught video element error event: ${string_pretty(event)}`);
21511
+ });
21512
+ this.recorder = recorder;
21513
+ this.rawVisualUserMedia = recorder.getRawVisualUserMedia();
21514
+ mediaEvents.forEach((eventName)=>{
21515
+ var _this_rawVisualUserMedia;
21516
+ null == (_this_rawVisualUserMedia = this.rawVisualUserMedia) || _this_rawVisualUserMedia.addEventListener(eventName, this.outputEvent, false);
21517
+ });
21197
21518
  }
21198
- draw(_deltaTime, elapsedTime) {
21199
- if (this.recordingTransportFailed) return;
21200
- if (!this.userMedia) throw new Error("No user media defined, unable to draw on canvas");
21519
+ }
21520
+ const visuals_userMedia = UserMedia;
21521
+ function recorder_define_property(obj, key, value) {
21522
+ if (key in obj) Object.defineProperty(obj, key, {
21523
+ value: value,
21524
+ enumerable: true,
21525
+ configurable: true,
21526
+ writable: true
21527
+ });
21528
+ else obj[key] = value;
21529
+ return obj;
21530
+ }
21531
+ class Recorder extends capture {
21532
+ executeCommand(command) {
21533
+ if (this.unloaded) return;
21201
21534
  try {
21202
- if (!this.isPaused() && this.stream && this.ctx) {
21203
- var _this_frame, _this_recordingBuffer;
21204
- if (0 === this.framesCount) this.emit("SENDING_FIRST_FRAME");
21205
- this.framesCount++;
21206
- const imageSource = this.userMedia.getRawVisuals();
21207
- if (this.canvas && imageSource) this.ctx.drawImage(imageSource, 0, 0, this.canvas.width, this.canvas.height);
21208
- else throw new Error("Unable to draw an image without a defined canvas");
21209
- this.recordingBuffer = null == (_this_frame = this.frame) ? void 0 : _this_frame.toBuffer();
21210
- const recordingBufferLength = null == (_this_recordingBuffer = this.recordingBuffer) ? void 0 : _this_recordingBuffer.length;
21211
- if (recordingBufferLength) {
21212
- if (this.recordingBuffer) {
21213
- const frameControlBuffer = Buffer.from(JSON.stringify({
21214
- frameNumber: this.framesCount
21215
- }));
21216
- const frameBuffer = Buffer.concat([
21217
- this.recordingBuffer,
21218
- frameControlBuffer
21219
- ]);
21220
- this.mediaTransmissionStarted = true;
21221
- this.writeStream(frameBuffer, {
21222
- frameNumber: this.framesCount,
21223
- onFlushedCallback: this.onFlushed.bind(this)
21535
+ if (command.args) {
21536
+ const debugLine = string_summarize(`Server commanded: ${command.command} with:`, command.args);
21537
+ this.options.logger.debug(debugLine);
21538
+ } else this.options.logger.debug(`Server commanded: ${command.command}`);
21539
+ switch(command.command){
21540
+ case "ready":
21541
+ this.emit("SERVER_READY");
21542
+ if (!this.userMediaTimeout) if (this.options.loadUserMediaOnRecord) this.show();
21543
+ else this.loadUserMedia();
21544
+ break;
21545
+ case "preview":
21546
+ this.preview(command.args);
21547
+ break;
21548
+ case "error":
21549
+ {
21550
+ var _command_args_err, _command_args, _command_args1;
21551
+ let explanation = "(No explanation given)";
21552
+ if (null == (_command_args = command.args) ? void 0 : null == (_command_args_err = _command_args.err) ? void 0 : _command_args_err.message) explanation = command.args.err.message;
21553
+ const err = error_createError({
21554
+ message: "Websocket error from Videomail server",
21555
+ explanation,
21556
+ err: deserializeError(null == (_command_args1 = command.args) ? void 0 : _command_args1.err),
21557
+ options: this.options
21224
21558
  });
21225
- this.visuals.checkTimer(elapsedTime);
21559
+ this.emit("ERROR", {
21560
+ err
21561
+ });
21562
+ break;
21563
+ }
21564
+ case "confirmFrame":
21565
+ this.updateFrameProgress(command.args);
21566
+ break;
21567
+ case "confirmSample":
21568
+ this.updateSampleProgress(command.args);
21569
+ break;
21570
+ case "beginAudioEncoding":
21571
+ this.emit("BEGIN_AUDIO_ENCODING");
21572
+ break;
21573
+ case "beginVideoEncoding":
21574
+ this.emit("BEGIN_VIDEO_ENCODING");
21575
+ break;
21576
+ default:
21577
+ {
21578
+ const err = error_createError({
21579
+ message: `Unknown server command: ${command.command}`,
21580
+ options: this.options
21581
+ });
21582
+ this.emit("ERROR", {
21583
+ err
21584
+ });
21585
+ break;
21226
21586
  }
21227
- } else throw error_createError({
21228
- message: "Failed to extract webcam data.",
21229
- options: this.options
21230
- });
21231
21587
  }
21232
21588
  } catch (exc) {
21233
21589
  this.emit("ERROR", {
@@ -21235,156 +21591,34 @@ var __webpack_exports__ = {};
21235
21591
  });
21236
21592
  }
21237
21593
  }
21238
- createLoop() {
21239
- const newLoop = animitter_default()({
21240
- fps: this.options.video.fps
21241
- }, this.draw.bind(this));
21242
- this.originalAnimationFrameObject = newLoop.getRequestAnimationFrameObject();
21243
- return newLoop;
21244
- }
21245
- record() {
21246
- if (this.unloaded || this.cameraRecovery) return;
21247
- if (!this.connected) {
21248
- this.options.logger.debug("Recorder: reconnecting before recording …");
21249
- this.initSocket(()=>{
21250
- this.once("SERVER_READY", ()=>{
21251
- if (this.unloaded) return;
21252
- if (this.userMediaLoaded || this.options.loadUserMediaOnRecord) this.record();
21253
- else this.once("USER_MEDIA_READY", ()=>{
21254
- if (!this.unloaded) this.record();
21255
- });
21256
- });
21257
- });
21258
- return;
21259
- }
21260
- if (!this.userMediaLoaded) {
21261
- if (this.options.loadUserMediaOnRecord) this.loadUserMedia({
21262
- recordWhenReady: true
21263
- });
21264
- else {
21265
- const err = error_createError({
21266
- message: "Load and enable your camera first",
21267
- options: this.options
21268
- });
21269
- this.emit("ERROR", {
21270
- err
21271
- });
21272
- }
21273
- return;
21274
- }
21275
- this.recordingDimensions = void 0;
21276
- try {
21277
- if (!this.userMedia) throw new Error("No user media defined, unable to create canvas");
21278
- this.canvas = this.userMedia.createCanvas();
21279
- } catch (exc) {
21280
- const err = error_createError({
21281
- exc,
21282
- options: this.options
21283
- });
21284
- this.emit("ERROR", {
21285
- err
21286
- });
21287
- return;
21288
- }
21289
- this.ctx = this.canvas.getContext("2d");
21290
- if (!this.canvas.width) {
21291
- const err = error_createError({
21292
- message: "Canvas has an invalid width.",
21293
- options: this.options
21294
- });
21295
- this.emit("ERROR", {
21296
- err
21297
- });
21298
- return;
21299
- }
21300
- if (!this.canvas.height) {
21301
- const err = error_createError({
21302
- message: "Canvas has an invalid height.",
21303
- options: this.options
21304
- });
21305
- this.emit("ERROR", {
21306
- err
21307
- });
21308
- return;
21309
- }
21310
- this.recordingDimensions = {
21311
- width: this.canvas.width,
21312
- height: this.canvas.height
21313
- };
21314
- this.frame = new canvas_to_buffer_modern_r(this.canvas, this.options.image.types, this.options.image.quality);
21315
- this.options.logger.debug("Recorder: record()");
21316
- this.recordingActive = true;
21317
- this.recordingTransportFailed = false;
21594
+ unload(params) {
21595
+ if (this.unloaded || !this.built) return;
21596
+ const e = null == params ? void 0 : params.e;
21597
+ let cause;
21598
+ if (e) cause = e.type;
21599
+ const prettyCause = cause ? `, cause: ${cause}` : "";
21600
+ this.options.logger.debug(`Recorder: unload()${prettyCause}`);
21601
+ this.recordingActive = false;
21318
21602
  this.mediaTransmissionStarted = false;
21319
- this.recordingAudioSampleRate = void 0;
21320
- this.userMedia.record();
21321
- this.emit("RECORDING", {
21322
- framesCount: this.framesCount
21323
- });
21324
- this.loop.on("update", (_deltaTime, elapsedTime)=>{
21325
- let avgFPS;
21326
- avgFPS = 0 !== elapsedTime ? Math.round(this.framesCount / elapsedTime * 1000) : void 0;
21327
- this.options.logger.debug(`Recorder updates avgFps = ${avgFPS} at frame ${this.framesCount}`);
21328
- });
21329
- this.loop.start();
21330
- }
21331
- setAnimationFrameObject(newObj) {
21332
- if (this.loop) {
21333
- const isRecording = this.isRecording();
21334
- this.loop.stop();
21335
- this.loop.setRequestAnimationFrameObject(newObj);
21336
- if (isRecording) this.loop.start();
21337
- }
21338
- }
21339
- restoreAnimationFrameObject() {
21340
- this.options.logger.debug("Recorder: restoreAnimationFrameObject()");
21341
- this.setAnimationFrameObject(this.originalAnimationFrameObject);
21342
- }
21343
- loopWithTimeouts() {
21344
- this.options.logger.debug("Recorder: loopWithTimeouts()");
21345
- const wantedInterval = 1e3 / this.options.video.fps;
21346
- let processingTime = 0;
21347
- let start;
21348
- const raf = (fn)=>setTimeout(()=>{
21349
- start = Date.now();
21350
- fn();
21351
- processingTime = Date.now() - start;
21352
- }, wantedInterval - processingTime);
21353
- const cancel = (id)=>{
21354
- window.clearTimeout(id);
21355
- };
21356
- this.setAnimationFrameObject({
21357
- requestAnimationFrame: raf,
21358
- cancelAnimationFrame: cancel
21359
- });
21603
+ this.reset();
21604
+ this.recordingDimensions = void 0;
21605
+ this.clearUserMediaTimeout();
21606
+ this.clearConnectionTimeout();
21607
+ this.clearReconnectTimeout();
21608
+ this.clearRetryTimeout();
21609
+ this.clearStopTimeout();
21610
+ this.stopPings();
21611
+ this.userMediaLoading = false;
21612
+ this.connecting = false;
21613
+ this.reconnecting = false;
21614
+ this.reconnectAttempts = 0;
21615
+ if (this.userMedia) this.userMedia.unloadRemainingEventListeners();
21616
+ this.unloaded = true;
21617
+ this.discardSocket();
21618
+ this.built = this.connecting = this.connected = false;
21360
21619
  }
21361
21620
  correctDimensions() {
21362
- if (!this.recorderElement) return;
21363
- const widthDimension = dimensions_useFullWidth(this.options.video.mobileBreakPoint);
21364
- if (this.options.video.stretch || widthDimension) {
21365
- this.recorderElement.style.width = "100%";
21366
- this.recorderElement.style.removeProperty("height");
21367
- } else {
21368
- if (this.options.video.width) {
21369
- const recorderWidth = this.getRecorderWidth(true);
21370
- if (null == recorderWidth ? void 0 : recorderWidth.value) this.recorderElement.width = recorderWidth.value;
21371
- else this.recorderElement.style.removeProperty("width");
21372
- }
21373
- if (this.options.video.height) {
21374
- const recorderHeight = this.getRecorderHeight(true);
21375
- if (null == recorderHeight ? void 0 : recorderHeight.value) this.recorderElement.height = recorderHeight.value;
21376
- else this.recorderElement.style.removeProperty("height");
21377
- }
21378
- }
21379
- }
21380
- switchFacingMode() {
21381
- if (this.cameraRecovery || !util_getBrowser(this.options).isMobile()) return;
21382
- if ("user" === this.facingMode) this.facingMode = "environment";
21383
- else if ("environment" === this.facingMode) this.facingMode = "user";
21384
- else this.options.logger.warn(`Recorder: unsupported facing mode ${string_pretty(this.facingMode)}`);
21385
- this.loadGenuineUserMedia({
21386
- switchingFacingMode: this.facingMode
21387
- });
21621
+ this.dimensions.correctDimensions();
21388
21622
  }
21389
21623
  initEvents() {
21390
21624
  this.options.logger.debug("Recorder: initEvents()");
@@ -21457,101 +21691,20 @@ var __webpack_exports__ = {};
21457
21691
  }
21458
21692
  this.built = true;
21459
21693
  }
21460
- isPaused() {
21461
- var _this_userMedia;
21462
- return (null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.isPaused()) && !this.loop.isRunning();
21463
- }
21464
- isRecording() {
21465
- var _this_loop;
21466
- return Boolean((null == (_this_loop = this.loop) ? void 0 : _this_loop.isRunning()) && !this.isPaused() && !this.isNotifying() && this.stream && !this.stream.destroyed);
21467
- }
21468
- hide() {
21469
- if (!this.isHidden()) {
21470
- if (this.recorderElement) html_hideElement(this.recorderElement);
21471
- this.clearUserMediaTimeout();
21472
- this.clearRetryTimeout();
21473
- }
21474
- }
21475
- isUnloaded() {
21476
- return this.unloaded;
21477
- }
21478
21694
  getRecorderWidth(responsive) {
21479
- var _this_userMedia;
21480
- if (null == (_this_userMedia = this.userMedia) ? void 0 : _this_userMedia.hasVideoWidth()) return this.userMedia.getRawWidth(responsive);
21481
- else if (responsive && this.options.video.width) return this.limitWidth(this.options.video.width);
21482
- const dimension = {
21483
- unit: "px",
21484
- value: this.options.video.width
21485
- };
21486
- return dimension;
21487
- }
21488
- getRecordingDimensions() {
21489
- return this.recordingDimensions && recorder_object_spread({}, this.recordingDimensions);
21695
+ return this.dimensions.getRecorderWidth(responsive);
21490
21696
  }
21491
21697
  getRecorderHeight(responsive, useBoundingClientRect) {
21492
- let recorderHeight;
21493
- if (this.recorderElement && useBoundingClientRect) {
21494
- const height = this.recorderElement.getBoundingClientRect().height;
21495
- recorderHeight = {
21496
- unit: "px",
21497
- value: height
21498
- };
21499
- } else if (this.userMedia) {
21500
- let height = this.userMedia.getRawHeight(responsive);
21501
- if (void 0 !== height && this.options.video.width) {
21502
- const ratio = this.getRatio();
21503
- if (void 0 !== ratio) {
21504
- const idealHeight = this.options.video.width * ratio;
21505
- height = Math.min(idealHeight, height);
21506
- }
21507
- }
21508
- recorderHeight = {
21509
- unit: "px",
21510
- value: height
21511
- };
21512
- } else if (responsive && this.options.video.height) recorderHeight = this.calculateHeight(responsive);
21513
- else if (this.options.video.height) {
21514
- const height = this.options.video.height;
21515
- recorderHeight = {
21516
- unit: "px",
21517
- value: height
21518
- };
21519
- }
21520
- return recorderHeight;
21698
+ return this.dimensions.getRecorderHeight(responsive, useBoundingClientRect);
21521
21699
  }
21522
21700
  getRatio() {
21523
- let ratio;
21524
- if (this.userMedia) {
21525
- const userMediaVideoWidth = this.userMedia.getVideoWidth();
21526
- const userMediaVideoHeight = this.userMedia.getVideoHeight();
21527
- if (!userMediaVideoWidth || userMediaVideoWidth < 1) ratio = this.visuals.getRatio();
21528
- else if (userMediaVideoHeight) ratio = userMediaVideoHeight / userMediaVideoWidth;
21529
- } else ratio = dimensions_getRatio(this.options);
21530
- return ratio;
21701
+ return this.dimensions.getRatio();
21531
21702
  }
21532
21703
  calculateWidth(responsive) {
21533
- let videoHeight;
21534
- if (this.userMedia) videoHeight = this.userMedia.getVideoHeight();
21535
- else if (this.recorderElement) videoHeight = this.recorderElement.videoHeight || this.recorderElement.height;
21536
- const ratio = this.getRatio();
21537
- return dimensions_calculateWidth(responsive, this.options, videoHeight, ratio);
21704
+ return this.dimensions.calculateWidth(responsive);
21538
21705
  }
21539
21706
  calculateHeight(responsive) {
21540
- let videoDimension;
21541
- if (this.userMedia) {
21542
- const videoHeight = this.userMedia.getVideoHeight();
21543
- videoDimension = {
21544
- value: videoHeight,
21545
- unit: "px"
21546
- };
21547
- } else if (this.recorderElement) {
21548
- const videoHeight = this.recorderElement.videoHeight || this.recorderElement.height;
21549
- videoDimension = {
21550
- value: videoHeight,
21551
- unit: "px"
21552
- };
21553
- } else videoDimension = dimensions_calculateHeight(responsive, void 0, this.options, this.getRatio(), this.recorderElement);
21554
- return videoDimension;
21707
+ return this.dimensions.calculateHeight(responsive);
21555
21708
  }
21556
21709
  getRawVisualUserMedia() {
21557
21710
  return this.recorderElement;
@@ -21568,14 +21721,14 @@ var __webpack_exports__ = {};
21568
21721
  limitHeight(height) {
21569
21722
  return this.visuals.limitHeight(height);
21570
21723
  }
21571
- isUserMediaLoaded() {
21572
- return this.userMediaLoaded;
21573
- }
21574
21724
  constructor(visuals, replay, options){
21575
- 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, "recordingAudioSampleRate", void 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, "mediaRequestId", 0), recorder_define_property(this, "cameraRecovery", void 0), recorder_define_property(this, "resolveCameraRecovery", void 0), recorder_define_property(this, "resumeAfterCameraRecovery", 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);
21576
- this.visuals = visuals;
21577
- this.replay = replay;
21578
- this.facingMode = options.video.facingMode;
21725
+ super(visuals, replay, options), recorder_define_property(this, "dimensions", void 0);
21726
+ this.dimensions = new recorder_dimensions({
21727
+ options,
21728
+ visuals,
21729
+ getRecorderElement: ()=>this.recorderElement,
21730
+ getUserMedia: ()=>this.userMedia
21731
+ });
21579
21732
  }
21580
21733
  }
21581
21734
  const visuals_recorder = Recorder;
@@ -22539,8 +22692,8 @@ var __webpack_exports__ = {};
22539
22692
  }
22540
22693
  else runValidation = false;
22541
22694
  if (runValidation) {
22542
- var _event_target;
22543
- const targetName = null == event ? void 0 : null == (_event_target = event.target) ? void 0 : _event_target.name;
22695
+ const target = null == event ? void 0 : event.target;
22696
+ const targetName = target instanceof Element ? target.getAttribute("name") : void 0;
22544
22697
  if (targetName) this.emit("VALIDATING", {
22545
22698
  targetName
22546
22699
  });
@@ -22575,27 +22728,10 @@ var __webpack_exports__ = {};
22575
22728
  }
22576
22729
  }
22577
22730
  if (valid) {
22578
- const recipients = this.form.getRecipients();
22579
- const toIsConfigured = "to" in recipients;
22580
- const ccIsConfigured = "cc" in recipients;
22581
- const bccIsConfigured = "bcc" in recipients;
22582
- const hasTo = recipients.to && recipients.to.length > 0;
22583
- const hasCc = recipients.cc && recipients.cc.length > 0;
22584
- const hasBcc = recipients.bcc && recipients.bcc.length > 0;
22585
- if (toIsConfigured) {
22586
- if (!hasTo) if (ccIsConfigured && bccIsConfigured) {
22587
- if (!hasCc && !hasBcc) valid = false;
22588
- } else if (ccIsConfigured) {
22589
- if (!hasCc) valid = false;
22590
- } else if (bccIsConfigured) {
22591
- if (!hasBcc) valid = false;
22592
- } else valid = false;
22593
- } else if (ccIsConfigured) {
22594
- if (!hasCc) {
22595
- if (bccIsConfigured && !hasBcc) valid = false;
22596
- }
22731
+ if (!email_isRecipientSelectionValid(this.form.getRecipients())) {
22732
+ valid = false;
22733
+ whyInvalid = "At least one recipient is required";
22597
22734
  }
22598
- if (!valid) whyInvalid = "At least one recipient is required";
22599
22735
  }
22600
22736
  } else {
22601
22737
  valid = visualsValid;