@stream-io/video-client 1.15.6 → 1.16.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/CHANGELOG.md +14 -0
- package/dist/index.browser.es.js +249 -137
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +253 -141
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.es.js +249 -137
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +18 -2
- package/dist/src/coordinator/connection/types.d.ts +4 -4
- package/dist/src/gen/coordinator/index.d.ts +1876 -2591
- package/dist/src/helpers/RNSpeechDetector.d.ts +3 -4
- package/dist/src/store/CallState.d.ts +2 -3
- package/index.ts +0 -1
- package/package.json +1 -1
- package/src/Call.ts +53 -2
- package/src/coordinator/connection/types.ts +4 -4
- package/src/devices/MicrophoneManager.ts +4 -12
- package/src/devices/__tests__/MicrophoneManagerRN.test.ts +6 -4
- package/src/gen/coordinator/index.ts +2762 -3476
- package/src/helpers/RNSpeechDetector.ts +104 -40
- package/src/store/CallState.ts +18 -26
- package/src/store/__tests__/CallState.test.ts +13 -1
- package/dist/src/gen/shims.d.ts +0 -41
- package/src/gen/shims.ts +0 -44
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import 'webrtc-adapter';
|
|
2
2
|
export * from './src/gen/coordinator';
|
|
3
|
-
export * from './src/gen/shims';
|
|
4
3
|
export * from './src/coordinator/connection/types';
|
|
5
4
|
export * as SfuEvents from './src/gen/video/sfu/event/events';
|
|
6
5
|
export * as SfuModels from './src/gen/video/sfu/models/models';
|
package/dist/index.es.js
CHANGED
|
@@ -9,8 +9,6 @@ import { parse } from 'sdp-transform';
|
|
|
9
9
|
import { UAParser } from 'ua-parser-js';
|
|
10
10
|
import https from 'https';
|
|
11
11
|
|
|
12
|
-
/* tslint:disable */
|
|
13
|
-
/* eslint-disable */
|
|
14
12
|
/**
|
|
15
13
|
* @export
|
|
16
14
|
*/
|
|
@@ -25,80 +23,6 @@ const AudioSettingsResponseDefaultDeviceEnum = {
|
|
|
25
23
|
SPEAKER: 'speaker',
|
|
26
24
|
EARPIECE: 'earpiece',
|
|
27
25
|
};
|
|
28
|
-
/**
|
|
29
|
-
* @export
|
|
30
|
-
*/
|
|
31
|
-
const BlockListOptionsBehaviorEnum = {
|
|
32
|
-
FLAG: 'flag',
|
|
33
|
-
BLOCK: 'block',
|
|
34
|
-
SHADOW_BLOCK: 'shadow_block',
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* @export
|
|
38
|
-
*/
|
|
39
|
-
const ChannelConfigWithInfoAutomodEnum = {
|
|
40
|
-
DISABLED: 'disabled',
|
|
41
|
-
SIMPLE: 'simple',
|
|
42
|
-
AI: 'AI',
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* @export
|
|
46
|
-
*/
|
|
47
|
-
const ChannelConfigWithInfoAutomodBehaviorEnum = {
|
|
48
|
-
FLAG: 'flag',
|
|
49
|
-
BLOCK: 'block',
|
|
50
|
-
SHADOW_BLOCK: 'shadow_block',
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* @export
|
|
54
|
-
*/
|
|
55
|
-
const ChannelConfigWithInfoBlocklistBehaviorEnum = {
|
|
56
|
-
FLAG: 'flag',
|
|
57
|
-
BLOCK: 'block',
|
|
58
|
-
SHADOW_BLOCK: 'shadow_block',
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* All possibility of string to use
|
|
62
|
-
* @export
|
|
63
|
-
*/
|
|
64
|
-
const ChannelOwnCapability = {
|
|
65
|
-
BAN_CHANNEL_MEMBERS: 'ban-channel-members',
|
|
66
|
-
CAST_POLL_VOTE: 'cast-poll-vote',
|
|
67
|
-
CONNECT_EVENTS: 'connect-events',
|
|
68
|
-
CREATE_ATTACHMENT: 'create-attachment',
|
|
69
|
-
CREATE_CALL: 'create-call',
|
|
70
|
-
DELETE_ANY_MESSAGE: 'delete-any-message',
|
|
71
|
-
DELETE_CHANNEL: 'delete-channel',
|
|
72
|
-
DELETE_OWN_MESSAGE: 'delete-own-message',
|
|
73
|
-
FLAG_MESSAGE: 'flag-message',
|
|
74
|
-
FREEZE_CHANNEL: 'freeze-channel',
|
|
75
|
-
JOIN_CALL: 'join-call',
|
|
76
|
-
JOIN_CHANNEL: 'join-channel',
|
|
77
|
-
LEAVE_CHANNEL: 'leave-channel',
|
|
78
|
-
MUTE_CHANNEL: 'mute-channel',
|
|
79
|
-
PIN_MESSAGE: 'pin-message',
|
|
80
|
-
QUERY_POLL_VOTES: 'query-poll-votes',
|
|
81
|
-
QUOTE_MESSAGE: 'quote-message',
|
|
82
|
-
READ_EVENTS: 'read-events',
|
|
83
|
-
SEARCH_MESSAGES: 'search-messages',
|
|
84
|
-
SEND_CUSTOM_EVENTS: 'send-custom-events',
|
|
85
|
-
SEND_LINKS: 'send-links',
|
|
86
|
-
SEND_MESSAGE: 'send-message',
|
|
87
|
-
SEND_POLL: 'send-poll',
|
|
88
|
-
SEND_REACTION: 'send-reaction',
|
|
89
|
-
SEND_REPLY: 'send-reply',
|
|
90
|
-
SEND_TYPING_EVENTS: 'send-typing-events',
|
|
91
|
-
SET_CHANNEL_COOLDOWN: 'set-channel-cooldown',
|
|
92
|
-
SKIP_SLOW_MODE: 'skip-slow-mode',
|
|
93
|
-
SLOW_MODE: 'slow-mode',
|
|
94
|
-
TYPING_EVENTS: 'typing-events',
|
|
95
|
-
UPDATE_ANY_MESSAGE: 'update-any-message',
|
|
96
|
-
UPDATE_CHANNEL: 'update-channel',
|
|
97
|
-
UPDATE_CHANNEL_MEMBERS: 'update-channel-members',
|
|
98
|
-
UPDATE_OWN_MESSAGE: 'update-own-message',
|
|
99
|
-
UPDATE_THREAD: 'update-thread',
|
|
100
|
-
UPLOAD_FILE: 'upload-file',
|
|
101
|
-
};
|
|
102
26
|
/**
|
|
103
27
|
* @export
|
|
104
28
|
*/
|
|
@@ -108,6 +32,16 @@ const CreateDeviceRequestPushProviderEnum = {
|
|
|
108
32
|
HUAWEI: 'huawei',
|
|
109
33
|
XIAOMI: 'xiaomi',
|
|
110
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* @export
|
|
37
|
+
*/
|
|
38
|
+
const LayoutSettingsRequestNameEnum = {
|
|
39
|
+
SPOTLIGHT: 'spotlight',
|
|
40
|
+
GRID: 'grid',
|
|
41
|
+
SINGLE_PARTICIPANT: 'single-participant',
|
|
42
|
+
MOBILE: 'mobile',
|
|
43
|
+
CUSTOM: 'custom',
|
|
44
|
+
};
|
|
111
45
|
/**
|
|
112
46
|
* @export
|
|
113
47
|
*/
|
|
@@ -150,6 +84,36 @@ const OwnCapability = {
|
|
|
150
84
|
UPDATE_CALL_PERMISSIONS: 'update-call-permissions',
|
|
151
85
|
UPDATE_CALL_SETTINGS: 'update-call-settings',
|
|
152
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* @export
|
|
89
|
+
*/
|
|
90
|
+
const RTMPBroadcastRequestQualityEnum = {
|
|
91
|
+
_360P: '360p',
|
|
92
|
+
_480P: '480p',
|
|
93
|
+
_720P: '720p',
|
|
94
|
+
_1080P: '1080p',
|
|
95
|
+
_1440P: '1440p',
|
|
96
|
+
PORTRAIT_360X640: 'portrait-360x640',
|
|
97
|
+
PORTRAIT_480X854: 'portrait-480x854',
|
|
98
|
+
PORTRAIT_720X1280: 'portrait-720x1280',
|
|
99
|
+
PORTRAIT_1080X1920: 'portrait-1080x1920',
|
|
100
|
+
PORTRAIT_1440X2560: 'portrait-1440x2560',
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* @export
|
|
104
|
+
*/
|
|
105
|
+
const RTMPSettingsRequestQualityEnum = {
|
|
106
|
+
_360P: '360p',
|
|
107
|
+
_480P: '480p',
|
|
108
|
+
_720P: '720p',
|
|
109
|
+
_1080P: '1080p',
|
|
110
|
+
_1440P: '1440p',
|
|
111
|
+
PORTRAIT_360X640: 'portrait-360x640',
|
|
112
|
+
PORTRAIT_480X854: 'portrait-480x854',
|
|
113
|
+
PORTRAIT_720X1280: 'portrait-720x1280',
|
|
114
|
+
PORTRAIT_1080X1920: 'portrait-1080x1920',
|
|
115
|
+
PORTRAIT_1440X2560: 'portrait-1440x2560',
|
|
116
|
+
};
|
|
153
117
|
/**
|
|
154
118
|
* @export
|
|
155
119
|
*/
|
|
@@ -181,6 +145,44 @@ const TranscriptionSettingsRequestClosedCaptionModeEnum = {
|
|
|
181
145
|
DISABLED: 'disabled',
|
|
182
146
|
AUTO_ON: 'auto-on',
|
|
183
147
|
};
|
|
148
|
+
/**
|
|
149
|
+
* @export
|
|
150
|
+
*/
|
|
151
|
+
const TranscriptionSettingsRequestLanguageEnum = {
|
|
152
|
+
AUTO: 'auto',
|
|
153
|
+
EN: 'en',
|
|
154
|
+
FR: 'fr',
|
|
155
|
+
ES: 'es',
|
|
156
|
+
DE: 'de',
|
|
157
|
+
IT: 'it',
|
|
158
|
+
NL: 'nl',
|
|
159
|
+
PT: 'pt',
|
|
160
|
+
PL: 'pl',
|
|
161
|
+
CA: 'ca',
|
|
162
|
+
CS: 'cs',
|
|
163
|
+
DA: 'da',
|
|
164
|
+
EL: 'el',
|
|
165
|
+
FI: 'fi',
|
|
166
|
+
ID: 'id',
|
|
167
|
+
JA: 'ja',
|
|
168
|
+
RU: 'ru',
|
|
169
|
+
SV: 'sv',
|
|
170
|
+
TA: 'ta',
|
|
171
|
+
TH: 'th',
|
|
172
|
+
TR: 'tr',
|
|
173
|
+
HU: 'hu',
|
|
174
|
+
RO: 'ro',
|
|
175
|
+
ZH: 'zh',
|
|
176
|
+
AR: 'ar',
|
|
177
|
+
TL: 'tl',
|
|
178
|
+
HE: 'he',
|
|
179
|
+
HI: 'hi',
|
|
180
|
+
HR: 'hr',
|
|
181
|
+
KO: 'ko',
|
|
182
|
+
MS: 'ms',
|
|
183
|
+
NO: 'no',
|
|
184
|
+
UK: 'uk',
|
|
185
|
+
};
|
|
184
186
|
/**
|
|
185
187
|
* @export
|
|
186
188
|
*/
|
|
@@ -197,6 +199,44 @@ const TranscriptionSettingsResponseClosedCaptionModeEnum = {
|
|
|
197
199
|
DISABLED: 'disabled',
|
|
198
200
|
AUTO_ON: 'auto-on',
|
|
199
201
|
};
|
|
202
|
+
/**
|
|
203
|
+
* @export
|
|
204
|
+
*/
|
|
205
|
+
const TranscriptionSettingsResponseLanguageEnum = {
|
|
206
|
+
AUTO: 'auto',
|
|
207
|
+
EN: 'en',
|
|
208
|
+
FR: 'fr',
|
|
209
|
+
ES: 'es',
|
|
210
|
+
DE: 'de',
|
|
211
|
+
IT: 'it',
|
|
212
|
+
NL: 'nl',
|
|
213
|
+
PT: 'pt',
|
|
214
|
+
PL: 'pl',
|
|
215
|
+
CA: 'ca',
|
|
216
|
+
CS: 'cs',
|
|
217
|
+
DA: 'da',
|
|
218
|
+
EL: 'el',
|
|
219
|
+
FI: 'fi',
|
|
220
|
+
ID: 'id',
|
|
221
|
+
JA: 'ja',
|
|
222
|
+
RU: 'ru',
|
|
223
|
+
SV: 'sv',
|
|
224
|
+
TA: 'ta',
|
|
225
|
+
TH: 'th',
|
|
226
|
+
TR: 'tr',
|
|
227
|
+
HU: 'hu',
|
|
228
|
+
RO: 'ro',
|
|
229
|
+
ZH: 'zh',
|
|
230
|
+
AR: 'ar',
|
|
231
|
+
TL: 'tl',
|
|
232
|
+
HE: 'he',
|
|
233
|
+
HI: 'hi',
|
|
234
|
+
HR: 'hr',
|
|
235
|
+
KO: 'ko',
|
|
236
|
+
MS: 'ms',
|
|
237
|
+
NO: 'no',
|
|
238
|
+
UK: 'uk',
|
|
239
|
+
};
|
|
200
240
|
/**
|
|
201
241
|
* @export
|
|
202
242
|
*/
|
|
@@ -4184,7 +4224,7 @@ const livestreamOrAudioRoomSortPreset = combineComparators(ifInvisibleBy(combine
|
|
|
4184
4224
|
*/
|
|
4185
4225
|
const defaultEgress = {
|
|
4186
4226
|
broadcasting: false,
|
|
4187
|
-
hls: { playlist_url: '' },
|
|
4227
|
+
hls: { playlist_url: '', status: '' },
|
|
4188
4228
|
rtmps: [],
|
|
4189
4229
|
};
|
|
4190
4230
|
/**
|
|
@@ -4647,21 +4687,19 @@ class CallState {
|
|
|
4647
4687
|
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
4648
4688
|
...egress,
|
|
4649
4689
|
broadcasting: false,
|
|
4690
|
+
hls: {
|
|
4691
|
+
...egress.hls,
|
|
4692
|
+
status: '',
|
|
4693
|
+
},
|
|
4650
4694
|
}));
|
|
4651
4695
|
};
|
|
4652
4696
|
this.updateFromHLSBroadcastingFailed = () => {
|
|
4653
4697
|
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
4654
4698
|
...egress,
|
|
4655
4699
|
broadcasting: false,
|
|
4656
|
-
}));
|
|
4657
|
-
};
|
|
4658
|
-
this.updateFromHLSBroadcastStarted = (event) => {
|
|
4659
|
-
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
4660
|
-
...egress,
|
|
4661
|
-
broadcasting: true,
|
|
4662
4700
|
hls: {
|
|
4663
4701
|
...egress.hls,
|
|
4664
|
-
|
|
4702
|
+
status: '',
|
|
4665
4703
|
},
|
|
4666
4704
|
}));
|
|
4667
4705
|
};
|
|
@@ -4872,21 +4910,16 @@ class CallState {
|
|
|
4872
4910
|
this.captioning$ = duc(this.captioningSubject);
|
|
4873
4911
|
this.eventHandlers = {
|
|
4874
4912
|
// these events are not updating the call state:
|
|
4875
|
-
'call.deleted': undefined,
|
|
4876
4913
|
'call.permission_request': undefined,
|
|
4877
4914
|
'call.recording_ready': undefined,
|
|
4915
|
+
'call.rtmp_broadcast_failed': undefined,
|
|
4916
|
+
'call.rtmp_broadcast_started': undefined,
|
|
4917
|
+
'call.rtmp_broadcast_stopped': undefined,
|
|
4878
4918
|
'call.transcription_ready': undefined,
|
|
4879
4919
|
'call.user_muted': undefined,
|
|
4880
4920
|
'connection.error': undefined,
|
|
4881
4921
|
'connection.ok': undefined,
|
|
4882
4922
|
'health.check': undefined,
|
|
4883
|
-
'user.banned': undefined,
|
|
4884
|
-
'user.deactivated': undefined,
|
|
4885
|
-
'user.deleted': undefined,
|
|
4886
|
-
'user.muted': undefined,
|
|
4887
|
-
'user.presence.changed': undefined,
|
|
4888
|
-
'user.reactivated': undefined,
|
|
4889
|
-
'user.unbanned': undefined,
|
|
4890
4923
|
'user.updated': undefined,
|
|
4891
4924
|
custom: undefined,
|
|
4892
4925
|
// events that update call state:
|
|
@@ -4903,12 +4936,15 @@ class CallState {
|
|
|
4903
4936
|
this.setCurrentValue(this.captioningSubject, false);
|
|
4904
4937
|
},
|
|
4905
4938
|
'call.created': (e) => this.updateFromCallResponse(e.call),
|
|
4939
|
+
'call.deleted': (e) => this.updateFromCallResponse(e.call),
|
|
4906
4940
|
'call.ended': (e) => {
|
|
4907
4941
|
this.updateFromCallResponse(e.call);
|
|
4908
4942
|
this.setCurrentValue(this.endedBySubject, e.user);
|
|
4909
4943
|
},
|
|
4910
4944
|
'call.hls_broadcasting_failed': this.updateFromHLSBroadcastingFailed,
|
|
4911
|
-
'call.hls_broadcasting_started':
|
|
4945
|
+
'call.hls_broadcasting_started': (e) => {
|
|
4946
|
+
this.updateFromCallResponse(e.call);
|
|
4947
|
+
},
|
|
4912
4948
|
'call.hls_broadcasting_stopped': this.updateFromHLSBroadcastStopped,
|
|
4913
4949
|
'call.live_started': (e) => this.updateFromCallResponse(e.call),
|
|
4914
4950
|
'call.member_added': this.updateFromMemberAdded,
|
|
@@ -7357,7 +7393,7 @@ const aggregate = (stats) => {
|
|
|
7357
7393
|
return report;
|
|
7358
7394
|
};
|
|
7359
7395
|
|
|
7360
|
-
const version = "1.
|
|
7396
|
+
const version = "1.16.0";
|
|
7361
7397
|
const [major, minor, patch] = version.split('.');
|
|
7362
7398
|
let sdkInfo = {
|
|
7363
7399
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -9338,7 +9374,7 @@ class MicrophoneManagerState extends InputMediaDeviceManagerState {
|
|
|
9338
9374
|
}
|
|
9339
9375
|
|
|
9340
9376
|
const DETECTION_FREQUENCY_IN_MS = 500;
|
|
9341
|
-
const AUDIO_LEVEL_THRESHOLD
|
|
9377
|
+
const AUDIO_LEVEL_THRESHOLD = 150;
|
|
9342
9378
|
const FFT_SIZE = 128;
|
|
9343
9379
|
/**
|
|
9344
9380
|
* Creates a new sound detector.
|
|
@@ -9349,7 +9385,7 @@ const FFT_SIZE = 128;
|
|
|
9349
9385
|
* @returns a clean-up function which once invoked stops the sound detector.
|
|
9350
9386
|
*/
|
|
9351
9387
|
const createSoundDetector = (audioStream, onSoundDetectedStateChanged, options = {}) => {
|
|
9352
|
-
const { detectionFrequencyInMs = DETECTION_FREQUENCY_IN_MS, audioLevelThreshold = AUDIO_LEVEL_THRESHOLD
|
|
9388
|
+
const { detectionFrequencyInMs = DETECTION_FREQUENCY_IN_MS, audioLevelThreshold = AUDIO_LEVEL_THRESHOLD, fftSize = FFT_SIZE, destroyStreamOnStop = true, } = options;
|
|
9353
9389
|
const audioContext = new AudioContext();
|
|
9354
9390
|
const analyser = audioContext.createAnalyser();
|
|
9355
9391
|
analyser.fftSize = fftSize;
|
|
@@ -9390,7 +9426,6 @@ const createSoundDetector = (audioStream, onSoundDetectedStateChanged, options =
|
|
|
9390
9426
|
};
|
|
9391
9427
|
};
|
|
9392
9428
|
|
|
9393
|
-
const AUDIO_LEVEL_THRESHOLD = 0.2;
|
|
9394
9429
|
class RNSpeechDetector {
|
|
9395
9430
|
constructor() {
|
|
9396
9431
|
this.pc1 = new RTCPeerConnection({});
|
|
@@ -9399,7 +9434,7 @@ class RNSpeechDetector {
|
|
|
9399
9434
|
/**
|
|
9400
9435
|
* Starts the speech detection.
|
|
9401
9436
|
*/
|
|
9402
|
-
async start() {
|
|
9437
|
+
async start(onSoundDetectedStateChanged) {
|
|
9403
9438
|
try {
|
|
9404
9439
|
this.cleanupAudioStream();
|
|
9405
9440
|
const audioStream = await navigator.mediaDevices.getUserMedia({
|
|
@@ -9412,6 +9447,14 @@ class RNSpeechDetector {
|
|
|
9412
9447
|
this.pc2.addEventListener('icecandidate', async (e) => {
|
|
9413
9448
|
await this.pc1.addIceCandidate(e.candidate);
|
|
9414
9449
|
});
|
|
9450
|
+
this.pc2.addEventListener('track', (e) => {
|
|
9451
|
+
e.streams[0].getTracks().forEach((track) => {
|
|
9452
|
+
// In RN, the remote track is automatically added to the audio output device
|
|
9453
|
+
// so we need to mute it to avoid hearing the audio back
|
|
9454
|
+
// @ts-ignore _setVolume is a private method in react-native-webrtc
|
|
9455
|
+
track._setVolume(0);
|
|
9456
|
+
});
|
|
9457
|
+
});
|
|
9415
9458
|
audioStream
|
|
9416
9459
|
.getTracks()
|
|
9417
9460
|
.forEach((track) => this.pc1.addTrack(track, audioStream));
|
|
@@ -9421,12 +9464,16 @@ class RNSpeechDetector {
|
|
|
9421
9464
|
const answer = await this.pc2.createAnswer();
|
|
9422
9465
|
await this.pc1.setRemoteDescription(answer);
|
|
9423
9466
|
await this.pc2.setLocalDescription(answer);
|
|
9424
|
-
const
|
|
9425
|
-
|
|
9426
|
-
|
|
9467
|
+
const unsub = this.onSpeakingDetectedStateChange(onSoundDetectedStateChanged);
|
|
9468
|
+
return () => {
|
|
9469
|
+
unsub();
|
|
9470
|
+
this.stop();
|
|
9471
|
+
};
|
|
9427
9472
|
}
|
|
9428
9473
|
catch (error) {
|
|
9429
|
-
|
|
9474
|
+
const logger = getLogger(['RNSpeechDetector']);
|
|
9475
|
+
logger('error', 'error handling permissions: ', error);
|
|
9476
|
+
return () => { };
|
|
9430
9477
|
}
|
|
9431
9478
|
}
|
|
9432
9479
|
/**
|
|
@@ -9436,40 +9483,85 @@ class RNSpeechDetector {
|
|
|
9436
9483
|
this.pc1.close();
|
|
9437
9484
|
this.pc2.close();
|
|
9438
9485
|
this.cleanupAudioStream();
|
|
9439
|
-
if (this.intervalId) {
|
|
9440
|
-
clearInterval(this.intervalId);
|
|
9441
|
-
}
|
|
9442
9486
|
}
|
|
9443
9487
|
/**
|
|
9444
9488
|
* Public method that detects the audio levels and returns the status.
|
|
9445
9489
|
*/
|
|
9446
9490
|
onSpeakingDetectedStateChange(onSoundDetectedStateChanged) {
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9491
|
+
const initialBaselineNoiseLevel = 0.13;
|
|
9492
|
+
let baselineNoiseLevel = initialBaselineNoiseLevel;
|
|
9493
|
+
let speechDetected = false;
|
|
9494
|
+
let intervalId;
|
|
9495
|
+
let speechTimer;
|
|
9496
|
+
let silenceTimer;
|
|
9497
|
+
let audioLevelHistory = []; // Store recent audio levels for smoother detection
|
|
9498
|
+
const historyLength = 10;
|
|
9499
|
+
const silenceThreshold = 1.1;
|
|
9500
|
+
const resetThreshold = 0.9;
|
|
9501
|
+
const speechTimeout = 500; // Speech is set to true after 500ms of audio detection
|
|
9502
|
+
const silenceTimeout = 5000; // Reset baseline after 5 seconds of silence
|
|
9503
|
+
const checkAudioLevel = async () => {
|
|
9504
|
+
try {
|
|
9505
|
+
const stats = (await this.pc1.getStats());
|
|
9506
|
+
const report = flatten(stats);
|
|
9507
|
+
// Audio levels are present inside stats of type `media-source` and of kind `audio`
|
|
9508
|
+
const audioMediaSourceStats = report.find((stat) => stat.type === 'media-source' &&
|
|
9509
|
+
stat.kind === 'audio');
|
|
9510
|
+
if (audioMediaSourceStats) {
|
|
9511
|
+
const { audioLevel } = audioMediaSourceStats;
|
|
9512
|
+
if (audioLevel) {
|
|
9513
|
+
// Update audio level history (with max historyLength sized array)
|
|
9514
|
+
audioLevelHistory.push(audioLevel);
|
|
9515
|
+
if (audioLevelHistory.length > historyLength) {
|
|
9516
|
+
audioLevelHistory.shift();
|
|
9517
|
+
}
|
|
9518
|
+
// Calculate average audio level
|
|
9519
|
+
const avgAudioLevel = audioLevelHistory.reduce((a, b) => a + b, 0) /
|
|
9520
|
+
audioLevelHistory.length;
|
|
9521
|
+
// Update baseline (if necessary) based on silence detection
|
|
9522
|
+
if (avgAudioLevel < baselineNoiseLevel * silenceThreshold) {
|
|
9523
|
+
if (!silenceTimer) {
|
|
9524
|
+
silenceTimer = setTimeout(() => {
|
|
9525
|
+
baselineNoiseLevel = Math.min(avgAudioLevel * resetThreshold, initialBaselineNoiseLevel);
|
|
9526
|
+
}, silenceTimeout);
|
|
9527
|
+
}
|
|
9528
|
+
}
|
|
9529
|
+
else {
|
|
9530
|
+
clearTimeout(silenceTimer);
|
|
9531
|
+
silenceTimer = undefined;
|
|
9532
|
+
}
|
|
9533
|
+
// Speech detection with hysteresis
|
|
9534
|
+
if (avgAudioLevel > baselineNoiseLevel * 1.5) {
|
|
9535
|
+
if (!speechDetected) {
|
|
9536
|
+
speechDetected = true;
|
|
9537
|
+
onSoundDetectedStateChanged({
|
|
9538
|
+
isSoundDetected: true,
|
|
9539
|
+
audioLevel,
|
|
9540
|
+
});
|
|
9541
|
+
}
|
|
9542
|
+
clearTimeout(speechTimer);
|
|
9543
|
+
speechTimer = setTimeout(() => {
|
|
9544
|
+
speechDetected = false;
|
|
9545
|
+
onSoundDetectedStateChanged({
|
|
9546
|
+
isSoundDetected: false,
|
|
9547
|
+
audioLevel: 0,
|
|
9548
|
+
});
|
|
9549
|
+
}, speechTimeout);
|
|
9550
|
+
}
|
|
9467
9551
|
}
|
|
9468
9552
|
}
|
|
9469
9553
|
}
|
|
9470
|
-
|
|
9554
|
+
catch (error) {
|
|
9555
|
+
const logger = getLogger(['RNSpeechDetector']);
|
|
9556
|
+
logger('error', 'error checking audio level from stats', error);
|
|
9557
|
+
}
|
|
9558
|
+
};
|
|
9559
|
+
// Call checkAudioLevel periodically (every 100ms)
|
|
9560
|
+
intervalId = setInterval(checkAudioLevel, 100);
|
|
9471
9561
|
return () => {
|
|
9472
|
-
clearInterval(
|
|
9562
|
+
clearInterval(intervalId);
|
|
9563
|
+
clearTimeout(speechTimer);
|
|
9564
|
+
clearTimeout(silenceTimer);
|
|
9473
9565
|
};
|
|
9474
9566
|
}
|
|
9475
9567
|
cleanupAudioStream() {
|
|
@@ -9487,9 +9579,7 @@ class RNSpeechDetector {
|
|
|
9487
9579
|
}
|
|
9488
9580
|
|
|
9489
9581
|
class MicrophoneManager extends InputMediaDeviceManager {
|
|
9490
|
-
constructor(call, disableMode =
|
|
9491
|
-
? 'disable-tracks'
|
|
9492
|
-
: 'stop-tracks') {
|
|
9582
|
+
constructor(call, disableMode = 'stop-tracks') {
|
|
9493
9583
|
super(call, new MicrophoneManagerState(disableMode), TrackType.AUDIO);
|
|
9494
9584
|
this.speakingWhileMutedNotificationEnabled = true;
|
|
9495
9585
|
this.soundDetectorConcurrencyTag = Symbol('soundDetectorConcurrencyTag');
|
|
@@ -9670,13 +9760,11 @@ class MicrophoneManager extends InputMediaDeviceManager {
|
|
|
9670
9760
|
await this.stopSpeakingWhileMutedDetection();
|
|
9671
9761
|
if (isReactNative()) {
|
|
9672
9762
|
this.rnSpeechDetector = new RNSpeechDetector();
|
|
9673
|
-
await this.rnSpeechDetector.start()
|
|
9674
|
-
const unsubscribe = this.rnSpeechDetector?.onSpeakingDetectedStateChange((event) => {
|
|
9763
|
+
const unsubscribe = await this.rnSpeechDetector.start((event) => {
|
|
9675
9764
|
this.state.setSpeakingWhileMuted(event.isSoundDetected);
|
|
9676
9765
|
});
|
|
9677
9766
|
this.soundDetectorCleanup = () => {
|
|
9678
9767
|
unsubscribe();
|
|
9679
|
-
this.rnSpeechDetector?.stop();
|
|
9680
9768
|
this.rnSpeechDetector = undefined;
|
|
9681
9769
|
};
|
|
9682
9770
|
}
|
|
@@ -10359,6 +10447,12 @@ class Call {
|
|
|
10359
10447
|
this.create = async (data) => {
|
|
10360
10448
|
return this.getOrCreate(data);
|
|
10361
10449
|
};
|
|
10450
|
+
/**
|
|
10451
|
+
* Deletes the call.
|
|
10452
|
+
*/
|
|
10453
|
+
this.delete = async (data = {}) => {
|
|
10454
|
+
return this.streamClient.post(`${this.streamClientBasePath}/delete`, data);
|
|
10455
|
+
};
|
|
10362
10456
|
/**
|
|
10363
10457
|
* A shortcut for {@link Call.get} with `ring` parameter set to `true`.
|
|
10364
10458
|
* Will send a `call.ring` event to the call members.
|
|
@@ -11369,8 +11463,8 @@ class Call {
|
|
|
11369
11463
|
/**
|
|
11370
11464
|
* Stops the livestreaming of the call.
|
|
11371
11465
|
*/
|
|
11372
|
-
this.stopLive = async () => {
|
|
11373
|
-
return this.streamClient.post(`${this.streamClientBasePath}/stop_live`,
|
|
11466
|
+
this.stopLive = async (data = {}) => {
|
|
11467
|
+
return this.streamClient.post(`${this.streamClientBasePath}/stop_live`, data);
|
|
11374
11468
|
};
|
|
11375
11469
|
/**
|
|
11376
11470
|
* Starts the broadcasting of the call.
|
|
@@ -11384,6 +11478,24 @@ class Call {
|
|
|
11384
11478
|
this.stopHLS = async () => {
|
|
11385
11479
|
return this.streamClient.post(`${this.streamClientBasePath}/stop_broadcasting`, {});
|
|
11386
11480
|
};
|
|
11481
|
+
/**
|
|
11482
|
+
* Starts the RTMP-out broadcasting of the call.
|
|
11483
|
+
*/
|
|
11484
|
+
this.startRTMPBroadcasts = async (data) => {
|
|
11485
|
+
return this.streamClient.post(`${this.streamClientBasePath}/rtmp_broadcasts`, data);
|
|
11486
|
+
};
|
|
11487
|
+
/**
|
|
11488
|
+
* Stops all RTMP-out broadcasting of the call.
|
|
11489
|
+
*/
|
|
11490
|
+
this.stopAllRTMPBroadcasts = async () => {
|
|
11491
|
+
return this.streamClient.post(`${this.streamClientBasePath}/rtmp_broadcasts/stop`);
|
|
11492
|
+
};
|
|
11493
|
+
/**
|
|
11494
|
+
* Stops the RTMP-out broadcasting of the call specified by it's name.
|
|
11495
|
+
*/
|
|
11496
|
+
this.stopRTMPBroadcast = async (name) => {
|
|
11497
|
+
return this.streamClient.post(`${this.streamClientBasePath}/rtmp_broadcasts/${name}/stop`);
|
|
11498
|
+
};
|
|
11387
11499
|
/**
|
|
11388
11500
|
* Updates the call settings or custom data.
|
|
11389
11501
|
*
|
|
@@ -12862,7 +12974,7 @@ class StreamClient {
|
|
|
12862
12974
|
return await this.wsConnection.connect(this.defaultWSTimeout);
|
|
12863
12975
|
};
|
|
12864
12976
|
this.getUserAgent = () => {
|
|
12865
|
-
const version = "1.
|
|
12977
|
+
const version = "1.16.0";
|
|
12866
12978
|
return (this.userAgent ||
|
|
12867
12979
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
12868
12980
|
};
|
|
@@ -13371,5 +13483,5 @@ class StreamVideoClient {
|
|
|
13371
13483
|
}
|
|
13372
13484
|
StreamVideoClient._instanceMap = new Map();
|
|
13373
13485
|
|
|
13374
|
-
export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum,
|
|
13486
|
+
export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestClosedCaptionModeEnum, TranscriptionSettingsRequestLanguageEnum, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseClosedCaptionModeEnum, TranscriptionSettingsResponseLanguageEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioBrowserPermission, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceInfo, getDeviceState, getLogLevel, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoBrowserPermission, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setPowerState, setSdkInfo, setThermalState, setWebRTCInfo, speakerLayoutSortPreset, speaking };
|
|
13375
13487
|
//# sourceMappingURL=index.es.js.map
|