videomail-client 16.0.3 → 16.1.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.
- package/README.md +18 -0
- package/dist/cjs/index.cjs +299 -47
- package/dist/esm/client.d.ts +2 -0
- package/dist/esm/index.js +228 -45
- package/dist/esm/types/events/index.d.ts +3 -1
- package/dist/esm/types/events/params.d.ts +4 -0
- package/dist/esm/util/Despot.d.ts +2 -0
- package/dist/esm/util/html/media/AudioRecorder.d.ts +3 -0
- package/dist/esm/wrappers/container.d.ts +2 -0
- package/dist/esm/wrappers/visuals/recorder.d.ts +9 -0
- package/dist/esm/wrappers/visuals/userMedia.d.ts +8 -3
- package/dist/esm/wrappers/visuals.d.ts +3 -0
- package/dist/umd/index.js +233 -42
- package/package.json +1 -1
package/dist/umd/index.js
CHANGED
|
@@ -11121,7 +11121,7 @@
|
|
|
11121
11121
|
var client = __webpack_require__("Q");
|
|
11122
11122
|
var client_default = /*#__PURE__*/ __webpack_require__.n(client);
|
|
11123
11123
|
var package_namespaceObject = {
|
|
11124
|
-
rE: "16.0
|
|
11124
|
+
rE: "16.1.0"
|
|
11125
11125
|
};
|
|
11126
11126
|
function isAudioEnabled(options) {
|
|
11127
11127
|
return Boolean(options.audio.enabled);
|
|
@@ -18636,10 +18636,14 @@
|
|
|
18636
18636
|
this.on("USER_MEDIA_READY", ()=>{
|
|
18637
18637
|
this.facingMode?.show();
|
|
18638
18638
|
});
|
|
18639
|
+
this.on("CAMERA_RECOVERING", ()=>{
|
|
18640
|
+
this.facingMode?.hide();
|
|
18641
|
+
});
|
|
18639
18642
|
this.on("RECORDING", ()=>{
|
|
18640
18643
|
this.startRecording();
|
|
18641
18644
|
});
|
|
18642
18645
|
this.on("RESUMING", ()=>{
|
|
18646
|
+
this.hidePause();
|
|
18643
18647
|
this.resumeRecording();
|
|
18644
18648
|
});
|
|
18645
18649
|
this.on("STOPPING", ()=>{
|
|
@@ -19254,6 +19258,7 @@
|
|
|
19254
19258
|
class AudioRecorder {
|
|
19255
19259
|
scriptProcessor;
|
|
19256
19260
|
audioInput;
|
|
19261
|
+
volume;
|
|
19257
19262
|
vcAudioContext;
|
|
19258
19263
|
userMedia;
|
|
19259
19264
|
options;
|
|
@@ -19276,9 +19281,19 @@
|
|
|
19276
19281
|
const float32Array = e.inputBuffer.getChannelData(0);
|
|
19277
19282
|
cb(new esm(float32Array));
|
|
19278
19283
|
}
|
|
19284
|
+
disconnect() {
|
|
19285
|
+
if (this.scriptProcessor) {
|
|
19286
|
+
this.scriptProcessor.onaudioprocess = null;
|
|
19287
|
+
this.scriptProcessor.disconnect();
|
|
19288
|
+
}
|
|
19289
|
+
this.audioInput?.disconnect();
|
|
19290
|
+
this.volume?.disconnect();
|
|
19291
|
+
}
|
|
19279
19292
|
init(localMediaStream) {
|
|
19280
19293
|
this.options.logger.debug("AudioRecorder: init()");
|
|
19294
|
+
this.disconnect();
|
|
19281
19295
|
const volume = this.getAudioContext().createGain();
|
|
19296
|
+
this.volume = volume;
|
|
19282
19297
|
try {
|
|
19283
19298
|
this.audioInput = this.getAudioContext().createMediaStreamSource(localMediaStream);
|
|
19284
19299
|
} catch (exc) {
|
|
@@ -19310,10 +19325,13 @@
|
|
|
19310
19325
|
this.onAudioProcess(e, cb);
|
|
19311
19326
|
};
|
|
19312
19327
|
}
|
|
19328
|
+
async resume() {
|
|
19329
|
+
const context = this.getAudioContext();
|
|
19330
|
+
if ("running" !== context.state) await context.resume();
|
|
19331
|
+
}
|
|
19313
19332
|
stop() {
|
|
19314
19333
|
this.options.logger.debug("AudioRecorder: stop()");
|
|
19315
|
-
|
|
19316
|
-
if (this.audioInput) this.audioInput.disconnect();
|
|
19334
|
+
this.disconnect();
|
|
19317
19335
|
if (this.hasAudioContext()) this.getAudioContext().close().then(()=>{
|
|
19318
19336
|
this.options.logger.debug("AudioRecorder: audio context is closed");
|
|
19319
19337
|
this.vcAudioContext = void 0;
|
|
@@ -19358,6 +19376,8 @@
|
|
|
19358
19376
|
onLoadedMetaDataReached = false;
|
|
19359
19377
|
playingPromiseReached = false;
|
|
19360
19378
|
videoTrackLabel;
|
|
19379
|
+
clearInitializationListeners;
|
|
19380
|
+
initializationId = 0;
|
|
19361
19381
|
outputEvent = (e)=>{
|
|
19362
19382
|
this.logEvent(e.type, {
|
|
19363
19383
|
readyState: this.rawVisualUserMedia?.readyState
|
|
@@ -19399,6 +19419,16 @@
|
|
|
19399
19419
|
this.currentVisualStream = void 0;
|
|
19400
19420
|
}
|
|
19401
19421
|
}
|
|
19422
|
+
async restorePlayback() {
|
|
19423
|
+
if (!this.rawVisualUserMedia) throw new Error("No camera preview is available.");
|
|
19424
|
+
await this.rawVisualUserMedia.play();
|
|
19425
|
+
await this.audioRecorder?.resume();
|
|
19426
|
+
}
|
|
19427
|
+
hasLiveStream() {
|
|
19428
|
+
const videoReady = this.currentVisualStream?.getVideoTracks().some((track)=>"live" === track.readyState && track.enabled && !track.muted);
|
|
19429
|
+
const audioReady = !isAudioEnabled(this.options) || this.currentVisualStream?.getAudioTracks().some((track)=>"live" === track.readyState && track.enabled && !track.muted);
|
|
19430
|
+
return Boolean(this.currentVisualStream?.active && videoReady && audioReady);
|
|
19431
|
+
}
|
|
19402
19432
|
hasEnded() {
|
|
19403
19433
|
if (this.rawVisualUserMedia?.ended) return this.rawVisualUserMedia.ended;
|
|
19404
19434
|
return !this.currentVisualStream?.active;
|
|
@@ -19413,6 +19443,7 @@
|
|
|
19413
19443
|
}
|
|
19414
19444
|
unloadRemainingEventListeners() {
|
|
19415
19445
|
this.options.logger.debug("UserMedia: unloadRemainingEventListeners()");
|
|
19446
|
+
this.clearInitializationListeners?.();
|
|
19416
19447
|
mediaEvents.forEach((eventName)=>{
|
|
19417
19448
|
this.rawVisualUserMedia?.removeEventListener(eventName, this.outputEvent);
|
|
19418
19449
|
});
|
|
@@ -19422,11 +19453,13 @@
|
|
|
19422
19453
|
this.removeListener("SENDING_FIRST_FRAME");
|
|
19423
19454
|
this.audioRecorder?.record(audioCallback);
|
|
19424
19455
|
}
|
|
19425
|
-
init(localMediaStream, videoCallback, audioCallback, endedEarlyCallback,
|
|
19456
|
+
init(localMediaStream, videoCallback, audioCallback, endedEarlyCallback, params) {
|
|
19457
|
+
this.clearInitializationListeners?.();
|
|
19426
19458
|
this.stop(localMediaStream, {
|
|
19427
19459
|
aboutToInitialize: true,
|
|
19428
|
-
switchingFacingMode
|
|
19460
|
+
preserveRecordingState: Boolean(params?.switchingFacingMode || params?.recovering)
|
|
19429
19461
|
});
|
|
19462
|
+
const initializationId = ++this.initializationId;
|
|
19430
19463
|
this.onPlayReached = false;
|
|
19431
19464
|
this.onLoadedMetaDataReached = false;
|
|
19432
19465
|
this.playingPromiseReached = false;
|
|
@@ -19439,18 +19472,25 @@
|
|
|
19439
19472
|
this.rawVisualUserMedia?.removeEventListener("play", onPlay);
|
|
19440
19473
|
this.rawVisualUserMedia?.removeEventListener("loadedmetadata", onLoadedMetaData);
|
|
19441
19474
|
};
|
|
19475
|
+
this.clearInitializationListeners = ()=>{
|
|
19476
|
+
this.rawVisualUserMedia?.removeEventListener("play", onPlay);
|
|
19477
|
+
this.rawVisualUserMedia?.removeEventListener("loadedmetadata", onLoadedMetaData);
|
|
19478
|
+
this.clearInitializationListeners = void 0;
|
|
19479
|
+
};
|
|
19442
19480
|
const play = ()=>{
|
|
19443
19481
|
try {
|
|
19444
19482
|
this.rawVisualUserMedia?.load();
|
|
19445
19483
|
if (this.rawVisualUserMedia?.paused) {
|
|
19446
19484
|
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)}`);
|
|
19447
19485
|
this.rawVisualUserMedia.play().then(()=>{
|
|
19486
|
+
if (initializationId !== this.initializationId) return;
|
|
19448
19487
|
if (!this.playingPromiseReached) {
|
|
19449
19488
|
this.options.logger.debug("UserMedia: play promise successful. Playing now.");
|
|
19450
19489
|
this.playingPromiseReached = true;
|
|
19451
19490
|
}
|
|
19452
19491
|
}).catch((exc)=>{
|
|
19453
|
-
if (
|
|
19492
|
+
if (initializationId !== this.initializationId) return;
|
|
19493
|
+
if (exc instanceof Error && !params?.recovering) this.options.logger.warn(`Caught pending user media promise exception: ${exc.toString()}`);
|
|
19454
19494
|
else {
|
|
19455
19495
|
unloadAllEventListeners();
|
|
19456
19496
|
endedEarlyCallback(error_createError({
|
|
@@ -19471,16 +19511,28 @@
|
|
|
19471
19511
|
this.options.logger.debug(`UserMedia: fireCallbacks(readyState=${readyState}, onPlayReached=${this.onPlayReached}, onLoadedMetaDataReached=${this.onLoadedMetaDataReached})`);
|
|
19472
19512
|
if (this.onPlayReached && this.onLoadedMetaDataReached) if (this.audioRecorder) try {
|
|
19473
19513
|
this.audioRecorder.init(localMediaStream);
|
|
19474
|
-
|
|
19475
|
-
this.
|
|
19476
|
-
|
|
19477
|
-
|
|
19514
|
+
const onAudioReady = ()=>{
|
|
19515
|
+
if (initializationId !== this.initializationId || this.currentVisualStream !== localMediaStream) return;
|
|
19516
|
+
if (this.recording) this.audioRecord(audioCallback);
|
|
19517
|
+
else this.on("SENDING_FIRST_FRAME", ()=>{
|
|
19518
|
+
this.audioRecord(audioCallback);
|
|
19519
|
+
});
|
|
19520
|
+
this.clearInitializationListeners?.();
|
|
19521
|
+
videoCallback();
|
|
19522
|
+
};
|
|
19523
|
+
if (params?.recovering) this.audioRecorder.resume().then(onAudioReady).catch(endedEarlyCallback);
|
|
19524
|
+
else onAudioReady();
|
|
19478
19525
|
} catch (exc) {
|
|
19479
19526
|
unloadAllEventListeners();
|
|
19480
|
-
this.stop(
|
|
19527
|
+
this.stop(void 0, {
|
|
19528
|
+
preserveRecordingState: Boolean(params?.recovering)
|
|
19529
|
+
});
|
|
19481
19530
|
endedEarlyCallback(exc);
|
|
19482
19531
|
}
|
|
19483
|
-
else
|
|
19532
|
+
else {
|
|
19533
|
+
this.clearInitializationListeners?.();
|
|
19534
|
+
videoCallback();
|
|
19535
|
+
}
|
|
19484
19536
|
};
|
|
19485
19537
|
const onPlay = ()=>{
|
|
19486
19538
|
try {
|
|
@@ -19550,9 +19602,8 @@
|
|
|
19550
19602
|
this.setVisualStream(localMediaStream);
|
|
19551
19603
|
play();
|
|
19552
19604
|
} catch (exc) {
|
|
19553
|
-
|
|
19554
|
-
|
|
19555
|
-
});
|
|
19605
|
+
unloadAllEventListeners();
|
|
19606
|
+
endedEarlyCallback(exc);
|
|
19556
19607
|
}
|
|
19557
19608
|
}
|
|
19558
19609
|
getVideoTrackLabel() {
|
|
@@ -19565,6 +19616,8 @@
|
|
|
19565
19616
|
try {
|
|
19566
19617
|
let chosenStream = visualStream;
|
|
19567
19618
|
if (!params?.aboutToInitialize) {
|
|
19619
|
+
this.initializationId++;
|
|
19620
|
+
this.clearInitializationListeners?.();
|
|
19568
19621
|
chosenStream ??= this.currentVisualStream;
|
|
19569
19622
|
const tracks = chosenStream?.getTracks();
|
|
19570
19623
|
if (tracks) tracks.forEach((track)=>{
|
|
@@ -19574,7 +19627,7 @@
|
|
|
19574
19627
|
this.audioRecorder?.stop();
|
|
19575
19628
|
this.audioRecorder = void 0;
|
|
19576
19629
|
}
|
|
19577
|
-
if (!params?.
|
|
19630
|
+
if (!params?.preserveRecordingState) this.paused = this.recording = false;
|
|
19578
19631
|
} catch (exc) {
|
|
19579
19632
|
this.emit("ERROR", {
|
|
19580
19633
|
exc
|
|
@@ -19672,6 +19725,7 @@
|
|
|
19672
19725
|
originalAnimationFrameObject;
|
|
19673
19726
|
samplesCount = 0;
|
|
19674
19727
|
framesCount = 0;
|
|
19728
|
+
recordingAudioSampleRate;
|
|
19675
19729
|
recordingStats;
|
|
19676
19730
|
confirmedFrameNumber = 0;
|
|
19677
19731
|
confirmedSampleNumber = 0;
|
|
@@ -19690,6 +19744,10 @@
|
|
|
19690
19744
|
ctx;
|
|
19691
19745
|
userMediaLoaded;
|
|
19692
19746
|
userMediaLoading = false;
|
|
19747
|
+
mediaRequestId = 0;
|
|
19748
|
+
cameraRecovery;
|
|
19749
|
+
resolveCameraRecovery;
|
|
19750
|
+
resumeAfterCameraRecovery = false;
|
|
19693
19751
|
submitting = false;
|
|
19694
19752
|
unloaded;
|
|
19695
19753
|
stopTime;
|
|
@@ -19953,7 +20011,9 @@
|
|
|
19953
20011
|
this.pingInterval = void 0;
|
|
19954
20012
|
}
|
|
19955
20013
|
onAudioSample(audioSample) {
|
|
19956
|
-
if (this.recordingTransportFailed) return;
|
|
20014
|
+
if (this.recordingTransportFailed || this.cameraRecovery) return;
|
|
20015
|
+
const sampleRate = this.userMedia?.getAudioSampleRate();
|
|
20016
|
+
if (sampleRate && sampleRate > 0) this.recordingAudioSampleRate ??= sampleRate;
|
|
19957
20017
|
this.samplesCount++;
|
|
19958
20018
|
this.mediaTransmissionStarted = true;
|
|
19959
20019
|
const audioBuffer = audioSample.toBuffer();
|
|
@@ -19966,19 +20026,26 @@
|
|
|
19966
20026
|
try {
|
|
19967
20027
|
this.options.logger.debug(`Recorder: onUserMediaReady(${params ? string_pretty(params) : ""})`);
|
|
19968
20028
|
const switchingFacingMode = params?.switchingFacingMode;
|
|
20029
|
+
if (params?.recovering) {
|
|
20030
|
+
if (!this.userMedia?.hasLiveStream()) return void this.failCameraRecovery(new Error("The restored camera has no live tracks."));
|
|
20031
|
+
if (void 0 !== this.recordingAudioSampleRate && this.userMedia.getAudioSampleRate() !== this.recordingAudioSampleRate) return void this.failCameraRecovery(new Error("The audio sample rate changed during recovery."));
|
|
20032
|
+
}
|
|
19969
20033
|
this.userMediaLoading = this.blocking = this.unloaded = this.submitting = false;
|
|
19970
20034
|
this.userMediaLoaded = true;
|
|
19971
20035
|
this.clearUserMediaTimeout();
|
|
19972
|
-
if (!switchingFacingMode) this.loop = this.createLoop();
|
|
20036
|
+
if (!switchingFacingMode && !params?.recovering) this.loop = this.createLoop();
|
|
19973
20037
|
this.show();
|
|
19974
20038
|
if (params?.recordWhenReady) this.record();
|
|
19975
20039
|
this.emit("USER_MEDIA_READY", {
|
|
19976
20040
|
switchingFacingMode: params?.switchingFacingMode,
|
|
20041
|
+
recovering: params?.recovering,
|
|
19977
20042
|
paused: this.isPaused(),
|
|
19978
20043
|
recordWhenReady: params?.recordWhenReady
|
|
19979
20044
|
});
|
|
20045
|
+
if (params?.recovering) this.finishCameraRecovery(true);
|
|
19980
20046
|
} catch (exc) {
|
|
19981
|
-
this.
|
|
20047
|
+
if (params?.recovering) this.failCameraRecovery(exc);
|
|
20048
|
+
else this.emit("ERROR", {
|
|
19982
20049
|
exc
|
|
19983
20050
|
});
|
|
19984
20051
|
}
|
|
@@ -20349,6 +20416,7 @@
|
|
|
20349
20416
|
return this.blocking;
|
|
20350
20417
|
}
|
|
20351
20418
|
userMediaErrorCallback(err, usedConstraints) {
|
|
20419
|
+
if (this.cameraRecovery) return void this.failCameraRecovery(err);
|
|
20352
20420
|
if (this.unloaded) return void this.options.logger.debug(`Recorder: already unloaded. Not going to throw error ${string_pretty(err)}`);
|
|
20353
20421
|
this.userMediaLoading = false;
|
|
20354
20422
|
this.clearUserMediaTimeout();
|
|
@@ -20380,7 +20448,7 @@
|
|
|
20380
20448
|
});
|
|
20381
20449
|
}
|
|
20382
20450
|
}
|
|
20383
|
-
getUserMediaCallback(localStream, params) {
|
|
20451
|
+
getUserMediaCallback(localStream, params, requestId = this.mediaRequestId) {
|
|
20384
20452
|
if (!this.userMedia) {
|
|
20385
20453
|
localStream.getTracks().forEach((track)=>{
|
|
20386
20454
|
track.stop();
|
|
@@ -20393,20 +20461,20 @@
|
|
|
20393
20461
|
this.options.logger.debug(`Recorder: getUserMediaCallback(${params ? string_pretty(params) : ""})`);
|
|
20394
20462
|
if (this.showUserMedia()) try {
|
|
20395
20463
|
this.userMedia.init(localStream, ()=>{
|
|
20396
|
-
if (!this.unloaded) this.onUserMediaReady(params);
|
|
20464
|
+
if (!this.unloaded && requestId === this.mediaRequestId) this.onUserMediaReady(params);
|
|
20397
20465
|
}, this.onAudioSample.bind(this), (err)=>{
|
|
20398
|
-
if (!this.unloaded) this.userMediaErrorCallback(err, {
|
|
20466
|
+
if (!this.unloaded && requestId === this.mediaRequestId) this.userMediaErrorCallback(err, {
|
|
20399
20467
|
audio: isAudioEnabled(this.options)
|
|
20400
20468
|
});
|
|
20401
|
-
}, params
|
|
20469
|
+
}, params);
|
|
20402
20470
|
} catch (exc) {
|
|
20403
20471
|
localStream.getTracks().forEach((track)=>{
|
|
20404
20472
|
track.stop();
|
|
20405
20473
|
});
|
|
20406
20474
|
this.userMediaLoading = false;
|
|
20407
20475
|
this.clearUserMediaTimeout();
|
|
20408
|
-
this.
|
|
20409
|
-
|
|
20476
|
+
this.userMediaErrorCallback(exc, {
|
|
20477
|
+
audio: isAudioEnabled(this.options)
|
|
20410
20478
|
});
|
|
20411
20479
|
}
|
|
20412
20480
|
else {
|
|
@@ -20415,12 +20483,14 @@
|
|
|
20415
20483
|
});
|
|
20416
20484
|
this.userMediaLoading = false;
|
|
20417
20485
|
this.clearUserMediaTimeout();
|
|
20486
|
+
this.cancelCameraRecovery();
|
|
20418
20487
|
}
|
|
20419
20488
|
}
|
|
20420
20489
|
loadGenuineUserMedia(params) {
|
|
20421
20490
|
this.options.logger.debug(`Recorder: loadGenuineUserMedia(${params ? string_pretty(params) : ""})`);
|
|
20422
20491
|
this.emit("ASKING_WEBCAM_PERMISSION");
|
|
20423
20492
|
this.userMediaLoading = true;
|
|
20493
|
+
const requestId = ++this.mediaRequestId;
|
|
20424
20494
|
const constraints = {
|
|
20425
20495
|
video: {
|
|
20426
20496
|
frameRate: {
|
|
@@ -20434,18 +20504,18 @@
|
|
|
20434
20504
|
this.options.logger.debug(string_summarize("Recorder: available webcam constraints are:", navigator.mediaDevices.getSupportedConstraints()));
|
|
20435
20505
|
const streamPromise = navigator.mediaDevices.getUserMedia(constraints);
|
|
20436
20506
|
streamPromise.then((localStream)=>{
|
|
20437
|
-
if (this.unloaded) return void localStream.getTracks().forEach((track)=>{
|
|
20507
|
+
if (this.unloaded || requestId !== this.mediaRequestId) return void localStream.getTracks().forEach((track)=>{
|
|
20438
20508
|
track.stop();
|
|
20439
20509
|
});
|
|
20440
|
-
this.getUserMediaCallback(localStream, params);
|
|
20510
|
+
this.getUserMediaCallback(localStream, params, requestId);
|
|
20441
20511
|
}).catch((reason)=>{
|
|
20442
|
-
if (!this.unloaded) this.userMediaErrorCallback(reason, constraints);
|
|
20512
|
+
if (!this.unloaded && requestId === this.mediaRequestId) this.userMediaErrorCallback(reason, constraints);
|
|
20443
20513
|
});
|
|
20444
20514
|
}
|
|
20445
20515
|
configureVideoConstraints(constraints, params) {
|
|
20446
20516
|
const videoConstraints = "object" == typeof constraints.video ? constraints.video : void 0;
|
|
20447
20517
|
if (!videoConstraints) return;
|
|
20448
|
-
if (params?.switchingFacingMode) videoConstraints.facingMode = params.switchingFacingMode;
|
|
20518
|
+
if (params?.switchingFacingMode || params?.recovering) videoConstraints.facingMode = params.switchingFacingMode || this.facingMode;
|
|
20449
20519
|
if (this.options.video.width) videoConstraints.width = {
|
|
20450
20520
|
ideal: this.options.video.width
|
|
20451
20521
|
};
|
|
@@ -20473,8 +20543,8 @@
|
|
|
20473
20543
|
if (!this.userMediaLoaded) {
|
|
20474
20544
|
this.userMediaLoading = false;
|
|
20475
20545
|
const err = util_getBrowser(this.options).getNoAccessIssue();
|
|
20476
|
-
this.
|
|
20477
|
-
|
|
20546
|
+
this.userMediaErrorCallback(err, {
|
|
20547
|
+
audio: isAudioEnabled(this.options)
|
|
20478
20548
|
});
|
|
20479
20549
|
}
|
|
20480
20550
|
}, this.options.timeouts.userMedia);
|
|
@@ -20484,6 +20554,7 @@
|
|
|
20484
20554
|
this.clearUserMediaTimeout();
|
|
20485
20555
|
this.options.logger.debug("Recorder: failed to load genuine user media");
|
|
20486
20556
|
this.userMediaLoading = false;
|
|
20557
|
+
if (this.cameraRecovery) return void this.failCameraRecovery(exc);
|
|
20487
20558
|
const errorListeners = this.getListeners("ERROR");
|
|
20488
20559
|
if (errorListeners?.length) this.emit("ERROR", {
|
|
20489
20560
|
exc
|
|
@@ -20607,9 +20678,10 @@
|
|
|
20607
20678
|
return this.recordingStats;
|
|
20608
20679
|
}
|
|
20609
20680
|
getAudioSampleRate() {
|
|
20610
|
-
return this.userMedia?.getAudioSampleRate();
|
|
20681
|
+
return this.recordingAudioSampleRate ?? this.userMedia?.getAudioSampleRate();
|
|
20611
20682
|
}
|
|
20612
20683
|
stop(params) {
|
|
20684
|
+
this.cancelCameraRecovery();
|
|
20613
20685
|
if (!this.userMedia) throw new Error("No user media defined, unable to stop");
|
|
20614
20686
|
this.options.logger.debug(`Recorder: stop(${params ? string_pretty(params) : ""})`);
|
|
20615
20687
|
this.recordingActive = false;
|
|
@@ -20635,7 +20707,7 @@
|
|
|
20635
20707
|
if (this.userMedia) this.recordingStats.videoTrackLabel = this.userMedia.getVideoTrackLabel();
|
|
20636
20708
|
if (isAudioEnabled(this.options) && this.userMedia) {
|
|
20637
20709
|
this.recordingStats.samplesCount = this.samplesCount;
|
|
20638
|
-
this.recordingStats.sampleRate = this.userMedia.getAudioSampleRate();
|
|
20710
|
+
this.recordingStats.sampleRate = this.recordingAudioSampleRate ?? this.userMedia.getAudioSampleRate();
|
|
20639
20711
|
}
|
|
20640
20712
|
this.writeCommand("stop", this.recordingStats, ()=>{
|
|
20641
20713
|
this.emit("STOPPED", {
|
|
@@ -20690,6 +20762,7 @@
|
|
|
20690
20762
|
this.built = this.connecting = this.connected = false;
|
|
20691
20763
|
}
|
|
20692
20764
|
reset() {
|
|
20765
|
+
this.cancelCameraRecovery();
|
|
20693
20766
|
if (!this.unloaded) {
|
|
20694
20767
|
this.options.logger.debug("Recorder: reset()");
|
|
20695
20768
|
this.emit("RESETTING");
|
|
@@ -20717,7 +20790,70 @@
|
|
|
20717
20790
|
isReady() {
|
|
20718
20791
|
return this.userMedia?.isReady();
|
|
20719
20792
|
}
|
|
20793
|
+
finishCameraRecovery(restored) {
|
|
20794
|
+
this.clearUserMediaTimeout();
|
|
20795
|
+
const resolve = this.resolveCameraRecovery;
|
|
20796
|
+
const resumeRequested = restored && this.resumeAfterCameraRecovery;
|
|
20797
|
+
this.cameraRecovery = void 0;
|
|
20798
|
+
this.resolveCameraRecovery = void 0;
|
|
20799
|
+
this.resumeAfterCameraRecovery = false;
|
|
20800
|
+
resolve?.(restored);
|
|
20801
|
+
if (resumeRequested && this.isPaused()) this.resume();
|
|
20802
|
+
}
|
|
20803
|
+
cancelCameraRecovery() {
|
|
20804
|
+
if (!this.cameraRecovery) return;
|
|
20805
|
+
this.mediaRequestId++;
|
|
20806
|
+
this.userMediaLoading = false;
|
|
20807
|
+
this.userMediaLoaded = false;
|
|
20808
|
+
this.clearUserMediaTimeout();
|
|
20809
|
+
this.userMedia?.stop(void 0, {
|
|
20810
|
+
preserveRecordingState: true
|
|
20811
|
+
});
|
|
20812
|
+
this.finishCameraRecovery(false);
|
|
20813
|
+
}
|
|
20814
|
+
failCameraRecovery(exc) {
|
|
20815
|
+
this.cancelCameraRecovery();
|
|
20816
|
+
const err = error_createError({
|
|
20817
|
+
message: "Camera recovery failed",
|
|
20818
|
+
explanation: "Your recording is still paused. Check camera permissions, then try Resume again or stop to keep the recorded part.",
|
|
20819
|
+
exc,
|
|
20820
|
+
options: this.options
|
|
20821
|
+
});
|
|
20822
|
+
this.emit("CAMERA_RECOVERY_FAILED", {
|
|
20823
|
+
err
|
|
20824
|
+
});
|
|
20825
|
+
}
|
|
20826
|
+
recoverCamera() {
|
|
20827
|
+
if (this.cameraRecovery) return this.cameraRecovery;
|
|
20828
|
+
if (!this.built || this.unloaded || !this.userMedia || this.userMediaLoading || this.submitting || this.key || void 0 !== this.stopTimeout || this.recordingTransportFailed) return Promise.resolve(false);
|
|
20829
|
+
const liveStream = this.userMedia.hasLiveStream();
|
|
20830
|
+
if (liveStream && this.isRecording()) return Promise.resolve(true);
|
|
20831
|
+
if (!liveStream && this.recordingActive && !this.isPaused()) this.pause();
|
|
20832
|
+
const recovery = new Promise((resolve)=>{
|
|
20833
|
+
this.resolveCameraRecovery = resolve;
|
|
20834
|
+
});
|
|
20835
|
+
this.cameraRecovery = recovery;
|
|
20836
|
+
this.emit("CAMERA_RECOVERING");
|
|
20837
|
+
if (liveStream) {
|
|
20838
|
+
this.userMediaTimeout = window.setTimeout(()=>{
|
|
20839
|
+
this.failCameraRecovery(new Error("Camera playback recovery timed out."));
|
|
20840
|
+
}, this.options.timeouts.userMedia);
|
|
20841
|
+
this.userMedia.restorePlayback().then(()=>{
|
|
20842
|
+
if (this.cameraRecovery === recovery) this.finishCameraRecovery(true);
|
|
20843
|
+
}).catch((exc)=>{
|
|
20844
|
+
if (this.cameraRecovery === recovery) this.failCameraRecovery(exc);
|
|
20845
|
+
});
|
|
20846
|
+
} else {
|
|
20847
|
+
this.userMediaLoaded = false;
|
|
20848
|
+
this.loadUserMedia({
|
|
20849
|
+
recovering: true
|
|
20850
|
+
});
|
|
20851
|
+
}
|
|
20852
|
+
return recovery;
|
|
20853
|
+
}
|
|
20720
20854
|
pause(params) {
|
|
20855
|
+
this.cancelCameraRecovery();
|
|
20856
|
+
this.resumeAfterDrain = false;
|
|
20721
20857
|
if (params) this.options.logger.debug(`pause() at frame ${this.framesCount} with ${string_pretty(params)}`);
|
|
20722
20858
|
else this.options.logger.debug(`pause() at frame ${this.framesCount}`);
|
|
20723
20859
|
this.userMedia?.pause();
|
|
@@ -20726,10 +20862,15 @@
|
|
|
20726
20862
|
this.sendPings();
|
|
20727
20863
|
}
|
|
20728
20864
|
resume() {
|
|
20865
|
+
if (this.cameraRecovery || !this.userMedia?.hasLiveStream()) {
|
|
20866
|
+
this.recoverCamera();
|
|
20867
|
+
this.resumeAfterCameraRecovery = Boolean(this.cameraRecovery);
|
|
20868
|
+
return;
|
|
20869
|
+
}
|
|
20729
20870
|
this.options.logger.debug(`Recorder: resume() with frame ${this.framesCount}`);
|
|
20730
20871
|
this.stopPings();
|
|
20731
20872
|
this.emit("RESUMING");
|
|
20732
|
-
this.userMedia
|
|
20873
|
+
this.userMedia.resume();
|
|
20733
20874
|
if (this.streamBackpressured) this.resumeAfterDrain = true;
|
|
20734
20875
|
else this.loop.start();
|
|
20735
20876
|
}
|
|
@@ -20784,7 +20925,7 @@
|
|
|
20784
20925
|
return newLoop;
|
|
20785
20926
|
}
|
|
20786
20927
|
record() {
|
|
20787
|
-
if (this.unloaded) return;
|
|
20928
|
+
if (this.unloaded || this.cameraRecovery) return;
|
|
20788
20929
|
if (!this.connected) {
|
|
20789
20930
|
this.options.logger.debug("Recorder: reconnecting before recording …");
|
|
20790
20931
|
this.initSocket(()=>{
|
|
@@ -20857,6 +20998,7 @@
|
|
|
20857
20998
|
this.recordingActive = true;
|
|
20858
20999
|
this.recordingTransportFailed = false;
|
|
20859
21000
|
this.mediaTransmissionStarted = false;
|
|
21001
|
+
this.recordingAudioSampleRate = void 0;
|
|
20860
21002
|
this.userMedia.record();
|
|
20861
21003
|
this.emit("RECORDING", {
|
|
20862
21004
|
framesCount: this.framesCount
|
|
@@ -20918,7 +21060,7 @@
|
|
|
20918
21060
|
}
|
|
20919
21061
|
}
|
|
20920
21062
|
switchFacingMode() {
|
|
20921
|
-
if (!util_getBrowser(this.options).isMobile()) return;
|
|
21063
|
+
if (this.cameraRecovery || !util_getBrowser(this.options).isMobile()) return;
|
|
20922
21064
|
if ("user" === this.facingMode) this.facingMode = "environment";
|
|
20923
21065
|
else if ("environment" === this.facingMode) this.facingMode = "user";
|
|
20924
21066
|
else this.options.logger.warn(`Recorder: unsupported facing mode ${string_pretty(this.facingMode)}`);
|
|
@@ -20929,12 +21071,14 @@
|
|
|
20929
21071
|
initEvents() {
|
|
20930
21072
|
this.options.logger.debug("Recorder: initEvents()");
|
|
20931
21073
|
this.on("SUBMITTING", ()=>{
|
|
21074
|
+
this.cancelCameraRecovery();
|
|
20932
21075
|
this.submitting = true;
|
|
20933
21076
|
});
|
|
20934
21077
|
this.on("SUBMITTED", ()=>{
|
|
20935
21078
|
this.submitting = false;
|
|
20936
21079
|
});
|
|
20937
21080
|
this.on("BLOCKING", ()=>{
|
|
21081
|
+
this.cancelCameraRecovery();
|
|
20938
21082
|
this.blocking = true;
|
|
20939
21083
|
this.clearUserMediaTimeout();
|
|
20940
21084
|
});
|
|
@@ -21362,6 +21506,7 @@
|
|
|
21362
21506
|
notifier;
|
|
21363
21507
|
visualsElement;
|
|
21364
21508
|
built = false;
|
|
21509
|
+
cameraRecoveryFailed = false;
|
|
21365
21510
|
constructor(container, options){
|
|
21366
21511
|
super("Visuals", options);
|
|
21367
21512
|
this.container = container;
|
|
@@ -21396,6 +21541,17 @@
|
|
|
21396
21541
|
this.endWaiting();
|
|
21397
21542
|
this.container.enableForm(false);
|
|
21398
21543
|
});
|
|
21544
|
+
this.on("CAMERA_RECOVERING", ()=>{
|
|
21545
|
+
this.clearCameraRecoveryNotice();
|
|
21546
|
+
});
|
|
21547
|
+
this.on("CAMERA_RECOVERY_FAILED", ({ err })=>{
|
|
21548
|
+
this.cameraRecoveryFailed = true;
|
|
21549
|
+
this.options.logger.warn(err);
|
|
21550
|
+
if (this.options.displayErrors) this.notifier.notify(err.message, err.explanation, {
|
|
21551
|
+
problem: true
|
|
21552
|
+
});
|
|
21553
|
+
this.endWaiting();
|
|
21554
|
+
});
|
|
21399
21555
|
this.on("PREVIEW", ()=>{
|
|
21400
21556
|
this.endWaiting();
|
|
21401
21557
|
});
|
|
@@ -21474,6 +21630,7 @@
|
|
|
21474
21630
|
child.remove();
|
|
21475
21631
|
}
|
|
21476
21632
|
reset() {
|
|
21633
|
+
this.clearCameraRecoveryNotice();
|
|
21477
21634
|
this.endWaiting();
|
|
21478
21635
|
this.recorder.reset();
|
|
21479
21636
|
}
|
|
@@ -21484,11 +21641,13 @@
|
|
|
21484
21641
|
this.container.endWaiting();
|
|
21485
21642
|
}
|
|
21486
21643
|
stop(params) {
|
|
21644
|
+
this.clearCameraRecoveryNotice();
|
|
21487
21645
|
this.recorder.stop(params);
|
|
21488
21646
|
this.recorderInsides.hidePause();
|
|
21489
21647
|
}
|
|
21490
21648
|
back(keepHidden = false, cb) {
|
|
21491
21649
|
this.options.logger.debug(`Visuals: back(keepHidden = ${keepHidden})`);
|
|
21650
|
+
this.cameraRecoveryFailed = false;
|
|
21492
21651
|
this.replay.hide();
|
|
21493
21652
|
this.notifier.hide();
|
|
21494
21653
|
if (keepHidden) {
|
|
@@ -21510,6 +21669,7 @@
|
|
|
21510
21669
|
if (!this.built) return;
|
|
21511
21670
|
const e = params?.e;
|
|
21512
21671
|
this.options.logger.debug(`Visuals: unload(${e ? string_pretty(e) : ""})`);
|
|
21672
|
+
this.cameraRecoveryFailed = false;
|
|
21513
21673
|
this.recorder.unload(params);
|
|
21514
21674
|
this.recorderInsides.unload();
|
|
21515
21675
|
this.replay.unload(params);
|
|
@@ -21523,13 +21683,31 @@
|
|
|
21523
21683
|
this.recorder.pause(params);
|
|
21524
21684
|
this.recorderInsides.showPause();
|
|
21525
21685
|
}
|
|
21686
|
+
clearCameraRecoveryNotice() {
|
|
21687
|
+
if (this.cameraRecoveryFailed) {
|
|
21688
|
+
this.notifier.hide();
|
|
21689
|
+
this.recorder.show();
|
|
21690
|
+
this.cameraRecoveryFailed = false;
|
|
21691
|
+
}
|
|
21692
|
+
}
|
|
21693
|
+
recoverCamera() {
|
|
21694
|
+
if (this.replay.isShown() || this.isNotifying() && !this.cameraRecoveryFailed) return Promise.resolve(false);
|
|
21695
|
+
this.clearCameraRecoveryNotice();
|
|
21696
|
+
return this.recorder.recoverCamera();
|
|
21697
|
+
}
|
|
21526
21698
|
resume() {
|
|
21527
|
-
|
|
21528
|
-
|
|
21529
|
-
|
|
21699
|
+
this.clearCameraRecoveryNotice();
|
|
21700
|
+
if (this.recorderInsides.isCountingDown()) {
|
|
21701
|
+
this.recorderInsides.resumeCountdown();
|
|
21702
|
+
this.recorderInsides.hidePause();
|
|
21703
|
+
} else {
|
|
21704
|
+
this.recorder.resume();
|
|
21705
|
+
if (!this.recorder.isPaused()) this.recorderInsides.hidePause();
|
|
21706
|
+
}
|
|
21530
21707
|
}
|
|
21531
21708
|
pauseOrResume() {
|
|
21532
|
-
if (this.
|
|
21709
|
+
if (this.cameraRecoveryFailed && this.recorder.isPaused()) this.resume();
|
|
21710
|
+
else if (this.isRecordable()) {
|
|
21533
21711
|
if (this.isRecording()) this.pause();
|
|
21534
21712
|
else if (this.recorder.isPaused()) this.resume();
|
|
21535
21713
|
else if (this.recorder.isReady()) this.recorder.record();
|
|
@@ -21772,10 +21950,10 @@
|
|
|
21772
21950
|
});
|
|
21773
21951
|
if (!playerOnly) this.stopListeningToVisibility = this.visibility.onChange((visible)=>{
|
|
21774
21952
|
if (this.built) if (visible) {
|
|
21775
|
-
if (isAutoPauseEnabled(this.options)
|
|
21953
|
+
if (isAutoPauseEnabled(this.options)) this.recoverCamera();
|
|
21776
21954
|
this.emit("VISIBLE");
|
|
21777
21955
|
} else {
|
|
21778
|
-
if (isAutoPauseEnabled(this.options)
|
|
21956
|
+
if (isAutoPauseEnabled(this.options)) this.suspend();
|
|
21779
21957
|
this.emit("INVISIBLE");
|
|
21780
21958
|
}
|
|
21781
21959
|
});
|
|
@@ -21963,6 +22141,13 @@
|
|
|
21963
22141
|
pause(params) {
|
|
21964
22142
|
this.visuals.pause(params);
|
|
21965
22143
|
}
|
|
22144
|
+
suspend() {
|
|
22145
|
+
if (this.built && (this.isCountingDown() || this.isRecording() || this.isPaused())) this.pause();
|
|
22146
|
+
}
|
|
22147
|
+
recoverCamera() {
|
|
22148
|
+
if (!this.built || this.hasError || this.submitted) return Promise.resolve(false);
|
|
22149
|
+
return this.visuals.recoverCamera();
|
|
22150
|
+
}
|
|
21966
22151
|
validate(event, force = false) {
|
|
21967
22152
|
let runValidation = true;
|
|
21968
22153
|
let valid = true;
|
|
@@ -22281,6 +22466,12 @@
|
|
|
22281
22466
|
record() {
|
|
22282
22467
|
this.container.record();
|
|
22283
22468
|
}
|
|
22469
|
+
pause() {
|
|
22470
|
+
this.container.suspend();
|
|
22471
|
+
}
|
|
22472
|
+
recoverCamera() {
|
|
22473
|
+
return this.container.recoverCamera();
|
|
22474
|
+
}
|
|
22284
22475
|
getLogLines() {
|
|
22285
22476
|
if (this.options.logger.getLines) return this.options.logger.getLines();
|
|
22286
22477
|
}
|