@snapcall/stream-ui 1.28.0 → 1.29.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/dist/stream-ui.esm.js +91 -34
- package/dist/stream-ui.js +91 -34
- package/dist/types.d.ts +5 -3
- package/package.json +1 -1
package/dist/stream-ui.esm.js
CHANGED
|
@@ -503,19 +503,17 @@ const $67e45b2e30dcc030$var$audioContextConstructor = window.AudioContext || win
|
|
|
503
503
|
const $67e45b2e30dcc030$var$AUDIO_MUTE_DETECTION_TIME = 2000;
|
|
504
504
|
const $67e45b2e30dcc030$var$START_SPEAK_DETECTION_TIME = 50;
|
|
505
505
|
const $67e45b2e30dcc030$var$STOP_SPEAK_DETECTION_TIME = 500;
|
|
506
|
+
const $67e45b2e30dcc030$var$AUDIO_DATA_RATE = 60;
|
|
506
507
|
class $67e45b2e30dcc030$export$ea669869acd8f177 {
|
|
507
508
|
constructor(stream, listener){
|
|
508
509
|
this.speakStartEventTime = 0;
|
|
509
510
|
this.speakStopEventTime = 0;
|
|
510
511
|
this.isSpeaking = false;
|
|
511
|
-
this.
|
|
512
|
-
this.audioLevelInterval = -1;
|
|
513
|
-
this.audioLevelAverageInterval = -1;
|
|
512
|
+
this.audioIntervals = {};
|
|
514
513
|
this.audioLevelAverage = {
|
|
515
514
|
count: 0,
|
|
516
515
|
average: 0
|
|
517
516
|
};
|
|
518
|
-
this.audioLevels = [];
|
|
519
517
|
this.id = stream.id;
|
|
520
518
|
this.listener = listener;
|
|
521
519
|
this.stream = stream;
|
|
@@ -532,15 +530,16 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
|
|
|
532
530
|
this.analyser.minDecibels = -90;
|
|
533
531
|
this.analyser.maxDecibels = -10;
|
|
534
532
|
this.audioStreamSource.connect(this.analyser);
|
|
533
|
+
this.audioLevels = new Array(Math.round(1000 / $67e45b2e30dcc030$var$AUDIO_DATA_RATE)).fill(0);
|
|
535
534
|
}
|
|
536
535
|
/**
|
|
537
|
-
* return the
|
|
536
|
+
* return the average (mean) of the audio levels (AUDIO_DATA_RATE per second) for the
|
|
538
537
|
* current second
|
|
539
|
-
*/
|
|
538
|
+
*/ getRecentAudioLevelAverage() {
|
|
540
539
|
const { length: length } = this.audioLevels;
|
|
541
540
|
const audioLevelsSum = this.audioLevels.reduce((sum, level)=>sum + level, 0);
|
|
542
|
-
const
|
|
543
|
-
return
|
|
541
|
+
const audioLevelAverage = audioLevelsSum / length;
|
|
542
|
+
return audioLevelAverage;
|
|
544
543
|
}
|
|
545
544
|
getCurrentAudioLevel() {
|
|
546
545
|
const { length: length } = this.audioLevels;
|
|
@@ -548,8 +547,8 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
|
|
|
548
547
|
return 0;
|
|
549
548
|
}
|
|
550
549
|
audioMuteDetection() {
|
|
551
|
-
const
|
|
552
|
-
if (
|
|
550
|
+
const audioLevelAverage = this.getRecentAudioLevelAverage();
|
|
551
|
+
if (audioLevelAverage === 0 && this.audioLevels.length > 0) this.listener?.onMuteDetection?.(this.id);
|
|
553
552
|
}
|
|
554
553
|
detectSpeakingChange(audioLevel) {
|
|
555
554
|
const threshold = 5;
|
|
@@ -588,24 +587,24 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
|
|
|
588
587
|
}
|
|
589
588
|
loopCalcul() {
|
|
590
589
|
const audioLevel = this.getInstantAudioLevel();
|
|
591
|
-
this.audioLevels
|
|
592
|
-
this.detectSpeakingChange(audioLevel);
|
|
590
|
+
this.audioLevels.shift();
|
|
593
591
|
this.audioLevels.push(audioLevel);
|
|
592
|
+
this.detectSpeakingChange(audioLevel);
|
|
594
593
|
this.listener?.onAudioLevel?.(audioLevel, this.id);
|
|
595
594
|
}
|
|
596
595
|
analyse() {
|
|
597
|
-
this.
|
|
598
|
-
this.
|
|
596
|
+
this.audioIntervals.level = setInterval(()=>this.loopCalcul(), 1000 / $67e45b2e30dcc030$var$AUDIO_DATA_RATE);
|
|
597
|
+
this.audioIntervals.muteDetection = setInterval(()=>this.audioMuteDetection(), $67e45b2e30dcc030$var$AUDIO_MUTE_DETECTION_TIME);
|
|
599
598
|
}
|
|
600
599
|
startAverageAnalysis() {
|
|
601
600
|
this.audioLevelAverage = {
|
|
602
601
|
count: 0,
|
|
603
602
|
average: 0
|
|
604
603
|
};
|
|
605
|
-
clearInterval(this.
|
|
606
|
-
this.
|
|
604
|
+
clearInterval(this.audioIntervals.levelAverage);
|
|
605
|
+
this.audioIntervals.levelAverage = setInterval(()=>{
|
|
607
606
|
const { count: count, average: average } = this.audioLevelAverage;
|
|
608
|
-
const nextAverage = (average * count + this.
|
|
607
|
+
const nextAverage = (average * count + this.getRecentAudioLevelAverage()) / (count + 1);
|
|
609
608
|
this.audioLevelAverage = {
|
|
610
609
|
count: count + 1,
|
|
611
610
|
average: nextAverage
|
|
@@ -613,7 +612,8 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
|
|
|
613
612
|
}, 1000);
|
|
614
613
|
}
|
|
615
614
|
stopAverageAnalysis() {
|
|
616
|
-
clearInterval(this.
|
|
615
|
+
clearInterval(this.audioIntervals.levelAverage);
|
|
616
|
+
delete this.audioIntervals.levelAverage;
|
|
617
617
|
return this.audioLevelAverage.average;
|
|
618
618
|
}
|
|
619
619
|
getFrequencyData() {
|
|
@@ -621,14 +621,18 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
|
|
|
621
621
|
this.analyser.getByteFrequencyData(FFTDataArray);
|
|
622
622
|
return FFTDataArray;
|
|
623
623
|
}
|
|
624
|
-
|
|
625
|
-
clearInterval(this.
|
|
626
|
-
clearInterval(this.
|
|
627
|
-
this.
|
|
624
|
+
clearIntervals() {
|
|
625
|
+
clearInterval(this.audioIntervals.level);
|
|
626
|
+
clearInterval(this.audioIntervals.levelAverage);
|
|
627
|
+
clearInterval(this.audioIntervals.muteDetection);
|
|
628
|
+
delete this.audioIntervals.level;
|
|
629
|
+
delete this.audioIntervals.levelAverage;
|
|
630
|
+
delete this.audioIntervals.muteDetection;
|
|
631
|
+
this.audioLevels.fill(0);
|
|
628
632
|
}
|
|
629
633
|
release() {
|
|
630
634
|
this.listener = undefined;
|
|
631
|
-
this.
|
|
635
|
+
this.clearIntervals();
|
|
632
636
|
this.stream = undefined;
|
|
633
637
|
try {
|
|
634
638
|
this.audioStreamSource.disconnect(this.analyser);
|
|
@@ -982,8 +986,14 @@ class $ab40fd7a219a4259$export$2e2bcd8739ae039 {
|
|
|
982
986
|
let needToAskVideo = Boolean(constraints.video && (!this.video.stream || !this.video.track || this.video.track.readyState === 'ended'));
|
|
983
987
|
const audioDeviceId = $ab40fd7a219a4259$export$fceddabcb6d8e584(constraints.audio);
|
|
984
988
|
const videoDeviceId = $ab40fd7a219a4259$export$fceddabcb6d8e584(constraints.video);
|
|
985
|
-
|
|
986
|
-
|
|
989
|
+
const oldAudioDeviceId = this.audio.track?.getSettings().deviceId;
|
|
990
|
+
const oldVideoDeviceId = this.video.track?.getSettings().deviceId;
|
|
991
|
+
/*
|
|
992
|
+
If deviceId is 'default', we cant differentiate if it's the same device or not. https://issues.chromium.org/issues/40199570#comment23
|
|
993
|
+
A possible solution would be to compare the label of the track. There is no guarantee that it will be unique or match the deviceId.
|
|
994
|
+
ex track label: Default - Microphone (USB Audio Device) (046d:0992)
|
|
995
|
+
*/ if (audioDeviceId && (audioDeviceId === 'default' || audioDeviceId !== oldAudioDeviceId)) needToAskAudio = true;
|
|
996
|
+
if (videoDeviceId && (videoDeviceId === 'default' || videoDeviceId !== oldVideoDeviceId)) needToAskVideo = true;
|
|
987
997
|
if (typeof constraints.video === 'object' && constraints.video.facingMode && constraints.video.facingMode !== this.video.track?.getSettings().facingMode) needToAskVideo = true;
|
|
988
998
|
return {
|
|
989
999
|
needToAskAudio: needToAskAudio,
|
|
@@ -1880,7 +1890,7 @@ class $c31e3fb4360572af$export$2e2bcd8739ae039 extends $c31e3fb4360572af$var$Str
|
|
|
1880
1890
|
}
|
|
1881
1891
|
async getTransport(kind, direction) {
|
|
1882
1892
|
if (!this.streamerMediasoup || !this.protoo) throw new Error('streamerMediasoup not initialized');
|
|
1883
|
-
let transport = this.mediasoupTransport[
|
|
1893
|
+
let transport = this.mediasoupTransport[direction];
|
|
1884
1894
|
if (!transport) {
|
|
1885
1895
|
try {
|
|
1886
1896
|
const promise = this.streamerMediasoup.createTransport(this.protoo, direction);
|
|
@@ -1889,7 +1899,7 @@ class $c31e3fb4360572af$export$2e2bcd8739ae039 extends $c31e3fb4360572af$var$Str
|
|
|
1889
1899
|
kind: kind,
|
|
1890
1900
|
createPromise: promise
|
|
1891
1901
|
};
|
|
1892
|
-
this.mediasoupTransport[
|
|
1902
|
+
this.mediasoupTransport[direction] = transport;
|
|
1893
1903
|
transport.transport = await promise;
|
|
1894
1904
|
if (transport.transport) this.listenWebRTCTransportStates(transport);
|
|
1895
1905
|
} catch (err) {
|
|
@@ -2072,6 +2082,7 @@ class $c31e3fb4360572af$export$2e2bcd8739ae039 extends $c31e3fb4360572af$var$Str
|
|
|
2072
2082
|
await this.micProducer?.replaceTrack({
|
|
2073
2083
|
track: track
|
|
2074
2084
|
});
|
|
2085
|
+
if (this.micProducer?.paused) track.enabled = false;
|
|
2075
2086
|
$c31e3fb4360572af$var$log.log('switchMicrophone', 'switched Microphone');
|
|
2076
2087
|
const trackSettings = track.getSettings();
|
|
2077
2088
|
const device = this.devicesList.find((it)=>it.deviceId === trackSettings.deviceId);
|
|
@@ -2497,7 +2508,6 @@ class $c31e3fb4360572af$export$2e2bcd8739ae039 extends $c31e3fb4360572af$var$Str
|
|
|
2497
2508
|
this.webcam.facingMode = config.facingMode;
|
|
2498
2509
|
} else {
|
|
2499
2510
|
if (config?.device) this.webcam.device = config.device;
|
|
2500
|
-
$c31e3fb4360572af$var$log.warn('enableVideo', 'default deviceId', this.webcam.device?.deviceId);
|
|
2501
2511
|
optionalParam.deviceId = {
|
|
2502
2512
|
ideal: this.webcam.device?.deviceId
|
|
2503
2513
|
};
|
|
@@ -2622,6 +2632,7 @@ class $c31e3fb4360572af$export$2e2bcd8739ae039 extends $c31e3fb4360572af$var$Str
|
|
|
2622
2632
|
audio: false,
|
|
2623
2633
|
video: true
|
|
2624
2634
|
});
|
|
2635
|
+
this.webcam.device = null;
|
|
2625
2636
|
this.webcamProducer = null;
|
|
2626
2637
|
this.webcamTrack = null;
|
|
2627
2638
|
if (this.useVideoBackground) {
|
|
@@ -3980,6 +3991,7 @@ class $e96d119a19ed0c6c$export$45fabd1ce5e673de {
|
|
|
3980
3991
|
this.video.addEventListener('enterpictureinpicture', this.onEnterPictureInPicture.bind(this));
|
|
3981
3992
|
this.video.addEventListener('leavepictureinpicture', this.onLeavePictureInPicture.bind(this));
|
|
3982
3993
|
this.tiles = [];
|
|
3994
|
+
this.missingVideoWarnings = {};
|
|
3983
3995
|
}
|
|
3984
3996
|
async start() {
|
|
3985
3997
|
if (this.tiles.length) {
|
|
@@ -4010,6 +4022,12 @@ class $e96d119a19ed0c6c$export$45fabd1ce5e673de {
|
|
|
4010
4022
|
this.started = false;
|
|
4011
4023
|
this.video.srcObject = null;
|
|
4012
4024
|
}
|
|
4025
|
+
warnMissingVideo(tileId) {
|
|
4026
|
+
if (!this.missingVideoWarnings[tileId]) {
|
|
4027
|
+
this.missingVideoWarnings[tileId] = '1';
|
|
4028
|
+
console.warn(`MultiPiP: No video found for peer ${tileId}`);
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4013
4031
|
draw() {
|
|
4014
4032
|
if (this.ctx && this.started) {
|
|
4015
4033
|
this.ctx.fillStyle = '#1f1f1f';
|
|
@@ -4017,7 +4035,10 @@ class $e96d119a19ed0c6c$export$45fabd1ce5e673de {
|
|
|
4017
4035
|
if (this.tiles.length) {
|
|
4018
4036
|
this.tiles.forEach((tile, index)=>{
|
|
4019
4037
|
const tileVideo = document.body.querySelectorAll(`[data-peer-id='${tile.id}'] video`)[0];
|
|
4020
|
-
if (!tileVideo)
|
|
4038
|
+
if (!tileVideo) {
|
|
4039
|
+
this.warnMissingVideo(tile.id);
|
|
4040
|
+
return;
|
|
4041
|
+
}
|
|
4021
4042
|
const tileRect = this.layout?.tileRects[index];
|
|
4022
4043
|
if (!tileRect) return;
|
|
4023
4044
|
this.ctx?.save();
|
|
@@ -6352,6 +6373,12 @@ const $580bffc02c115932$export$12201ede76c4c5e1 = ()=>{
|
|
|
6352
6373
|
const base64Image = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).captureVideo(videoElementRef.current);
|
|
6353
6374
|
try {
|
|
6354
6375
|
const uploaded = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).saveCapture(base64Image);
|
|
6376
|
+
await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).createEvents([
|
|
6377
|
+
{
|
|
6378
|
+
filename: uploaded.filename,
|
|
6379
|
+
type: 'image'
|
|
6380
|
+
}
|
|
6381
|
+
]);
|
|
6355
6382
|
await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).sendCustomMessageToAll({
|
|
6356
6383
|
type: 'snapshot',
|
|
6357
6384
|
imageSrc: uploaded.url
|
|
@@ -7125,6 +7152,7 @@ const $0707965973625e01$export$f36e83cafa401ab5 = ({ stream: stream, width: widt
|
|
|
7125
7152
|
onSnapshot: ()=>snapshot.trigger({
|
|
7126
7153
|
videoElementRef: videoElementRef
|
|
7127
7154
|
}),
|
|
7155
|
+
"data-peer-id": stream.id,
|
|
7128
7156
|
children: [
|
|
7129
7157
|
/*#__PURE__*/ (0, $3Sbms$jsx)((0, $7ec04c1818c68245$export$d574f5511ec1d79a), {
|
|
7130
7158
|
ref: videoElementRef,
|
|
@@ -12113,14 +12141,14 @@ const $64dee502cbd6331e$export$1ea93f9eface5983 = ({ duration: duration = 0, ave
|
|
|
12113
12141
|
duotone: true
|
|
12114
12142
|
})
|
|
12115
12143
|
});
|
|
12116
|
-
if (averageAudioLevel <=
|
|
12144
|
+
if (averageAudioLevel <= 1) return /*#__PURE__*/ (0, $3Sbms$jsx)($64dee502cbd6331e$var$Notification, {
|
|
12117
12145
|
title: t('recorder.audioLevelNotification.spokenWordsWarning.title'),
|
|
12118
12146
|
description: t('recorder.audioLevelNotification.spokenWordsWarning.description'),
|
|
12119
12147
|
icon: /*#__PURE__*/ (0, $3Sbms$jsx)((0, $3Sbms$AlertTriangleIcon), {
|
|
12120
12148
|
duotone: true
|
|
12121
12149
|
})
|
|
12122
12150
|
});
|
|
12123
|
-
if (averageAudioLevel <=
|
|
12151
|
+
if (averageAudioLevel <= 3) return /*#__PURE__*/ (0, $3Sbms$jsx)($64dee502cbd6331e$var$Notification, {
|
|
12124
12152
|
title: t('recorder.audioLevelNotification.spokenWordsQuestion.title'),
|
|
12125
12153
|
description: t('recorder.audioLevelNotification.spokenWordsQuestion.description'),
|
|
12126
12154
|
icon: /*#__PURE__*/ (0, $3Sbms$jsx)((0, $3Sbms$InfoCircleIcon), {
|
|
@@ -12261,7 +12289,7 @@ const $a5dd8f67439dd9eb$var$getStoredAssets = async ()=>{
|
|
|
12261
12289
|
const storedAssets = JSON.parse(localStorage.getItem('snapcall_assets') || '[]');
|
|
12262
12290
|
const assets = await Promise.all(storedAssets.map(async (storedAsset)=>{
|
|
12263
12291
|
try {
|
|
12264
|
-
let { url: url, thumbnailUrl: thumbnailUrl } = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).readAsset(storedAsset.filename);
|
|
12292
|
+
let { url: url, thumbnailUrl: thumbnailUrl, error: error } = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).readAsset(storedAsset.filename);
|
|
12265
12293
|
if (url) {
|
|
12266
12294
|
if (storedAsset.mode === 'photo') thumbnailUrl = url;
|
|
12267
12295
|
return {
|
|
@@ -12269,7 +12297,7 @@ const $a5dd8f67439dd9eb$var$getStoredAssets = async ()=>{
|
|
|
12269
12297
|
url: url,
|
|
12270
12298
|
thumbnailUrl: thumbnailUrl
|
|
12271
12299
|
};
|
|
12272
|
-
}
|
|
12300
|
+
} else if (error) $a5dd8f67439dd9eb$export$df987b50509121ea(storedAsset.filename);
|
|
12273
12301
|
} catch (error) {
|
|
12274
12302
|
$a5dd8f67439dd9eb$export$df987b50509121ea(storedAsset.filename);
|
|
12275
12303
|
}
|
|
@@ -12315,6 +12343,31 @@ const $a5dd8f67439dd9eb$export$931d641a2a152cf = ()=>{
|
|
|
12315
12343
|
|
|
12316
12344
|
|
|
12317
12345
|
|
|
12346
|
+
|
|
12347
|
+
|
|
12348
|
+
const $7c2ec1087f88cbe4$export$f2bc44ad94513462 = ()=>{
|
|
12349
|
+
const { clientInitResult: clientInitResult } = (0, $3Sbms$useContext)((0, $5f30d8bf4f04621e$export$2e2bcd8739ae039));
|
|
12350
|
+
const flowSource = clientInitResult.flow?.steps?.[0].config?.source;
|
|
12351
|
+
const onRecorderEnd = ()=>{
|
|
12352
|
+
if (flowSource === 'smooch') // @ts-ignore
|
|
12353
|
+
window.WebviewSdk?.close?.();
|
|
12354
|
+
else if (flowSource === 'whatsapp') window.location.href = 'https://wa.me';
|
|
12355
|
+
};
|
|
12356
|
+
(0, $3Sbms$useEffect)(()=>{
|
|
12357
|
+
if (flowSource === 'smooch') {
|
|
12358
|
+
const smoochScript = document.createElement('script');
|
|
12359
|
+
smoochScript.src = 'https://cdn.smooch.io/webview-sdk.min.js';
|
|
12360
|
+
if (!document.body.contains(smoochScript)) document.body.appendChild(smoochScript);
|
|
12361
|
+
}
|
|
12362
|
+
}, [
|
|
12363
|
+
flowSource
|
|
12364
|
+
]);
|
|
12365
|
+
return {
|
|
12366
|
+
onRecorderEnd: onRecorderEnd
|
|
12367
|
+
};
|
|
12368
|
+
};
|
|
12369
|
+
|
|
12370
|
+
|
|
12318
12371
|
const $3ecacdd28d707ec1$var$eventTypes = {
|
|
12319
12372
|
screen: 'screenshare',
|
|
12320
12373
|
photo: 'image',
|
|
@@ -12324,6 +12377,7 @@ const $3ecacdd28d707ec1$var$eventTypes = {
|
|
|
12324
12377
|
const $3ecacdd28d707ec1$export$c01bb29adf88f117 = ({ state: state })=>{
|
|
12325
12378
|
const { t: t } = (0, $3Sbms$useTranslation)();
|
|
12326
12379
|
const { assets: assets, incomingAsset: incomingAsset } = (0, $75812785bb101fee$export$2174f25d572f9f31)();
|
|
12380
|
+
const flowSourceAction = (0, $7c2ec1087f88cbe4$export$f2bc44ad94513462)();
|
|
12327
12381
|
const sendMutation = (0, $3Sbms$useMutation)({
|
|
12328
12382
|
mutationFn: async ()=>{
|
|
12329
12383
|
try {
|
|
@@ -12348,7 +12402,6 @@ const $3ecacdd28d707ec1$export$c01bb29adf88f117 = ({ state: state })=>{
|
|
|
12348
12402
|
});
|
|
12349
12403
|
throw new Error('some media not saved');
|
|
12350
12404
|
}
|
|
12351
|
-
(0, $c9e496369b59be7a$export$2f377c2162fd02b2).release();
|
|
12352
12405
|
return results;
|
|
12353
12406
|
} catch (error) {
|
|
12354
12407
|
reportError({
|
|
@@ -12358,6 +12411,10 @@ const $3ecacdd28d707ec1$export$c01bb29adf88f117 = ({ state: state })=>{
|
|
|
12358
12411
|
console.log(error);
|
|
12359
12412
|
throw error;
|
|
12360
12413
|
}
|
|
12414
|
+
},
|
|
12415
|
+
onSuccess: ()=>{
|
|
12416
|
+
(0, $c9e496369b59be7a$export$2f377c2162fd02b2).release();
|
|
12417
|
+
flowSourceAction.onRecorderEnd();
|
|
12361
12418
|
}
|
|
12362
12419
|
});
|
|
12363
12420
|
const reportError = (0, $946223bbb2c552ef$export$5a5695b638d078e7)();
|
package/dist/stream-ui.js
CHANGED
|
@@ -509,19 +509,17 @@ const $6a90fae7e584afd4$var$audioContextConstructor = window.AudioContext || win
|
|
|
509
509
|
const $6a90fae7e584afd4$var$AUDIO_MUTE_DETECTION_TIME = 2000;
|
|
510
510
|
const $6a90fae7e584afd4$var$START_SPEAK_DETECTION_TIME = 50;
|
|
511
511
|
const $6a90fae7e584afd4$var$STOP_SPEAK_DETECTION_TIME = 500;
|
|
512
|
+
const $6a90fae7e584afd4$var$AUDIO_DATA_RATE = 60;
|
|
512
513
|
class $6a90fae7e584afd4$export$ea669869acd8f177 {
|
|
513
514
|
constructor(stream, listener){
|
|
514
515
|
this.speakStartEventTime = 0;
|
|
515
516
|
this.speakStopEventTime = 0;
|
|
516
517
|
this.isSpeaking = false;
|
|
517
|
-
this.
|
|
518
|
-
this.audioLevelInterval = -1;
|
|
519
|
-
this.audioLevelAverageInterval = -1;
|
|
518
|
+
this.audioIntervals = {};
|
|
520
519
|
this.audioLevelAverage = {
|
|
521
520
|
count: 0,
|
|
522
521
|
average: 0
|
|
523
522
|
};
|
|
524
|
-
this.audioLevels = [];
|
|
525
523
|
this.id = stream.id;
|
|
526
524
|
this.listener = listener;
|
|
527
525
|
this.stream = stream;
|
|
@@ -538,15 +536,16 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
|
|
|
538
536
|
this.analyser.minDecibels = -90;
|
|
539
537
|
this.analyser.maxDecibels = -10;
|
|
540
538
|
this.audioStreamSource.connect(this.analyser);
|
|
539
|
+
this.audioLevels = new Array(Math.round(1000 / $6a90fae7e584afd4$var$AUDIO_DATA_RATE)).fill(0);
|
|
541
540
|
}
|
|
542
541
|
/**
|
|
543
|
-
* return the
|
|
542
|
+
* return the average (mean) of the audio levels (AUDIO_DATA_RATE per second) for the
|
|
544
543
|
* current second
|
|
545
|
-
*/
|
|
544
|
+
*/ getRecentAudioLevelAverage() {
|
|
546
545
|
const { length: length } = this.audioLevels;
|
|
547
546
|
const audioLevelsSum = this.audioLevels.reduce((sum, level)=>sum + level, 0);
|
|
548
|
-
const
|
|
549
|
-
return
|
|
547
|
+
const audioLevelAverage = audioLevelsSum / length;
|
|
548
|
+
return audioLevelAverage;
|
|
550
549
|
}
|
|
551
550
|
getCurrentAudioLevel() {
|
|
552
551
|
const { length: length } = this.audioLevels;
|
|
@@ -554,8 +553,8 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
|
|
|
554
553
|
return 0;
|
|
555
554
|
}
|
|
556
555
|
audioMuteDetection() {
|
|
557
|
-
const
|
|
558
|
-
if (
|
|
556
|
+
const audioLevelAverage = this.getRecentAudioLevelAverage();
|
|
557
|
+
if (audioLevelAverage === 0 && this.audioLevels.length > 0) this.listener?.onMuteDetection?.(this.id);
|
|
559
558
|
}
|
|
560
559
|
detectSpeakingChange(audioLevel) {
|
|
561
560
|
const threshold = 5;
|
|
@@ -594,24 +593,24 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
|
|
|
594
593
|
}
|
|
595
594
|
loopCalcul() {
|
|
596
595
|
const audioLevel = this.getInstantAudioLevel();
|
|
597
|
-
this.audioLevels
|
|
598
|
-
this.detectSpeakingChange(audioLevel);
|
|
596
|
+
this.audioLevels.shift();
|
|
599
597
|
this.audioLevels.push(audioLevel);
|
|
598
|
+
this.detectSpeakingChange(audioLevel);
|
|
600
599
|
this.listener?.onAudioLevel?.(audioLevel, this.id);
|
|
601
600
|
}
|
|
602
601
|
analyse() {
|
|
603
|
-
this.
|
|
604
|
-
this.
|
|
602
|
+
this.audioIntervals.level = setInterval(()=>this.loopCalcul(), 1000 / $6a90fae7e584afd4$var$AUDIO_DATA_RATE);
|
|
603
|
+
this.audioIntervals.muteDetection = setInterval(()=>this.audioMuteDetection(), $6a90fae7e584afd4$var$AUDIO_MUTE_DETECTION_TIME);
|
|
605
604
|
}
|
|
606
605
|
startAverageAnalysis() {
|
|
607
606
|
this.audioLevelAverage = {
|
|
608
607
|
count: 0,
|
|
609
608
|
average: 0
|
|
610
609
|
};
|
|
611
|
-
clearInterval(this.
|
|
612
|
-
this.
|
|
610
|
+
clearInterval(this.audioIntervals.levelAverage);
|
|
611
|
+
this.audioIntervals.levelAverage = setInterval(()=>{
|
|
613
612
|
const { count: count, average: average } = this.audioLevelAverage;
|
|
614
|
-
const nextAverage = (average * count + this.
|
|
613
|
+
const nextAverage = (average * count + this.getRecentAudioLevelAverage()) / (count + 1);
|
|
615
614
|
this.audioLevelAverage = {
|
|
616
615
|
count: count + 1,
|
|
617
616
|
average: nextAverage
|
|
@@ -619,7 +618,8 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
|
|
|
619
618
|
}, 1000);
|
|
620
619
|
}
|
|
621
620
|
stopAverageAnalysis() {
|
|
622
|
-
clearInterval(this.
|
|
621
|
+
clearInterval(this.audioIntervals.levelAverage);
|
|
622
|
+
delete this.audioIntervals.levelAverage;
|
|
623
623
|
return this.audioLevelAverage.average;
|
|
624
624
|
}
|
|
625
625
|
getFrequencyData() {
|
|
@@ -627,14 +627,18 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
|
|
|
627
627
|
this.analyser.getByteFrequencyData(FFTDataArray);
|
|
628
628
|
return FFTDataArray;
|
|
629
629
|
}
|
|
630
|
-
|
|
631
|
-
clearInterval(this.
|
|
632
|
-
clearInterval(this.
|
|
633
|
-
this.
|
|
630
|
+
clearIntervals() {
|
|
631
|
+
clearInterval(this.audioIntervals.level);
|
|
632
|
+
clearInterval(this.audioIntervals.levelAverage);
|
|
633
|
+
clearInterval(this.audioIntervals.muteDetection);
|
|
634
|
+
delete this.audioIntervals.level;
|
|
635
|
+
delete this.audioIntervals.levelAverage;
|
|
636
|
+
delete this.audioIntervals.muteDetection;
|
|
637
|
+
this.audioLevels.fill(0);
|
|
634
638
|
}
|
|
635
639
|
release() {
|
|
636
640
|
this.listener = undefined;
|
|
637
|
-
this.
|
|
641
|
+
this.clearIntervals();
|
|
638
642
|
this.stream = undefined;
|
|
639
643
|
try {
|
|
640
644
|
this.audioStreamSource.disconnect(this.analyser);
|
|
@@ -988,8 +992,14 @@ class $d582bbc5717818b4$export$2e2bcd8739ae039 {
|
|
|
988
992
|
let needToAskVideo = Boolean(constraints.video && (!this.video.stream || !this.video.track || this.video.track.readyState === 'ended'));
|
|
989
993
|
const audioDeviceId = $d582bbc5717818b4$export$fceddabcb6d8e584(constraints.audio);
|
|
990
994
|
const videoDeviceId = $d582bbc5717818b4$export$fceddabcb6d8e584(constraints.video);
|
|
991
|
-
|
|
992
|
-
|
|
995
|
+
const oldAudioDeviceId = this.audio.track?.getSettings().deviceId;
|
|
996
|
+
const oldVideoDeviceId = this.video.track?.getSettings().deviceId;
|
|
997
|
+
/*
|
|
998
|
+
If deviceId is 'default', we cant differentiate if it's the same device or not. https://issues.chromium.org/issues/40199570#comment23
|
|
999
|
+
A possible solution would be to compare the label of the track. There is no guarantee that it will be unique or match the deviceId.
|
|
1000
|
+
ex track label: Default - Microphone (USB Audio Device) (046d:0992)
|
|
1001
|
+
*/ if (audioDeviceId && (audioDeviceId === 'default' || audioDeviceId !== oldAudioDeviceId)) needToAskAudio = true;
|
|
1002
|
+
if (videoDeviceId && (videoDeviceId === 'default' || videoDeviceId !== oldVideoDeviceId)) needToAskVideo = true;
|
|
993
1003
|
if (typeof constraints.video === 'object' && constraints.video.facingMode && constraints.video.facingMode !== this.video.track?.getSettings().facingMode) needToAskVideo = true;
|
|
994
1004
|
return {
|
|
995
1005
|
needToAskAudio: needToAskAudio,
|
|
@@ -1886,7 +1896,7 @@ class $1dedebd5ff3002eb$export$2e2bcd8739ae039 extends $1dedebd5ff3002eb$var$Str
|
|
|
1886
1896
|
}
|
|
1887
1897
|
async getTransport(kind, direction) {
|
|
1888
1898
|
if (!this.streamerMediasoup || !this.protoo) throw new Error('streamerMediasoup not initialized');
|
|
1889
|
-
let transport = this.mediasoupTransport[
|
|
1899
|
+
let transport = this.mediasoupTransport[direction];
|
|
1890
1900
|
if (!transport) {
|
|
1891
1901
|
try {
|
|
1892
1902
|
const promise = this.streamerMediasoup.createTransport(this.protoo, direction);
|
|
@@ -1895,7 +1905,7 @@ class $1dedebd5ff3002eb$export$2e2bcd8739ae039 extends $1dedebd5ff3002eb$var$Str
|
|
|
1895
1905
|
kind: kind,
|
|
1896
1906
|
createPromise: promise
|
|
1897
1907
|
};
|
|
1898
|
-
this.mediasoupTransport[
|
|
1908
|
+
this.mediasoupTransport[direction] = transport;
|
|
1899
1909
|
transport.transport = await promise;
|
|
1900
1910
|
if (transport.transport) this.listenWebRTCTransportStates(transport);
|
|
1901
1911
|
} catch (err) {
|
|
@@ -2078,6 +2088,7 @@ class $1dedebd5ff3002eb$export$2e2bcd8739ae039 extends $1dedebd5ff3002eb$var$Str
|
|
|
2078
2088
|
await this.micProducer?.replaceTrack({
|
|
2079
2089
|
track: track
|
|
2080
2090
|
});
|
|
2091
|
+
if (this.micProducer?.paused) track.enabled = false;
|
|
2081
2092
|
$1dedebd5ff3002eb$var$log.log('switchMicrophone', 'switched Microphone');
|
|
2082
2093
|
const trackSettings = track.getSettings();
|
|
2083
2094
|
const device = this.devicesList.find((it)=>it.deviceId === trackSettings.deviceId);
|
|
@@ -2503,7 +2514,6 @@ class $1dedebd5ff3002eb$export$2e2bcd8739ae039 extends $1dedebd5ff3002eb$var$Str
|
|
|
2503
2514
|
this.webcam.facingMode = config.facingMode;
|
|
2504
2515
|
} else {
|
|
2505
2516
|
if (config?.device) this.webcam.device = config.device;
|
|
2506
|
-
$1dedebd5ff3002eb$var$log.warn('enableVideo', 'default deviceId', this.webcam.device?.deviceId);
|
|
2507
2517
|
optionalParam.deviceId = {
|
|
2508
2518
|
ideal: this.webcam.device?.deviceId
|
|
2509
2519
|
};
|
|
@@ -2628,6 +2638,7 @@ class $1dedebd5ff3002eb$export$2e2bcd8739ae039 extends $1dedebd5ff3002eb$var$Str
|
|
|
2628
2638
|
audio: false,
|
|
2629
2639
|
video: true
|
|
2630
2640
|
});
|
|
2641
|
+
this.webcam.device = null;
|
|
2631
2642
|
this.webcamProducer = null;
|
|
2632
2643
|
this.webcamTrack = null;
|
|
2633
2644
|
if (this.useVideoBackground) {
|
|
@@ -3986,6 +3997,7 @@ class $21395e477f83709c$export$45fabd1ce5e673de {
|
|
|
3986
3997
|
this.video.addEventListener('enterpictureinpicture', this.onEnterPictureInPicture.bind(this));
|
|
3987
3998
|
this.video.addEventListener('leavepictureinpicture', this.onLeavePictureInPicture.bind(this));
|
|
3988
3999
|
this.tiles = [];
|
|
4000
|
+
this.missingVideoWarnings = {};
|
|
3989
4001
|
}
|
|
3990
4002
|
async start() {
|
|
3991
4003
|
if (this.tiles.length) {
|
|
@@ -4016,6 +4028,12 @@ class $21395e477f83709c$export$45fabd1ce5e673de {
|
|
|
4016
4028
|
this.started = false;
|
|
4017
4029
|
this.video.srcObject = null;
|
|
4018
4030
|
}
|
|
4031
|
+
warnMissingVideo(tileId) {
|
|
4032
|
+
if (!this.missingVideoWarnings[tileId]) {
|
|
4033
|
+
this.missingVideoWarnings[tileId] = '1';
|
|
4034
|
+
console.warn(`MultiPiP: No video found for peer ${tileId}`);
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4019
4037
|
draw() {
|
|
4020
4038
|
if (this.ctx && this.started) {
|
|
4021
4039
|
this.ctx.fillStyle = '#1f1f1f';
|
|
@@ -4023,7 +4041,10 @@ class $21395e477f83709c$export$45fabd1ce5e673de {
|
|
|
4023
4041
|
if (this.tiles.length) {
|
|
4024
4042
|
this.tiles.forEach((tile, index)=>{
|
|
4025
4043
|
const tileVideo = document.body.querySelectorAll(`[data-peer-id='${tile.id}'] video`)[0];
|
|
4026
|
-
if (!tileVideo)
|
|
4044
|
+
if (!tileVideo) {
|
|
4045
|
+
this.warnMissingVideo(tile.id);
|
|
4046
|
+
return;
|
|
4047
|
+
}
|
|
4027
4048
|
const tileRect = this.layout?.tileRects[index];
|
|
4028
4049
|
if (!tileRect) return;
|
|
4029
4050
|
this.ctx?.save();
|
|
@@ -6358,6 +6379,12 @@ const $b7b8f2e5b7552341$export$12201ede76c4c5e1 = ()=>{
|
|
|
6358
6379
|
const base64Image = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).captureVideo(videoElementRef.current);
|
|
6359
6380
|
try {
|
|
6360
6381
|
const uploaded = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).saveCapture(base64Image);
|
|
6382
|
+
await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).createEvents([
|
|
6383
|
+
{
|
|
6384
|
+
filename: uploaded.filename,
|
|
6385
|
+
type: 'image'
|
|
6386
|
+
}
|
|
6387
|
+
]);
|
|
6361
6388
|
await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).sendCustomMessageToAll({
|
|
6362
6389
|
type: 'snapshot',
|
|
6363
6390
|
imageSrc: uploaded.url
|
|
@@ -7131,6 +7158,7 @@ const $75b49da54f729405$export$f36e83cafa401ab5 = ({ stream: stream, width: widt
|
|
|
7131
7158
|
onSnapshot: ()=>snapshot.trigger({
|
|
7132
7159
|
videoElementRef: videoElementRef
|
|
7133
7160
|
}),
|
|
7161
|
+
"data-peer-id": stream.id,
|
|
7134
7162
|
children: [
|
|
7135
7163
|
/*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)((0, $66c45b20958474ec$export$d574f5511ec1d79a), {
|
|
7136
7164
|
ref: videoElementRef,
|
|
@@ -12119,14 +12147,14 @@ const $c42fbc742adf8306$export$1ea93f9eface5983 = ({ duration: duration = 0, ave
|
|
|
12119
12147
|
duotone: true
|
|
12120
12148
|
})
|
|
12121
12149
|
});
|
|
12122
|
-
if (averageAudioLevel <=
|
|
12150
|
+
if (averageAudioLevel <= 1) return /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)($c42fbc742adf8306$var$Notification, {
|
|
12123
12151
|
title: t('recorder.audioLevelNotification.spokenWordsWarning.title'),
|
|
12124
12152
|
description: t('recorder.audioLevelNotification.spokenWordsWarning.description'),
|
|
12125
12153
|
icon: /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)((0, $jQDcL$snapcalldesignsystemicons.AlertTriangleIcon), {
|
|
12126
12154
|
duotone: true
|
|
12127
12155
|
})
|
|
12128
12156
|
});
|
|
12129
|
-
if (averageAudioLevel <=
|
|
12157
|
+
if (averageAudioLevel <= 3) return /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)($c42fbc742adf8306$var$Notification, {
|
|
12130
12158
|
title: t('recorder.audioLevelNotification.spokenWordsQuestion.title'),
|
|
12131
12159
|
description: t('recorder.audioLevelNotification.spokenWordsQuestion.description'),
|
|
12132
12160
|
icon: /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)((0, $jQDcL$snapcalldesignsystemicons.InfoCircleIcon), {
|
|
@@ -12267,7 +12295,7 @@ const $8a7a24ac08dbc187$var$getStoredAssets = async ()=>{
|
|
|
12267
12295
|
const storedAssets = JSON.parse(localStorage.getItem('snapcall_assets') || '[]');
|
|
12268
12296
|
const assets = await Promise.all(storedAssets.map(async (storedAsset)=>{
|
|
12269
12297
|
try {
|
|
12270
|
-
let { url: url, thumbnailUrl: thumbnailUrl } = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).readAsset(storedAsset.filename);
|
|
12298
|
+
let { url: url, thumbnailUrl: thumbnailUrl, error: error } = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).readAsset(storedAsset.filename);
|
|
12271
12299
|
if (url) {
|
|
12272
12300
|
if (storedAsset.mode === 'photo') thumbnailUrl = url;
|
|
12273
12301
|
return {
|
|
@@ -12275,7 +12303,7 @@ const $8a7a24ac08dbc187$var$getStoredAssets = async ()=>{
|
|
|
12275
12303
|
url: url,
|
|
12276
12304
|
thumbnailUrl: thumbnailUrl
|
|
12277
12305
|
};
|
|
12278
|
-
}
|
|
12306
|
+
} else if (error) $8a7a24ac08dbc187$export$df987b50509121ea(storedAsset.filename);
|
|
12279
12307
|
} catch (error) {
|
|
12280
12308
|
$8a7a24ac08dbc187$export$df987b50509121ea(storedAsset.filename);
|
|
12281
12309
|
}
|
|
@@ -12321,6 +12349,31 @@ const $8a7a24ac08dbc187$export$931d641a2a152cf = ()=>{
|
|
|
12321
12349
|
|
|
12322
12350
|
|
|
12323
12351
|
|
|
12352
|
+
|
|
12353
|
+
|
|
12354
|
+
const $663f53e6b55f0d5a$export$f2bc44ad94513462 = ()=>{
|
|
12355
|
+
const { clientInitResult: clientInitResult } = (0, $jQDcL$react.useContext)((0, $8b39f32976a7698a$export$2e2bcd8739ae039));
|
|
12356
|
+
const flowSource = clientInitResult.flow?.steps?.[0].config?.source;
|
|
12357
|
+
const onRecorderEnd = ()=>{
|
|
12358
|
+
if (flowSource === 'smooch') // @ts-ignore
|
|
12359
|
+
window.WebviewSdk?.close?.();
|
|
12360
|
+
else if (flowSource === 'whatsapp') window.location.href = 'https://wa.me';
|
|
12361
|
+
};
|
|
12362
|
+
(0, $jQDcL$react.useEffect)(()=>{
|
|
12363
|
+
if (flowSource === 'smooch') {
|
|
12364
|
+
const smoochScript = document.createElement('script');
|
|
12365
|
+
smoochScript.src = 'https://cdn.smooch.io/webview-sdk.min.js';
|
|
12366
|
+
if (!document.body.contains(smoochScript)) document.body.appendChild(smoochScript);
|
|
12367
|
+
}
|
|
12368
|
+
}, [
|
|
12369
|
+
flowSource
|
|
12370
|
+
]);
|
|
12371
|
+
return {
|
|
12372
|
+
onRecorderEnd: onRecorderEnd
|
|
12373
|
+
};
|
|
12374
|
+
};
|
|
12375
|
+
|
|
12376
|
+
|
|
12324
12377
|
const $e399416dd32d3252$var$eventTypes = {
|
|
12325
12378
|
screen: 'screenshare',
|
|
12326
12379
|
photo: 'image',
|
|
@@ -12330,6 +12383,7 @@ const $e399416dd32d3252$var$eventTypes = {
|
|
|
12330
12383
|
const $e399416dd32d3252$export$c01bb29adf88f117 = ({ state: state })=>{
|
|
12331
12384
|
const { t: t } = (0, $jQDcL$reacti18next.useTranslation)();
|
|
12332
12385
|
const { assets: assets, incomingAsset: incomingAsset } = (0, $098350f721a0bb52$export$2174f25d572f9f31)();
|
|
12386
|
+
const flowSourceAction = (0, $663f53e6b55f0d5a$export$f2bc44ad94513462)();
|
|
12333
12387
|
const sendMutation = (0, $jQDcL$tanstackreactquery.useMutation)({
|
|
12334
12388
|
mutationFn: async ()=>{
|
|
12335
12389
|
try {
|
|
@@ -12354,7 +12408,6 @@ const $e399416dd32d3252$export$c01bb29adf88f117 = ({ state: state })=>{
|
|
|
12354
12408
|
});
|
|
12355
12409
|
throw new Error('some media not saved');
|
|
12356
12410
|
}
|
|
12357
|
-
(0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).release();
|
|
12358
12411
|
return results;
|
|
12359
12412
|
} catch (error) {
|
|
12360
12413
|
reportError({
|
|
@@ -12364,6 +12417,10 @@ const $e399416dd32d3252$export$c01bb29adf88f117 = ({ state: state })=>{
|
|
|
12364
12417
|
console.log(error);
|
|
12365
12418
|
throw error;
|
|
12366
12419
|
}
|
|
12420
|
+
},
|
|
12421
|
+
onSuccess: ()=>{
|
|
12422
|
+
(0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).release();
|
|
12423
|
+
flowSourceAction.onRecorderEnd();
|
|
12367
12424
|
}
|
|
12368
12425
|
});
|
|
12369
12426
|
const reportError = (0, $8dfcca373a03b9e8$export$5a5695b638d078e7)();
|
package/dist/types.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ interface Step {
|
|
|
18
18
|
config?: {
|
|
19
19
|
description: string;
|
|
20
20
|
image_url: string;
|
|
21
|
+
source?: string;
|
|
21
22
|
};
|
|
22
23
|
translation: {
|
|
23
24
|
title?: string;
|
|
@@ -192,16 +193,16 @@ declare class AudioLevel {
|
|
|
192
193
|
readonly id: string;
|
|
193
194
|
constructor(stream: MediaStream, listener?: AudioLevelListener);
|
|
194
195
|
/**
|
|
195
|
-
* return the
|
|
196
|
+
* return the average (mean) of the audio levels (AUDIO_DATA_RATE per second) for the
|
|
196
197
|
* current second
|
|
197
198
|
*/
|
|
198
|
-
|
|
199
|
+
getRecentAudioLevelAverage(): number;
|
|
199
200
|
getCurrentAudioLevel(): number;
|
|
200
201
|
analyse(): void;
|
|
201
202
|
startAverageAnalysis(): void;
|
|
202
203
|
stopAverageAnalysis(): number;
|
|
203
204
|
getFrequencyData(): Uint8Array;
|
|
204
|
-
|
|
205
|
+
clearIntervals(): void;
|
|
205
206
|
release(): void;
|
|
206
207
|
static isAPIAvailable(): boolean;
|
|
207
208
|
}
|
|
@@ -599,6 +600,7 @@ declare class StreamerClient extends StreamerEventTargetType implements AudioLev
|
|
|
599
600
|
readAsset(file: string): Promise<{
|
|
600
601
|
url: string;
|
|
601
602
|
thumbnailUrl?: string;
|
|
603
|
+
error?: string;
|
|
602
604
|
}>;
|
|
603
605
|
deleteAsset(file: string): Promise<{
|
|
604
606
|
status: boolean;
|