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/esm/client.d.ts
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -3620,7 +3620,7 @@ const constants = {
|
|
|
3620
3620
|
}
|
|
3621
3621
|
};
|
|
3622
3622
|
var package_namespaceObject = {
|
|
3623
|
-
rE: "16.0
|
|
3623
|
+
rE: "16.1.0"
|
|
3624
3624
|
};
|
|
3625
3625
|
function isAudioEnabled(options) {
|
|
3626
3626
|
return Boolean(options.audio.enabled);
|
|
@@ -5760,10 +5760,14 @@ class RecorderInsides extends util_Despot {
|
|
|
5760
5760
|
this.on("USER_MEDIA_READY", ()=>{
|
|
5761
5761
|
this.facingMode?.show();
|
|
5762
5762
|
});
|
|
5763
|
+
this.on("CAMERA_RECOVERING", ()=>{
|
|
5764
|
+
this.facingMode?.hide();
|
|
5765
|
+
});
|
|
5763
5766
|
this.on("RECORDING", ()=>{
|
|
5764
5767
|
this.startRecording();
|
|
5765
5768
|
});
|
|
5766
5769
|
this.on("RESUMING", ()=>{
|
|
5770
|
+
this.hidePause();
|
|
5767
5771
|
this.resumeRecording();
|
|
5768
5772
|
});
|
|
5769
5773
|
this.on("STOPPING", ()=>{
|
|
@@ -6333,9 +6337,19 @@ class AudioRecorder {
|
|
|
6333
6337
|
const float32Array = e.inputBuffer.getChannelData(0);
|
|
6334
6338
|
cb(new audio_sample(float32Array));
|
|
6335
6339
|
}
|
|
6340
|
+
disconnect() {
|
|
6341
|
+
if (this.scriptProcessor) {
|
|
6342
|
+
this.scriptProcessor.onaudioprocess = null;
|
|
6343
|
+
this.scriptProcessor.disconnect();
|
|
6344
|
+
}
|
|
6345
|
+
this.audioInput?.disconnect();
|
|
6346
|
+
this.volume?.disconnect();
|
|
6347
|
+
}
|
|
6336
6348
|
init(localMediaStream) {
|
|
6337
6349
|
this.options.logger.debug("AudioRecorder: init()");
|
|
6350
|
+
this.disconnect();
|
|
6338
6351
|
const volume = this.getAudioContext().createGain();
|
|
6352
|
+
this.volume = volume;
|
|
6339
6353
|
try {
|
|
6340
6354
|
this.audioInput = this.getAudioContext().createMediaStreamSource(localMediaStream);
|
|
6341
6355
|
} catch (exc) {
|
|
@@ -6367,10 +6381,13 @@ class AudioRecorder {
|
|
|
6367
6381
|
this.onAudioProcess(e, cb);
|
|
6368
6382
|
};
|
|
6369
6383
|
}
|
|
6384
|
+
async resume() {
|
|
6385
|
+
const context = this.getAudioContext();
|
|
6386
|
+
if ("running" !== context.state) await context.resume();
|
|
6387
|
+
}
|
|
6370
6388
|
stop() {
|
|
6371
6389
|
this.options.logger.debug("AudioRecorder: stop()");
|
|
6372
|
-
|
|
6373
|
-
if (this.audioInput) this.audioInput.disconnect();
|
|
6390
|
+
this.disconnect();
|
|
6374
6391
|
if (this.hasAudioContext()) this.getAudioContext().close().then(()=>{
|
|
6375
6392
|
this.options.logger.debug("AudioRecorder: audio context is closed");
|
|
6376
6393
|
this.vcAudioContext = void 0;
|
|
@@ -6389,6 +6406,7 @@ class AudioRecorder {
|
|
|
6389
6406
|
constructor(userMedia, options){
|
|
6390
6407
|
AudioRecorder_define_property(this, "scriptProcessor", void 0);
|
|
6391
6408
|
AudioRecorder_define_property(this, "audioInput", void 0);
|
|
6409
|
+
AudioRecorder_define_property(this, "volume", void 0);
|
|
6392
6410
|
AudioRecorder_define_property(this, "vcAudioContext", void 0);
|
|
6393
6411
|
AudioRecorder_define_property(this, "userMedia", void 0);
|
|
6394
6412
|
AudioRecorder_define_property(this, "options", void 0);
|
|
@@ -6448,6 +6466,16 @@ class UserMedia extends util_Despot {
|
|
|
6448
6466
|
this.currentVisualStream = void 0;
|
|
6449
6467
|
}
|
|
6450
6468
|
}
|
|
6469
|
+
async restorePlayback() {
|
|
6470
|
+
if (!this.rawVisualUserMedia) throw new Error("No camera preview is available.");
|
|
6471
|
+
await this.rawVisualUserMedia.play();
|
|
6472
|
+
await this.audioRecorder?.resume();
|
|
6473
|
+
}
|
|
6474
|
+
hasLiveStream() {
|
|
6475
|
+
const videoReady = this.currentVisualStream?.getVideoTracks().some((track)=>"live" === track.readyState && track.enabled && !track.muted);
|
|
6476
|
+
const audioReady = !isAudioEnabled(this.options) || this.currentVisualStream?.getAudioTracks().some((track)=>"live" === track.readyState && track.enabled && !track.muted);
|
|
6477
|
+
return Boolean(this.currentVisualStream?.active && videoReady && audioReady);
|
|
6478
|
+
}
|
|
6451
6479
|
hasEnded() {
|
|
6452
6480
|
if (this.rawVisualUserMedia?.ended) return this.rawVisualUserMedia.ended;
|
|
6453
6481
|
return !this.currentVisualStream?.active;
|
|
@@ -6462,6 +6490,7 @@ class UserMedia extends util_Despot {
|
|
|
6462
6490
|
}
|
|
6463
6491
|
unloadRemainingEventListeners() {
|
|
6464
6492
|
this.options.logger.debug("UserMedia: unloadRemainingEventListeners()");
|
|
6493
|
+
this.clearInitializationListeners?.();
|
|
6465
6494
|
mediaEvents.forEach((eventName)=>{
|
|
6466
6495
|
this.rawVisualUserMedia?.removeEventListener(eventName, this.outputEvent);
|
|
6467
6496
|
});
|
|
@@ -6471,11 +6500,13 @@ class UserMedia extends util_Despot {
|
|
|
6471
6500
|
this.removeListener("SENDING_FIRST_FRAME");
|
|
6472
6501
|
this.audioRecorder?.record(audioCallback);
|
|
6473
6502
|
}
|
|
6474
|
-
init(localMediaStream, videoCallback, audioCallback, endedEarlyCallback,
|
|
6503
|
+
init(localMediaStream, videoCallback, audioCallback, endedEarlyCallback, params) {
|
|
6504
|
+
this.clearInitializationListeners?.();
|
|
6475
6505
|
this.stop(localMediaStream, {
|
|
6476
6506
|
aboutToInitialize: true,
|
|
6477
|
-
switchingFacingMode
|
|
6507
|
+
preserveRecordingState: Boolean(params?.switchingFacingMode || params?.recovering)
|
|
6478
6508
|
});
|
|
6509
|
+
const initializationId = ++this.initializationId;
|
|
6479
6510
|
this.onPlayReached = false;
|
|
6480
6511
|
this.onLoadedMetaDataReached = false;
|
|
6481
6512
|
this.playingPromiseReached = false;
|
|
@@ -6488,18 +6519,25 @@ class UserMedia extends util_Despot {
|
|
|
6488
6519
|
this.rawVisualUserMedia?.removeEventListener("play", onPlay);
|
|
6489
6520
|
this.rawVisualUserMedia?.removeEventListener("loadedmetadata", onLoadedMetaData);
|
|
6490
6521
|
};
|
|
6522
|
+
this.clearInitializationListeners = ()=>{
|
|
6523
|
+
this.rawVisualUserMedia?.removeEventListener("play", onPlay);
|
|
6524
|
+
this.rawVisualUserMedia?.removeEventListener("loadedmetadata", onLoadedMetaData);
|
|
6525
|
+
this.clearInitializationListeners = void 0;
|
|
6526
|
+
};
|
|
6491
6527
|
const play = ()=>{
|
|
6492
6528
|
try {
|
|
6493
6529
|
this.rawVisualUserMedia?.load();
|
|
6494
6530
|
if (this.rawVisualUserMedia?.paused) {
|
|
6495
6531
|
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)}`);
|
|
6496
6532
|
this.rawVisualUserMedia.play().then(()=>{
|
|
6533
|
+
if (initializationId !== this.initializationId) return;
|
|
6497
6534
|
if (!this.playingPromiseReached) {
|
|
6498
6535
|
this.options.logger.debug("UserMedia: play promise successful. Playing now.");
|
|
6499
6536
|
this.playingPromiseReached = true;
|
|
6500
6537
|
}
|
|
6501
6538
|
}).catch((exc)=>{
|
|
6502
|
-
if (
|
|
6539
|
+
if (initializationId !== this.initializationId) return;
|
|
6540
|
+
if (exc instanceof Error && !params?.recovering) this.options.logger.warn(`Caught pending user media promise exception: ${exc.toString()}`);
|
|
6503
6541
|
else {
|
|
6504
6542
|
unloadAllEventListeners();
|
|
6505
6543
|
endedEarlyCallback(error_createError({
|
|
@@ -6520,16 +6558,28 @@ class UserMedia extends util_Despot {
|
|
|
6520
6558
|
this.options.logger.debug(`UserMedia: fireCallbacks(readyState=${readyState}, onPlayReached=${this.onPlayReached}, onLoadedMetaDataReached=${this.onLoadedMetaDataReached})`);
|
|
6521
6559
|
if (this.onPlayReached && this.onLoadedMetaDataReached) if (this.audioRecorder) try {
|
|
6522
6560
|
this.audioRecorder.init(localMediaStream);
|
|
6523
|
-
|
|
6524
|
-
this.
|
|
6525
|
-
|
|
6526
|
-
|
|
6561
|
+
const onAudioReady = ()=>{
|
|
6562
|
+
if (initializationId !== this.initializationId || this.currentVisualStream !== localMediaStream) return;
|
|
6563
|
+
if (this.recording) this.audioRecord(audioCallback);
|
|
6564
|
+
else this.on("SENDING_FIRST_FRAME", ()=>{
|
|
6565
|
+
this.audioRecord(audioCallback);
|
|
6566
|
+
});
|
|
6567
|
+
this.clearInitializationListeners?.();
|
|
6568
|
+
videoCallback();
|
|
6569
|
+
};
|
|
6570
|
+
if (params?.recovering) this.audioRecorder.resume().then(onAudioReady).catch(endedEarlyCallback);
|
|
6571
|
+
else onAudioReady();
|
|
6527
6572
|
} catch (exc) {
|
|
6528
6573
|
unloadAllEventListeners();
|
|
6529
|
-
this.stop(
|
|
6574
|
+
this.stop(void 0, {
|
|
6575
|
+
preserveRecordingState: Boolean(params?.recovering)
|
|
6576
|
+
});
|
|
6530
6577
|
endedEarlyCallback(exc);
|
|
6531
6578
|
}
|
|
6532
|
-
else
|
|
6579
|
+
else {
|
|
6580
|
+
this.clearInitializationListeners?.();
|
|
6581
|
+
videoCallback();
|
|
6582
|
+
}
|
|
6533
6583
|
};
|
|
6534
6584
|
const onPlay = ()=>{
|
|
6535
6585
|
try {
|
|
@@ -6599,9 +6649,8 @@ class UserMedia extends util_Despot {
|
|
|
6599
6649
|
this.setVisualStream(localMediaStream);
|
|
6600
6650
|
play();
|
|
6601
6651
|
} catch (exc) {
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
});
|
|
6652
|
+
unloadAllEventListeners();
|
|
6653
|
+
endedEarlyCallback(exc);
|
|
6605
6654
|
}
|
|
6606
6655
|
}
|
|
6607
6656
|
getVideoTrackLabel() {
|
|
@@ -6614,6 +6663,8 @@ class UserMedia extends util_Despot {
|
|
|
6614
6663
|
try {
|
|
6615
6664
|
let chosenStream = visualStream;
|
|
6616
6665
|
if (!params?.aboutToInitialize) {
|
|
6666
|
+
this.initializationId++;
|
|
6667
|
+
this.clearInitializationListeners?.();
|
|
6617
6668
|
chosenStream ??= this.currentVisualStream;
|
|
6618
6669
|
const tracks = chosenStream?.getTracks();
|
|
6619
6670
|
if (tracks) tracks.forEach((track)=>{
|
|
@@ -6623,7 +6674,7 @@ class UserMedia extends util_Despot {
|
|
|
6623
6674
|
this.audioRecorder?.stop();
|
|
6624
6675
|
this.audioRecorder = void 0;
|
|
6625
6676
|
}
|
|
6626
|
-
if (!params?.
|
|
6677
|
+
if (!params?.preserveRecordingState) this.paused = this.recording = false;
|
|
6627
6678
|
} catch (exc) {
|
|
6628
6679
|
this.emit("ERROR", {
|
|
6629
6680
|
exc
|
|
@@ -6710,7 +6761,7 @@ class UserMedia extends util_Despot {
|
|
|
6710
6761
|
};
|
|
6711
6762
|
}
|
|
6712
6763
|
constructor(recorder, options){
|
|
6713
|
-
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, "outputEvent", (e)=>{
|
|
6764
|
+
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)=>{
|
|
6714
6765
|
this.logEvent(e.type, {
|
|
6715
6766
|
readyState: this.rawVisualUserMedia?.readyState
|
|
6716
6767
|
});
|
|
@@ -6971,7 +7022,9 @@ class Recorder extends util_Despot {
|
|
|
6971
7022
|
this.pingInterval = void 0;
|
|
6972
7023
|
}
|
|
6973
7024
|
onAudioSample(audioSample) {
|
|
6974
|
-
if (this.recordingTransportFailed) return;
|
|
7025
|
+
if (this.recordingTransportFailed || this.cameraRecovery) return;
|
|
7026
|
+
const sampleRate = this.userMedia?.getAudioSampleRate();
|
|
7027
|
+
if (sampleRate && sampleRate > 0) this.recordingAudioSampleRate ??= sampleRate;
|
|
6975
7028
|
this.samplesCount++;
|
|
6976
7029
|
this.mediaTransmissionStarted = true;
|
|
6977
7030
|
const audioBuffer = audioSample.toBuffer();
|
|
@@ -6984,19 +7037,26 @@ class Recorder extends util_Despot {
|
|
|
6984
7037
|
try {
|
|
6985
7038
|
this.options.logger.debug(`Recorder: onUserMediaReady(${params ? string_pretty(params) : ""})`);
|
|
6986
7039
|
const switchingFacingMode = params?.switchingFacingMode;
|
|
7040
|
+
if (params?.recovering) {
|
|
7041
|
+
if (!this.userMedia?.hasLiveStream()) return void this.failCameraRecovery(new Error("The restored camera has no live tracks."));
|
|
7042
|
+
if (void 0 !== this.recordingAudioSampleRate && this.userMedia.getAudioSampleRate() !== this.recordingAudioSampleRate) return void this.failCameraRecovery(new Error("The audio sample rate changed during recovery."));
|
|
7043
|
+
}
|
|
6987
7044
|
this.userMediaLoading = this.blocking = this.unloaded = this.submitting = false;
|
|
6988
7045
|
this.userMediaLoaded = true;
|
|
6989
7046
|
this.clearUserMediaTimeout();
|
|
6990
|
-
if (!switchingFacingMode) this.loop = this.createLoop();
|
|
7047
|
+
if (!switchingFacingMode && !params?.recovering) this.loop = this.createLoop();
|
|
6991
7048
|
this.show();
|
|
6992
7049
|
if (params?.recordWhenReady) this.record();
|
|
6993
7050
|
this.emit("USER_MEDIA_READY", {
|
|
6994
7051
|
switchingFacingMode: params?.switchingFacingMode,
|
|
7052
|
+
recovering: params?.recovering,
|
|
6995
7053
|
paused: this.isPaused(),
|
|
6996
7054
|
recordWhenReady: params?.recordWhenReady
|
|
6997
7055
|
});
|
|
7056
|
+
if (params?.recovering) this.finishCameraRecovery(true);
|
|
6998
7057
|
} catch (exc) {
|
|
6999
|
-
this.
|
|
7058
|
+
if (params?.recovering) this.failCameraRecovery(exc);
|
|
7059
|
+
else this.emit("ERROR", {
|
|
7000
7060
|
exc
|
|
7001
7061
|
});
|
|
7002
7062
|
}
|
|
@@ -7367,6 +7427,7 @@ class Recorder extends util_Despot {
|
|
|
7367
7427
|
return this.blocking;
|
|
7368
7428
|
}
|
|
7369
7429
|
userMediaErrorCallback(err, usedConstraints) {
|
|
7430
|
+
if (this.cameraRecovery) return void this.failCameraRecovery(err);
|
|
7370
7431
|
if (this.unloaded) return void this.options.logger.debug(`Recorder: already unloaded. Not going to throw error ${string_pretty(err)}`);
|
|
7371
7432
|
this.userMediaLoading = false;
|
|
7372
7433
|
this.clearUserMediaTimeout();
|
|
@@ -7398,7 +7459,7 @@ class Recorder extends util_Despot {
|
|
|
7398
7459
|
});
|
|
7399
7460
|
}
|
|
7400
7461
|
}
|
|
7401
|
-
getUserMediaCallback(localStream, params) {
|
|
7462
|
+
getUserMediaCallback(localStream, params, requestId = this.mediaRequestId) {
|
|
7402
7463
|
if (!this.userMedia) {
|
|
7403
7464
|
localStream.getTracks().forEach((track)=>{
|
|
7404
7465
|
track.stop();
|
|
@@ -7411,20 +7472,20 @@ class Recorder extends util_Despot {
|
|
|
7411
7472
|
this.options.logger.debug(`Recorder: getUserMediaCallback(${params ? string_pretty(params) : ""})`);
|
|
7412
7473
|
if (this.showUserMedia()) try {
|
|
7413
7474
|
this.userMedia.init(localStream, ()=>{
|
|
7414
|
-
if (!this.unloaded) this.onUserMediaReady(params);
|
|
7475
|
+
if (!this.unloaded && requestId === this.mediaRequestId) this.onUserMediaReady(params);
|
|
7415
7476
|
}, this.onAudioSample.bind(this), (err)=>{
|
|
7416
|
-
if (!this.unloaded) this.userMediaErrorCallback(err, {
|
|
7477
|
+
if (!this.unloaded && requestId === this.mediaRequestId) this.userMediaErrorCallback(err, {
|
|
7417
7478
|
audio: isAudioEnabled(this.options)
|
|
7418
7479
|
});
|
|
7419
|
-
}, params
|
|
7480
|
+
}, params);
|
|
7420
7481
|
} catch (exc) {
|
|
7421
7482
|
localStream.getTracks().forEach((track)=>{
|
|
7422
7483
|
track.stop();
|
|
7423
7484
|
});
|
|
7424
7485
|
this.userMediaLoading = false;
|
|
7425
7486
|
this.clearUserMediaTimeout();
|
|
7426
|
-
this.
|
|
7427
|
-
|
|
7487
|
+
this.userMediaErrorCallback(exc, {
|
|
7488
|
+
audio: isAudioEnabled(this.options)
|
|
7428
7489
|
});
|
|
7429
7490
|
}
|
|
7430
7491
|
else {
|
|
@@ -7433,12 +7494,14 @@ class Recorder extends util_Despot {
|
|
|
7433
7494
|
});
|
|
7434
7495
|
this.userMediaLoading = false;
|
|
7435
7496
|
this.clearUserMediaTimeout();
|
|
7497
|
+
this.cancelCameraRecovery();
|
|
7436
7498
|
}
|
|
7437
7499
|
}
|
|
7438
7500
|
loadGenuineUserMedia(params) {
|
|
7439
7501
|
this.options.logger.debug(`Recorder: loadGenuineUserMedia(${params ? string_pretty(params) : ""})`);
|
|
7440
7502
|
this.emit("ASKING_WEBCAM_PERMISSION");
|
|
7441
7503
|
this.userMediaLoading = true;
|
|
7504
|
+
const requestId = ++this.mediaRequestId;
|
|
7442
7505
|
const constraints = {
|
|
7443
7506
|
video: {
|
|
7444
7507
|
frameRate: {
|
|
@@ -7452,18 +7515,18 @@ class Recorder extends util_Despot {
|
|
|
7452
7515
|
this.options.logger.debug(string_summarize("Recorder: available webcam constraints are:", navigator.mediaDevices.getSupportedConstraints()));
|
|
7453
7516
|
const streamPromise = navigator.mediaDevices.getUserMedia(constraints);
|
|
7454
7517
|
streamPromise.then((localStream)=>{
|
|
7455
|
-
if (this.unloaded) return void localStream.getTracks().forEach((track)=>{
|
|
7518
|
+
if (this.unloaded || requestId !== this.mediaRequestId) return void localStream.getTracks().forEach((track)=>{
|
|
7456
7519
|
track.stop();
|
|
7457
7520
|
});
|
|
7458
|
-
this.getUserMediaCallback(localStream, params);
|
|
7521
|
+
this.getUserMediaCallback(localStream, params, requestId);
|
|
7459
7522
|
}).catch((reason)=>{
|
|
7460
|
-
if (!this.unloaded) this.userMediaErrorCallback(reason, constraints);
|
|
7523
|
+
if (!this.unloaded && requestId === this.mediaRequestId) this.userMediaErrorCallback(reason, constraints);
|
|
7461
7524
|
});
|
|
7462
7525
|
}
|
|
7463
7526
|
configureVideoConstraints(constraints, params) {
|
|
7464
7527
|
const videoConstraints = "object" == typeof constraints.video ? constraints.video : void 0;
|
|
7465
7528
|
if (!videoConstraints) return;
|
|
7466
|
-
if (params?.switchingFacingMode) videoConstraints.facingMode = params.switchingFacingMode;
|
|
7529
|
+
if (params?.switchingFacingMode || params?.recovering) videoConstraints.facingMode = params.switchingFacingMode || this.facingMode;
|
|
7467
7530
|
if (this.options.video.width) videoConstraints.width = {
|
|
7468
7531
|
ideal: this.options.video.width
|
|
7469
7532
|
};
|
|
@@ -7491,8 +7554,8 @@ class Recorder extends util_Despot {
|
|
|
7491
7554
|
if (!this.userMediaLoaded) {
|
|
7492
7555
|
this.userMediaLoading = false;
|
|
7493
7556
|
const err = util_getBrowser(this.options).getNoAccessIssue();
|
|
7494
|
-
this.
|
|
7495
|
-
|
|
7557
|
+
this.userMediaErrorCallback(err, {
|
|
7558
|
+
audio: isAudioEnabled(this.options)
|
|
7496
7559
|
});
|
|
7497
7560
|
}
|
|
7498
7561
|
}, this.options.timeouts.userMedia);
|
|
@@ -7502,6 +7565,7 @@ class Recorder extends util_Despot {
|
|
|
7502
7565
|
this.clearUserMediaTimeout();
|
|
7503
7566
|
this.options.logger.debug("Recorder: failed to load genuine user media");
|
|
7504
7567
|
this.userMediaLoading = false;
|
|
7568
|
+
if (this.cameraRecovery) return void this.failCameraRecovery(exc);
|
|
7505
7569
|
const errorListeners = this.getListeners("ERROR");
|
|
7506
7570
|
if (errorListeners?.length) this.emit("ERROR", {
|
|
7507
7571
|
exc
|
|
@@ -7625,9 +7689,10 @@ class Recorder extends util_Despot {
|
|
|
7625
7689
|
return this.recordingStats;
|
|
7626
7690
|
}
|
|
7627
7691
|
getAudioSampleRate() {
|
|
7628
|
-
return this.userMedia?.getAudioSampleRate();
|
|
7692
|
+
return this.recordingAudioSampleRate ?? this.userMedia?.getAudioSampleRate();
|
|
7629
7693
|
}
|
|
7630
7694
|
stop(params) {
|
|
7695
|
+
this.cancelCameraRecovery();
|
|
7631
7696
|
if (!this.userMedia) throw new Error("No user media defined, unable to stop");
|
|
7632
7697
|
this.options.logger.debug(`Recorder: stop(${params ? string_pretty(params) : ""})`);
|
|
7633
7698
|
this.recordingActive = false;
|
|
@@ -7653,7 +7718,7 @@ class Recorder extends util_Despot {
|
|
|
7653
7718
|
if (this.userMedia) this.recordingStats.videoTrackLabel = this.userMedia.getVideoTrackLabel();
|
|
7654
7719
|
if (isAudioEnabled(this.options) && this.userMedia) {
|
|
7655
7720
|
this.recordingStats.samplesCount = this.samplesCount;
|
|
7656
|
-
this.recordingStats.sampleRate = this.userMedia.getAudioSampleRate();
|
|
7721
|
+
this.recordingStats.sampleRate = this.recordingAudioSampleRate ?? this.userMedia.getAudioSampleRate();
|
|
7657
7722
|
}
|
|
7658
7723
|
this.writeCommand("stop", this.recordingStats, ()=>{
|
|
7659
7724
|
this.emit("STOPPED", {
|
|
@@ -7708,6 +7773,7 @@ class Recorder extends util_Despot {
|
|
|
7708
7773
|
this.built = this.connecting = this.connected = false;
|
|
7709
7774
|
}
|
|
7710
7775
|
reset() {
|
|
7776
|
+
this.cancelCameraRecovery();
|
|
7711
7777
|
if (!this.unloaded) {
|
|
7712
7778
|
this.options.logger.debug("Recorder: reset()");
|
|
7713
7779
|
this.emit("RESETTING");
|
|
@@ -7735,7 +7801,70 @@ class Recorder extends util_Despot {
|
|
|
7735
7801
|
isReady() {
|
|
7736
7802
|
return this.userMedia?.isReady();
|
|
7737
7803
|
}
|
|
7804
|
+
finishCameraRecovery(restored) {
|
|
7805
|
+
this.clearUserMediaTimeout();
|
|
7806
|
+
const resolve = this.resolveCameraRecovery;
|
|
7807
|
+
const resumeRequested = restored && this.resumeAfterCameraRecovery;
|
|
7808
|
+
this.cameraRecovery = void 0;
|
|
7809
|
+
this.resolveCameraRecovery = void 0;
|
|
7810
|
+
this.resumeAfterCameraRecovery = false;
|
|
7811
|
+
resolve?.(restored);
|
|
7812
|
+
if (resumeRequested && this.isPaused()) this.resume();
|
|
7813
|
+
}
|
|
7814
|
+
cancelCameraRecovery() {
|
|
7815
|
+
if (!this.cameraRecovery) return;
|
|
7816
|
+
this.mediaRequestId++;
|
|
7817
|
+
this.userMediaLoading = false;
|
|
7818
|
+
this.userMediaLoaded = false;
|
|
7819
|
+
this.clearUserMediaTimeout();
|
|
7820
|
+
this.userMedia?.stop(void 0, {
|
|
7821
|
+
preserveRecordingState: true
|
|
7822
|
+
});
|
|
7823
|
+
this.finishCameraRecovery(false);
|
|
7824
|
+
}
|
|
7825
|
+
failCameraRecovery(exc) {
|
|
7826
|
+
this.cancelCameraRecovery();
|
|
7827
|
+
const err = error_createError({
|
|
7828
|
+
message: "Camera recovery failed",
|
|
7829
|
+
explanation: "Your recording is still paused. Check camera permissions, then try Resume again or stop to keep the recorded part.",
|
|
7830
|
+
exc,
|
|
7831
|
+
options: this.options
|
|
7832
|
+
});
|
|
7833
|
+
this.emit("CAMERA_RECOVERY_FAILED", {
|
|
7834
|
+
err
|
|
7835
|
+
});
|
|
7836
|
+
}
|
|
7837
|
+
recoverCamera() {
|
|
7838
|
+
if (this.cameraRecovery) return this.cameraRecovery;
|
|
7839
|
+
if (!this.built || this.unloaded || !this.userMedia || this.userMediaLoading || this.submitting || this.key || void 0 !== this.stopTimeout || this.recordingTransportFailed) return Promise.resolve(false);
|
|
7840
|
+
const liveStream = this.userMedia.hasLiveStream();
|
|
7841
|
+
if (liveStream && this.isRecording()) return Promise.resolve(true);
|
|
7842
|
+
if (!liveStream && this.recordingActive && !this.isPaused()) this.pause();
|
|
7843
|
+
const recovery = new Promise((resolve)=>{
|
|
7844
|
+
this.resolveCameraRecovery = resolve;
|
|
7845
|
+
});
|
|
7846
|
+
this.cameraRecovery = recovery;
|
|
7847
|
+
this.emit("CAMERA_RECOVERING");
|
|
7848
|
+
if (liveStream) {
|
|
7849
|
+
this.userMediaTimeout = window.setTimeout(()=>{
|
|
7850
|
+
this.failCameraRecovery(new Error("Camera playback recovery timed out."));
|
|
7851
|
+
}, this.options.timeouts.userMedia);
|
|
7852
|
+
this.userMedia.restorePlayback().then(()=>{
|
|
7853
|
+
if (this.cameraRecovery === recovery) this.finishCameraRecovery(true);
|
|
7854
|
+
}).catch((exc)=>{
|
|
7855
|
+
if (this.cameraRecovery === recovery) this.failCameraRecovery(exc);
|
|
7856
|
+
});
|
|
7857
|
+
} else {
|
|
7858
|
+
this.userMediaLoaded = false;
|
|
7859
|
+
this.loadUserMedia({
|
|
7860
|
+
recovering: true
|
|
7861
|
+
});
|
|
7862
|
+
}
|
|
7863
|
+
return recovery;
|
|
7864
|
+
}
|
|
7738
7865
|
pause(params) {
|
|
7866
|
+
this.cancelCameraRecovery();
|
|
7867
|
+
this.resumeAfterDrain = false;
|
|
7739
7868
|
if (params) this.options.logger.debug(`pause() at frame ${this.framesCount} with ${string_pretty(params)}`);
|
|
7740
7869
|
else this.options.logger.debug(`pause() at frame ${this.framesCount}`);
|
|
7741
7870
|
this.userMedia?.pause();
|
|
@@ -7744,10 +7873,15 @@ class Recorder extends util_Despot {
|
|
|
7744
7873
|
this.sendPings();
|
|
7745
7874
|
}
|
|
7746
7875
|
resume() {
|
|
7876
|
+
if (this.cameraRecovery || !this.userMedia?.hasLiveStream()) {
|
|
7877
|
+
this.recoverCamera();
|
|
7878
|
+
this.resumeAfterCameraRecovery = Boolean(this.cameraRecovery);
|
|
7879
|
+
return;
|
|
7880
|
+
}
|
|
7747
7881
|
this.options.logger.debug(`Recorder: resume() with frame ${this.framesCount}`);
|
|
7748
7882
|
this.stopPings();
|
|
7749
7883
|
this.emit("RESUMING");
|
|
7750
|
-
this.userMedia
|
|
7884
|
+
this.userMedia.resume();
|
|
7751
7885
|
if (this.streamBackpressured) this.resumeAfterDrain = true;
|
|
7752
7886
|
else this.loop.start();
|
|
7753
7887
|
}
|
|
@@ -7802,7 +7936,7 @@ class Recorder extends util_Despot {
|
|
|
7802
7936
|
return newLoop;
|
|
7803
7937
|
}
|
|
7804
7938
|
record() {
|
|
7805
|
-
if (this.unloaded) return;
|
|
7939
|
+
if (this.unloaded || this.cameraRecovery) return;
|
|
7806
7940
|
if (!this.connected) {
|
|
7807
7941
|
this.options.logger.debug("Recorder: reconnecting before recording …");
|
|
7808
7942
|
this.initSocket(()=>{
|
|
@@ -7875,6 +8009,7 @@ class Recorder extends util_Despot {
|
|
|
7875
8009
|
this.recordingActive = true;
|
|
7876
8010
|
this.recordingTransportFailed = false;
|
|
7877
8011
|
this.mediaTransmissionStarted = false;
|
|
8012
|
+
this.recordingAudioSampleRate = void 0;
|
|
7878
8013
|
this.userMedia.record();
|
|
7879
8014
|
this.emit("RECORDING", {
|
|
7880
8015
|
framesCount: this.framesCount
|
|
@@ -7936,7 +8071,7 @@ class Recorder extends util_Despot {
|
|
|
7936
8071
|
}
|
|
7937
8072
|
}
|
|
7938
8073
|
switchFacingMode() {
|
|
7939
|
-
if (!util_getBrowser(this.options).isMobile()) return;
|
|
8074
|
+
if (this.cameraRecovery || !util_getBrowser(this.options).isMobile()) return;
|
|
7940
8075
|
if ("user" === this.facingMode) this.facingMode = "environment";
|
|
7941
8076
|
else if ("environment" === this.facingMode) this.facingMode = "user";
|
|
7942
8077
|
else this.options.logger.warn(`Recorder: unsupported facing mode ${string_pretty(this.facingMode)}`);
|
|
@@ -7947,12 +8082,14 @@ class Recorder extends util_Despot {
|
|
|
7947
8082
|
initEvents() {
|
|
7948
8083
|
this.options.logger.debug("Recorder: initEvents()");
|
|
7949
8084
|
this.on("SUBMITTING", ()=>{
|
|
8085
|
+
this.cancelCameraRecovery();
|
|
7950
8086
|
this.submitting = true;
|
|
7951
8087
|
});
|
|
7952
8088
|
this.on("SUBMITTED", ()=>{
|
|
7953
8089
|
this.submitting = false;
|
|
7954
8090
|
});
|
|
7955
8091
|
this.on("BLOCKING", ()=>{
|
|
8092
|
+
this.cancelCameraRecovery();
|
|
7956
8093
|
this.blocking = true;
|
|
7957
8094
|
this.clearUserMediaTimeout();
|
|
7958
8095
|
});
|
|
@@ -8126,7 +8263,7 @@ class Recorder extends util_Despot {
|
|
|
8126
8263
|
return this.userMediaLoaded;
|
|
8127
8264
|
}
|
|
8128
8265
|
constructor(visuals, replay, options){
|
|
8129
|
-
super("Recorder", options), recorder_define_property(this, "visuals", void 0), recorder_define_property(this, "replay", void 0), recorder_define_property(this, "pendingWrites", new boundedWriteQueue()), recorder_define_property(this, "loop", void 0), recorder_define_property(this, "originalAnimationFrameObject", void 0), recorder_define_property(this, "samplesCount", 0), recorder_define_property(this, "framesCount", 0), recorder_define_property(this, "recordingStats", void 0), recorder_define_property(this, "confirmedFrameNumber", 0), recorder_define_property(this, "confirmedSampleNumber", 0), recorder_define_property(this, "recorderElement", void 0), recorder_define_property(this, "userMedia", void 0), recorder_define_property(this, "userMediaTimeout", void 0), recorder_define_property(this, "retryTimeout", void 0), recorder_define_property(this, "reconnectTimeout", void 0), recorder_define_property(this, "connectionTimeout", void 0), recorder_define_property(this, "backpressureTimeout", void 0), recorder_define_property(this, "stopTimeout", void 0), recorder_define_property(this, "frameProgress", void 0), recorder_define_property(this, "sampleProgress", void 0), recorder_define_property(this, "canvas", void 0), recorder_define_property(this, "recordingDimensions", void 0), recorder_define_property(this, "ctx", void 0), recorder_define_property(this, "userMediaLoaded", void 0), recorder_define_property(this, "userMediaLoading", false), recorder_define_property(this, "submitting", false), recorder_define_property(this, "unloaded", void 0), recorder_define_property(this, "stopTime", void 0), recorder_define_property(this, "stream", void 0), recorder_define_property(this, "streamBackpressured", false), recorder_define_property(this, "resumeAfterDrain", false), recorder_define_property(this, "mediaTransmissionStarted", false), recorder_define_property(this, "recordingActive", false), recorder_define_property(this, "recordingTransportFailed", false), recorder_define_property(this, "connecting", false), recorder_define_property(this, "connected", false), recorder_define_property(this, "connectionFailed", false), recorder_define_property(this, "reconnecting", false), recorder_define_property(this, "reconnectAttempts", 0), recorder_define_property(this, "blocking", false), recorder_define_property(this, "built", false), recorder_define_property(this, "key", void 0), recorder_define_property(this, "waitingTime", void 0), recorder_define_property(this, "connectingStartedAt", void 0), recorder_define_property(this, "lastCloseEvent", void 0), recorder_define_property(this, "lastSocketError", void 0), recorder_define_property(this, "pingInterval", void 0), recorder_define_property(this, "frame", void 0), recorder_define_property(this, "recordingBuffer", void 0), recorder_define_property(this, "facingMode", void 0);
|
|
8266
|
+
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);
|
|
8130
8267
|
this.visuals = visuals;
|
|
8131
8268
|
this.replay = replay;
|
|
8132
8269
|
this.facingMode = options.video.facingMode;
|
|
@@ -8419,6 +8556,17 @@ class Visuals extends util_Despot {
|
|
|
8419
8556
|
this.endWaiting();
|
|
8420
8557
|
this.container.enableForm(false);
|
|
8421
8558
|
});
|
|
8559
|
+
this.on("CAMERA_RECOVERING", ()=>{
|
|
8560
|
+
this.clearCameraRecoveryNotice();
|
|
8561
|
+
});
|
|
8562
|
+
this.on("CAMERA_RECOVERY_FAILED", ({ err })=>{
|
|
8563
|
+
this.cameraRecoveryFailed = true;
|
|
8564
|
+
this.options.logger.warn(err);
|
|
8565
|
+
if (this.options.displayErrors) this.notifier.notify(err.message, err.explanation, {
|
|
8566
|
+
problem: true
|
|
8567
|
+
});
|
|
8568
|
+
this.endWaiting();
|
|
8569
|
+
});
|
|
8422
8570
|
this.on("PREVIEW", ()=>{
|
|
8423
8571
|
this.endWaiting();
|
|
8424
8572
|
});
|
|
@@ -8497,6 +8645,7 @@ class Visuals extends util_Despot {
|
|
|
8497
8645
|
child.remove();
|
|
8498
8646
|
}
|
|
8499
8647
|
reset() {
|
|
8648
|
+
this.clearCameraRecoveryNotice();
|
|
8500
8649
|
this.endWaiting();
|
|
8501
8650
|
this.recorder.reset();
|
|
8502
8651
|
}
|
|
@@ -8507,11 +8656,13 @@ class Visuals extends util_Despot {
|
|
|
8507
8656
|
this.container.endWaiting();
|
|
8508
8657
|
}
|
|
8509
8658
|
stop(params) {
|
|
8659
|
+
this.clearCameraRecoveryNotice();
|
|
8510
8660
|
this.recorder.stop(params);
|
|
8511
8661
|
this.recorderInsides.hidePause();
|
|
8512
8662
|
}
|
|
8513
8663
|
back(keepHidden = false, cb) {
|
|
8514
8664
|
this.options.logger.debug(`Visuals: back(keepHidden = ${keepHidden})`);
|
|
8665
|
+
this.cameraRecoveryFailed = false;
|
|
8515
8666
|
this.replay.hide();
|
|
8516
8667
|
this.notifier.hide();
|
|
8517
8668
|
if (keepHidden) {
|
|
@@ -8533,6 +8684,7 @@ class Visuals extends util_Despot {
|
|
|
8533
8684
|
if (!this.built) return;
|
|
8534
8685
|
const e = params?.e;
|
|
8535
8686
|
this.options.logger.debug(`Visuals: unload(${e ? string_pretty(e) : ""})`);
|
|
8687
|
+
this.cameraRecoveryFailed = false;
|
|
8536
8688
|
this.recorder.unload(params);
|
|
8537
8689
|
this.recorderInsides.unload();
|
|
8538
8690
|
this.replay.unload(params);
|
|
@@ -8546,13 +8698,31 @@ class Visuals extends util_Despot {
|
|
|
8546
8698
|
this.recorder.pause(params);
|
|
8547
8699
|
this.recorderInsides.showPause();
|
|
8548
8700
|
}
|
|
8701
|
+
clearCameraRecoveryNotice() {
|
|
8702
|
+
if (this.cameraRecoveryFailed) {
|
|
8703
|
+
this.notifier.hide();
|
|
8704
|
+
this.recorder.show();
|
|
8705
|
+
this.cameraRecoveryFailed = false;
|
|
8706
|
+
}
|
|
8707
|
+
}
|
|
8708
|
+
recoverCamera() {
|
|
8709
|
+
if (this.replay.isShown() || this.isNotifying() && !this.cameraRecoveryFailed) return Promise.resolve(false);
|
|
8710
|
+
this.clearCameraRecoveryNotice();
|
|
8711
|
+
return this.recorder.recoverCamera();
|
|
8712
|
+
}
|
|
8549
8713
|
resume() {
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8714
|
+
this.clearCameraRecoveryNotice();
|
|
8715
|
+
if (this.recorderInsides.isCountingDown()) {
|
|
8716
|
+
this.recorderInsides.resumeCountdown();
|
|
8717
|
+
this.recorderInsides.hidePause();
|
|
8718
|
+
} else {
|
|
8719
|
+
this.recorder.resume();
|
|
8720
|
+
if (!this.recorder.isPaused()) this.recorderInsides.hidePause();
|
|
8721
|
+
}
|
|
8553
8722
|
}
|
|
8554
8723
|
pauseOrResume() {
|
|
8555
|
-
if (this.
|
|
8724
|
+
if (this.cameraRecoveryFailed && this.recorder.isPaused()) this.resume();
|
|
8725
|
+
else if (this.isRecordable()) {
|
|
8556
8726
|
if (this.isRecording()) this.pause();
|
|
8557
8727
|
else if (this.recorder.isPaused()) this.resume();
|
|
8558
8728
|
else if (this.recorder.isReady()) this.recorder.record();
|
|
@@ -8674,7 +8844,7 @@ class Visuals extends util_Despot {
|
|
|
8674
8844
|
return this.visualsElement;
|
|
8675
8845
|
}
|
|
8676
8846
|
constructor(container, options){
|
|
8677
|
-
super("Visuals", options), visuals_define_property(this, "container", void 0), visuals_define_property(this, "replay", void 0), visuals_define_property(this, "recorder", void 0), visuals_define_property(this, "recorderInsides", void 0), visuals_define_property(this, "notifier", void 0), visuals_define_property(this, "visualsElement", void 0), visuals_define_property(this, "built", false);
|
|
8847
|
+
super("Visuals", options), visuals_define_property(this, "container", void 0), visuals_define_property(this, "replay", void 0), visuals_define_property(this, "recorder", void 0), visuals_define_property(this, "recorderInsides", void 0), visuals_define_property(this, "notifier", void 0), visuals_define_property(this, "visualsElement", void 0), visuals_define_property(this, "built", false), visuals_define_property(this, "cameraRecoveryFailed", false);
|
|
8678
8848
|
this.container = container;
|
|
8679
8849
|
this.replay = new visuals_replay(this, options);
|
|
8680
8850
|
this.recorder = new visuals_recorder(this, this.replay, options);
|
|
@@ -8776,10 +8946,10 @@ class Container extends util_Despot {
|
|
|
8776
8946
|
});
|
|
8777
8947
|
if (!playerOnly) this.stopListeningToVisibility = this.visibility.onChange((visible)=>{
|
|
8778
8948
|
if (this.built) if (visible) {
|
|
8779
|
-
if (isAutoPauseEnabled(this.options)
|
|
8949
|
+
if (isAutoPauseEnabled(this.options)) this.recoverCamera();
|
|
8780
8950
|
this.emit("VISIBLE");
|
|
8781
8951
|
} else {
|
|
8782
|
-
if (isAutoPauseEnabled(this.options)
|
|
8952
|
+
if (isAutoPauseEnabled(this.options)) this.suspend();
|
|
8783
8953
|
this.emit("INVISIBLE");
|
|
8784
8954
|
}
|
|
8785
8955
|
});
|
|
@@ -8967,6 +9137,13 @@ class Container extends util_Despot {
|
|
|
8967
9137
|
pause(params) {
|
|
8968
9138
|
this.visuals.pause(params);
|
|
8969
9139
|
}
|
|
9140
|
+
suspend() {
|
|
9141
|
+
if (this.built && (this.isCountingDown() || this.isRecording() || this.isPaused())) this.pause();
|
|
9142
|
+
}
|
|
9143
|
+
recoverCamera() {
|
|
9144
|
+
if (!this.built || this.hasError || this.submitted) return Promise.resolve(false);
|
|
9145
|
+
return this.visuals.recoverCamera();
|
|
9146
|
+
}
|
|
8970
9147
|
validate(event, force = false) {
|
|
8971
9148
|
let runValidation = true;
|
|
8972
9149
|
let valid = true;
|
|
@@ -9308,6 +9485,12 @@ class VideomailClient extends util_Despot {
|
|
|
9308
9485
|
record() {
|
|
9309
9486
|
this.container.record();
|
|
9310
9487
|
}
|
|
9488
|
+
pause() {
|
|
9489
|
+
this.container.suspend();
|
|
9490
|
+
}
|
|
9491
|
+
recoverCamera() {
|
|
9492
|
+
return this.container.recoverCamera();
|
|
9493
|
+
}
|
|
9311
9494
|
getLogLines() {
|
|
9312
9495
|
if (this.options.logger.getLines) return this.options.logger.getLines();
|
|
9313
9496
|
}
|