@stream-io/video-client 1.4.1 → 1.4.3
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 +219 -144
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +219 -142
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +219 -144
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +7 -7
- package/dist/src/StreamSfuClient.d.ts +7 -7
- package/dist/src/StreamVideoClient.d.ts +5 -5
- package/dist/src/coordinator/connection/client.d.ts +13 -14
- package/dist/src/coordinator/connection/connection.d.ts +3 -5
- package/dist/src/coordinator/connection/insights.d.ts +0 -1
- package/dist/src/devices/BrowserPermission.d.ts +24 -0
- package/dist/src/devices/InputMediaDeviceManagerState.d.ts +3 -3
- package/dist/src/devices/devices.d.ts +30 -11
- package/dist/src/gen/coordinator/index.d.ts +5 -0
- package/dist/src/helpers/ViewportTracker.d.ts +1 -1
- package/dist/src/helpers/lazy.d.ts +4 -0
- package/dist/src/helpers/sdp-munging.d.ts +2 -2
- package/dist/src/rtc/Dispatcher.d.ts +2 -2
- package/dist/src/rtc/codecs.d.ts +1 -1
- package/dist/src/rtc/signal.d.ts +0 -1
- package/dist/src/stats/utils.d.ts +4 -4
- package/dist/src/store/CallState.d.ts +1 -1
- package/package.json +4 -4
- package/src/devices/BrowserPermission.ts +152 -0
- package/src/devices/CameraManagerState.ts +2 -6
- package/src/devices/InputMediaDeviceManagerState.ts +10 -44
- package/src/devices/MicrophoneManagerState.ts +2 -6
- package/src/devices/__tests__/CameraManager.test.ts +3 -0
- package/src/devices/__tests__/InputMediaDeviceManager.test.ts +5 -3
- package/src/devices/__tests__/InputMediaDeviceManagerFilters.test.ts +6 -2
- package/src/devices/__tests__/InputMediaDeviceManagerState.test.ts +41 -51
- package/src/devices/__tests__/MicrophoneManager.test.ts +4 -1
- package/src/devices/__tests__/MicrophoneManagerRN.test.ts +8 -1
- package/src/devices/__tests__/SpeakerManager.test.ts +8 -1
- package/src/devices/__tests__/mocks.ts +6 -1
- package/src/devices/devices.ts +113 -112
- package/src/gen/coordinator/index.ts +5 -0
- package/src/helpers/RNSpeechDetector.ts +1 -1
- package/src/helpers/lazy.ts +15 -0
package/dist/index.es.js
CHANGED
|
@@ -4,7 +4,7 @@ import { ServiceType, stackIntercept } from '@protobuf-ts/runtime-rpc';
|
|
|
4
4
|
import axios, { AxiosHeaders } from 'axios';
|
|
5
5
|
export { AxiosError } from 'axios';
|
|
6
6
|
import { TwirpFetchTransport } from '@protobuf-ts/twirp-transport';
|
|
7
|
-
import { ReplaySubject, combineLatest, BehaviorSubject, map as map$1, shareReplay, distinctUntilChanged, takeWhile, distinctUntilKeyChanged, merge, from,
|
|
7
|
+
import { ReplaySubject, combineLatest, BehaviorSubject, map as map$1, shareReplay, distinctUntilChanged, takeWhile, distinctUntilKeyChanged, fromEventPattern, startWith, concatMap, merge, from, fromEvent, debounceTime, pairwise, of, filter, debounce, timer } from 'rxjs';
|
|
8
8
|
import * as SDP from 'sdp-transform';
|
|
9
9
|
import { UAParser } from 'ua-parser-js';
|
|
10
10
|
import WebSocket from 'isomorphic-ws';
|
|
@@ -123,6 +123,11 @@ const RecordSettingsRequestQualityEnum = {
|
|
|
123
123
|
_720P: '720p',
|
|
124
124
|
_1080P: '1080p',
|
|
125
125
|
_1440P: '1440p',
|
|
126
|
+
PORTRAIT_360X640: 'portrait-360x640',
|
|
127
|
+
PORTRAIT_480X854: 'portrait-480x854',
|
|
128
|
+
PORTRAIT_720X1280: 'portrait-720x1280',
|
|
129
|
+
PORTRAIT_1080X1920: 'portrait-1080x1920',
|
|
130
|
+
PORTRAIT_1440X2560: 'portrait-1440x2560',
|
|
126
131
|
};
|
|
127
132
|
/**
|
|
128
133
|
* @export
|
|
@@ -10808,6 +10813,127 @@ const CallTypes = new CallTypesRegistry([
|
|
|
10808
10813
|
}),
|
|
10809
10814
|
]);
|
|
10810
10815
|
|
|
10816
|
+
class BrowserPermission {
|
|
10817
|
+
constructor(permission) {
|
|
10818
|
+
this.permission = permission;
|
|
10819
|
+
this.disposeController = new AbortController();
|
|
10820
|
+
this.wasPrompted = false;
|
|
10821
|
+
this.listeners = new Set();
|
|
10822
|
+
this.logger = getLogger(['permissions']);
|
|
10823
|
+
const signal = this.disposeController.signal;
|
|
10824
|
+
this.ready = (async () => {
|
|
10825
|
+
const assumeGranted = (error) => {
|
|
10826
|
+
this.logger('warn', "Can't query permissions, assuming granted", {
|
|
10827
|
+
permission,
|
|
10828
|
+
error,
|
|
10829
|
+
});
|
|
10830
|
+
this.setState('granted');
|
|
10831
|
+
};
|
|
10832
|
+
if (!canQueryPermissions()) {
|
|
10833
|
+
return assumeGranted();
|
|
10834
|
+
}
|
|
10835
|
+
try {
|
|
10836
|
+
const status = await navigator.permissions.query({
|
|
10837
|
+
name: permission.queryName,
|
|
10838
|
+
});
|
|
10839
|
+
if (!signal.aborted) {
|
|
10840
|
+
this.setState(status.state);
|
|
10841
|
+
status.addEventListener('change', () => this.setState(status.state), {
|
|
10842
|
+
signal,
|
|
10843
|
+
});
|
|
10844
|
+
}
|
|
10845
|
+
}
|
|
10846
|
+
catch (err) {
|
|
10847
|
+
assumeGranted(err);
|
|
10848
|
+
}
|
|
10849
|
+
})();
|
|
10850
|
+
}
|
|
10851
|
+
dispose() {
|
|
10852
|
+
this.state = undefined;
|
|
10853
|
+
this.disposeController.abort();
|
|
10854
|
+
}
|
|
10855
|
+
async getState() {
|
|
10856
|
+
await this.ready;
|
|
10857
|
+
if (!this.state) {
|
|
10858
|
+
throw new Error('BrowserPermission instance possibly disposed');
|
|
10859
|
+
}
|
|
10860
|
+
return this.state;
|
|
10861
|
+
}
|
|
10862
|
+
async prompt({ forcePrompt = false, throwOnNotAllowed = false, } = {}) {
|
|
10863
|
+
await withoutConcurrency(`permission-prompt-${this.permission.queryName}`, async () => {
|
|
10864
|
+
if ((await this.getState()) !== 'prompt' ||
|
|
10865
|
+
(this.wasPrompted && !forcePrompt)) {
|
|
10866
|
+
const isGranted = this.state === 'granted';
|
|
10867
|
+
if (!isGranted && throwOnNotAllowed) {
|
|
10868
|
+
throw new DOMException('Permission was not granted previously, and prompting again is not allowed', 'NotAllowedError');
|
|
10869
|
+
}
|
|
10870
|
+
return isGranted;
|
|
10871
|
+
}
|
|
10872
|
+
try {
|
|
10873
|
+
this.wasPrompted = true;
|
|
10874
|
+
const stream = await navigator.mediaDevices.getUserMedia(this.permission.constraints);
|
|
10875
|
+
disposeOfMediaStream(stream);
|
|
10876
|
+
return true;
|
|
10877
|
+
}
|
|
10878
|
+
catch (e) {
|
|
10879
|
+
if (e instanceof DOMException && e.name === 'NotAllowedError') {
|
|
10880
|
+
this.logger('info', 'Browser permission was not granted', {
|
|
10881
|
+
permission: this.permission,
|
|
10882
|
+
});
|
|
10883
|
+
if (throwOnNotAllowed) {
|
|
10884
|
+
throw e;
|
|
10885
|
+
}
|
|
10886
|
+
return false;
|
|
10887
|
+
}
|
|
10888
|
+
this.logger('error', `Failed to getUserMedia`, {
|
|
10889
|
+
error: e,
|
|
10890
|
+
permission: this.permission,
|
|
10891
|
+
});
|
|
10892
|
+
throw e;
|
|
10893
|
+
}
|
|
10894
|
+
});
|
|
10895
|
+
}
|
|
10896
|
+
listen(cb) {
|
|
10897
|
+
this.listeners.add(cb);
|
|
10898
|
+
if (this.state)
|
|
10899
|
+
cb(this.state);
|
|
10900
|
+
return () => this.listeners.delete(cb);
|
|
10901
|
+
}
|
|
10902
|
+
asObservable() {
|
|
10903
|
+
return fromEventPattern((handler) => this.listen(handler), (handler, unlisten) => unlisten()).pipe(
|
|
10904
|
+
// In some browsers, the 'change' event doesn't reliably emit and hence,
|
|
10905
|
+
// permissionState stays in 'prompt' state forever.
|
|
10906
|
+
// Typically, this happens when a user grants one-time permission.
|
|
10907
|
+
// Instead of checking if a permission is granted, we check if it isn't denied
|
|
10908
|
+
map$1((state) => state !== 'denied'));
|
|
10909
|
+
}
|
|
10910
|
+
setState(state) {
|
|
10911
|
+
if (this.state !== state) {
|
|
10912
|
+
this.state = state;
|
|
10913
|
+
this.listeners.forEach((listener) => listener(state));
|
|
10914
|
+
}
|
|
10915
|
+
}
|
|
10916
|
+
}
|
|
10917
|
+
function canQueryPermissions() {
|
|
10918
|
+
return (!isReactNative() &&
|
|
10919
|
+
typeof navigator !== 'undefined' &&
|
|
10920
|
+
!!navigator.permissions?.query);
|
|
10921
|
+
}
|
|
10922
|
+
|
|
10923
|
+
const uninitialized = Symbol('uninitialized');
|
|
10924
|
+
/**
|
|
10925
|
+
* Lazily creates a value using a provided factory
|
|
10926
|
+
*/
|
|
10927
|
+
function lazy(factory) {
|
|
10928
|
+
let value = uninitialized;
|
|
10929
|
+
return () => {
|
|
10930
|
+
if (value === uninitialized) {
|
|
10931
|
+
value = factory();
|
|
10932
|
+
}
|
|
10933
|
+
return value;
|
|
10934
|
+
};
|
|
10935
|
+
}
|
|
10936
|
+
|
|
10811
10937
|
/**
|
|
10812
10938
|
* Returns an Observable that emits the list of available devices
|
|
10813
10939
|
* that meet the given constraints.
|
|
@@ -10815,44 +10941,23 @@ const CallTypes = new CallTypesRegistry([
|
|
|
10815
10941
|
* @param constraints the constraints to use when requesting the devices.
|
|
10816
10942
|
* @param kind the kind of devices to enumerate.
|
|
10817
10943
|
*/
|
|
10818
|
-
const getDevices = (
|
|
10819
|
-
return
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
10829
|
-
|
|
10830
|
-
devices = await navigator.mediaDevices.enumerateDevices();
|
|
10831
|
-
}
|
|
10832
|
-
finally {
|
|
10833
|
-
if (mediaStream)
|
|
10834
|
-
disposeOfMediaStream(mediaStream);
|
|
10835
|
-
}
|
|
10836
|
-
}
|
|
10837
|
-
return devices;
|
|
10838
|
-
};
|
|
10839
|
-
enumerate()
|
|
10840
|
-
.then((devices) => {
|
|
10841
|
-
// notify subscribers and complete
|
|
10842
|
-
subscriber.next(devices);
|
|
10843
|
-
subscriber.complete();
|
|
10844
|
-
})
|
|
10845
|
-
.catch((error) => {
|
|
10846
|
-
const logger = getLogger(['devices']);
|
|
10847
|
-
logger('error', 'Failed to enumerate devices', error);
|
|
10848
|
-
subscriber.error(error);
|
|
10849
|
-
});
|
|
10850
|
-
});
|
|
10944
|
+
const getDevices = (permission, kind) => {
|
|
10945
|
+
return from((async () => {
|
|
10946
|
+
let devices = await navigator.mediaDevices.enumerateDevices();
|
|
10947
|
+
// for privacy reasons, most browsers don't give you device labels
|
|
10948
|
+
// unless you have a corresponding camera or microphone permission
|
|
10949
|
+
const shouldPromptForBrowserPermission = devices.some((device) => device.kind === kind && device.label === '');
|
|
10950
|
+
if (shouldPromptForBrowserPermission) {
|
|
10951
|
+
await permission.prompt({ throwOnNotAllowed: true });
|
|
10952
|
+
devices = await navigator.mediaDevices.enumerateDevices();
|
|
10953
|
+
}
|
|
10954
|
+
return devices.filter((d) => d.kind === kind);
|
|
10955
|
+
})());
|
|
10851
10956
|
};
|
|
10852
10957
|
/**
|
|
10853
|
-
*
|
|
10854
|
-
*
|
|
10855
|
-
|
|
10958
|
+
* Tells if the browser supports audio output change on 'audio' elements,
|
|
10959
|
+
* see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId.
|
|
10960
|
+
*/
|
|
10856
10961
|
const checkIfAudioOutputChangeSupported = () => {
|
|
10857
10962
|
if (typeof document === 'undefined')
|
|
10858
10963
|
return false;
|
|
@@ -10879,72 +10984,57 @@ const videoDeviceConstraints = {
|
|
|
10879
10984
|
},
|
|
10880
10985
|
};
|
|
10881
10986
|
/**
|
|
10882
|
-
*
|
|
10883
|
-
*
|
|
10884
|
-
|
|
10885
|
-
|
|
10886
|
-
|
|
10887
|
-
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
10891
|
-
|
|
10892
|
-
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
//
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
const notify = () => subscriber.next();
|
|
10904
|
-
navigator.mediaDevices.addEventListener('devicechange', notify);
|
|
10905
|
-
return () => {
|
|
10906
|
-
navigator.mediaDevices.removeEventListener('devicechange', notify);
|
|
10907
|
-
};
|
|
10908
|
-
}).pipe(debounceTime(500), concatMap(() => from(navigator.mediaDevices.enumerateDevices())), shareReplay(1));
|
|
10909
|
-
});
|
|
10910
|
-
const getAudioDevicesObserver = memoizedObservable(() => {
|
|
10911
|
-
return merge(getDevices(audioDeviceConstraints, 'audioinput'), getDeviceChangeObserver()).pipe(shareReplay(1));
|
|
10912
|
-
});
|
|
10913
|
-
const getAudioOutputDevicesObserver = memoizedObservable(() => {
|
|
10914
|
-
return merge(getDevices(audioDeviceConstraints, 'audiooutput'), getDeviceChangeObserver()).pipe(shareReplay(1));
|
|
10915
|
-
});
|
|
10916
|
-
const getVideoDevicesObserver = memoizedObservable(() => {
|
|
10917
|
-
return merge(getDevices(videoDeviceConstraints, 'videoinput'), getDeviceChangeObserver()).pipe(shareReplay(1));
|
|
10987
|
+
* Keeps track of the browser permission to use microphone. This permission also
|
|
10988
|
+
* affects an ability to enumerate audio devices.
|
|
10989
|
+
*/
|
|
10990
|
+
const getAudioBrowserPermission = lazy(() => new BrowserPermission({
|
|
10991
|
+
constraints: audioDeviceConstraints,
|
|
10992
|
+
queryName: 'microphone',
|
|
10993
|
+
}));
|
|
10994
|
+
/**
|
|
10995
|
+
* Keeps track of the browser permission to use camera. This permission also
|
|
10996
|
+
* affects an ability to enumerate video devices.
|
|
10997
|
+
*/
|
|
10998
|
+
const getVideoBrowserPermission = lazy(() => new BrowserPermission({
|
|
10999
|
+
constraints: videoDeviceConstraints,
|
|
11000
|
+
queryName: 'camera',
|
|
11001
|
+
}));
|
|
11002
|
+
const getDeviceChangeObserver = lazy(() => {
|
|
11003
|
+
// 'addEventListener' is not available in React Native, returning
|
|
11004
|
+
// an observable that will never fire
|
|
11005
|
+
if (!navigator.mediaDevices.addEventListener)
|
|
11006
|
+
return from([]);
|
|
11007
|
+
return fromEvent(navigator.mediaDevices, 'devicechange').pipe(map$1(() => undefined), debounceTime(500));
|
|
10918
11008
|
});
|
|
10919
11009
|
/**
|
|
10920
|
-
* Prompts the user for a permission to use audio devices (if not already granted
|
|
11010
|
+
* Prompts the user for a permission to use audio devices (if not already granted
|
|
11011
|
+
* and was not prompted before) and lists the available 'audioinput' devices,
|
|
11012
|
+
* if devices are added/removed the list is updated, and if the permission is revoked,
|
|
11013
|
+
* the observable errors.
|
|
10921
11014
|
*/
|
|
10922
|
-
const getAudioDevices = () => {
|
|
10923
|
-
return
|
|
10924
|
-
};
|
|
11015
|
+
const getAudioDevices = lazy(() => {
|
|
11016
|
+
return merge(getDeviceChangeObserver(), getAudioBrowserPermission().asObservable()).pipe(startWith(undefined), concatMap(() => getDevices(getAudioBrowserPermission(), 'audioinput')), shareReplay(1));
|
|
11017
|
+
});
|
|
10925
11018
|
/**
|
|
10926
|
-
* Prompts the user for a permission to use video devices (if not already granted
|
|
11019
|
+
* Prompts the user for a permission to use video devices (if not already granted
|
|
11020
|
+
* and was not prompted before) and lists the available 'videoinput' devices,
|
|
11021
|
+
* if devices are added/removed the list is updated, and if the permission is revoked,
|
|
11022
|
+
* the observable errors.
|
|
10927
11023
|
*/
|
|
10928
11024
|
const getVideoDevices = () => {
|
|
10929
|
-
return
|
|
11025
|
+
return merge(getDeviceChangeObserver(), getVideoBrowserPermission().asObservable()).pipe(startWith(undefined), concatMap(() => getDevices(getVideoBrowserPermission(), 'videoinput')), shareReplay(1));
|
|
10930
11026
|
};
|
|
10931
11027
|
/**
|
|
10932
|
-
* Prompts the user for a permission to use
|
|
11028
|
+
* Prompts the user for a permission to use video devices (if not already granted
|
|
11029
|
+
* and was not prompted before) and lists the available 'audiooutput' devices,
|
|
11030
|
+
* if devices are added/removed the list is updated, and if the permission is revoked,
|
|
11031
|
+
* the observable errors.
|
|
10933
11032
|
*/
|
|
10934
11033
|
const getAudioOutputDevices = () => {
|
|
10935
|
-
return
|
|
11034
|
+
return merge(getDeviceChangeObserver(), getAudioBrowserPermission().asObservable()).pipe(startWith(undefined), concatMap(() => getDevices(getAudioBrowserPermission(), 'audiooutput')), shareReplay(1));
|
|
10936
11035
|
};
|
|
10937
11036
|
const getStream = async (constraints) => {
|
|
10938
|
-
|
|
10939
|
-
return await navigator.mediaDevices.getUserMedia(constraints);
|
|
10940
|
-
}
|
|
10941
|
-
catch (e) {
|
|
10942
|
-
getLogger(['devices'])('error', `Failed to getUserMedia`, {
|
|
10943
|
-
error: e,
|
|
10944
|
-
constraints: constraints,
|
|
10945
|
-
});
|
|
10946
|
-
throw e;
|
|
10947
|
-
}
|
|
11037
|
+
return await navigator.mediaDevices.getUserMedia(constraints);
|
|
10948
11038
|
};
|
|
10949
11039
|
/**
|
|
10950
11040
|
* Returns an audio media stream that fulfills the given constraints.
|
|
@@ -10961,7 +11051,20 @@ const getAudioStream = async (trackConstraints) => {
|
|
|
10961
11051
|
...trackConstraints,
|
|
10962
11052
|
},
|
|
10963
11053
|
};
|
|
10964
|
-
|
|
11054
|
+
try {
|
|
11055
|
+
await getAudioBrowserPermission().prompt({
|
|
11056
|
+
throwOnNotAllowed: true,
|
|
11057
|
+
forcePrompt: true,
|
|
11058
|
+
});
|
|
11059
|
+
return getStream(constraints);
|
|
11060
|
+
}
|
|
11061
|
+
catch (e) {
|
|
11062
|
+
getLogger(['devices'])('error', 'Failed to get audio stream', {
|
|
11063
|
+
error: e,
|
|
11064
|
+
constraints: constraints,
|
|
11065
|
+
});
|
|
11066
|
+
throw e;
|
|
11067
|
+
}
|
|
10965
11068
|
};
|
|
10966
11069
|
/**
|
|
10967
11070
|
* Returns a video media stream that fulfills the given constraints.
|
|
@@ -10978,7 +11081,20 @@ const getVideoStream = async (trackConstraints) => {
|
|
|
10978
11081
|
...trackConstraints,
|
|
10979
11082
|
},
|
|
10980
11083
|
};
|
|
10981
|
-
|
|
11084
|
+
try {
|
|
11085
|
+
await getVideoBrowserPermission().prompt({
|
|
11086
|
+
throwOnNotAllowed: true,
|
|
11087
|
+
forcePrompt: true,
|
|
11088
|
+
});
|
|
11089
|
+
return getStream(constraints);
|
|
11090
|
+
}
|
|
11091
|
+
catch (e) {
|
|
11092
|
+
getLogger(['devices'])('error', 'Failed to get video stream', {
|
|
11093
|
+
error: e,
|
|
11094
|
+
constraints: constraints,
|
|
11095
|
+
});
|
|
11096
|
+
throw e;
|
|
11097
|
+
}
|
|
10982
11098
|
};
|
|
10983
11099
|
/**
|
|
10984
11100
|
* Prompts the user for a permission to share a screen.
|
|
@@ -11014,7 +11130,7 @@ const getScreenShareStream = async (options) => {
|
|
|
11014
11130
|
};
|
|
11015
11131
|
const deviceIds$ = typeof navigator !== 'undefined' &&
|
|
11016
11132
|
typeof navigator.mediaDevices !== 'undefined'
|
|
11017
|
-
?
|
|
11133
|
+
? getDeviceChangeObserver().pipe(startWith(undefined), concatMap(() => navigator.mediaDevices.enumerateDevices()), shareReplay(1))
|
|
11018
11134
|
: undefined;
|
|
11019
11135
|
/**
|
|
11020
11136
|
* Deactivates MediaStream (stops and removes tracks) to be later garbage collected
|
|
@@ -11397,12 +11513,11 @@ class InputMediaDeviceManagerState {
|
|
|
11397
11513
|
* Constructs new InputMediaDeviceManagerState instance.
|
|
11398
11514
|
*
|
|
11399
11515
|
* @param disableMode the disable mode to use.
|
|
11400
|
-
* @param
|
|
11516
|
+
* @param permission the BrowserPermission to use for querying.
|
|
11401
11517
|
* `undefined` means no permission is required.
|
|
11402
11518
|
*/
|
|
11403
|
-
constructor(disableMode = 'stop-tracks',
|
|
11519
|
+
constructor(disableMode = 'stop-tracks', permission) {
|
|
11404
11520
|
this.disableMode = disableMode;
|
|
11405
|
-
this.permissionName = permissionName;
|
|
11406
11521
|
this.statusSubject = new BehaviorSubject(undefined);
|
|
11407
11522
|
this.optimisticStatusSubject = new BehaviorSubject(undefined);
|
|
11408
11523
|
this.mediaStreamSubject = new BehaviorSubject(undefined);
|
|
@@ -11433,43 +11548,6 @@ class InputMediaDeviceManagerState {
|
|
|
11433
11548
|
* The default constraints for the device.
|
|
11434
11549
|
*/
|
|
11435
11550
|
this.defaultConstraints$ = this.defaultConstraintsSubject.asObservable();
|
|
11436
|
-
/**
|
|
11437
|
-
* An observable that will emit `true` if browser/system permission
|
|
11438
|
-
* is granted, `false` otherwise.
|
|
11439
|
-
*/
|
|
11440
|
-
this.hasBrowserPermission$ = new Observable((subscriber) => {
|
|
11441
|
-
const notifyGranted = () => subscriber.next(true);
|
|
11442
|
-
const permissionsAPIAvailable = !!navigator?.permissions?.query;
|
|
11443
|
-
if (isReactNative() || !this.permissionName || !permissionsAPIAvailable) {
|
|
11444
|
-
getLogger(['devices'])('warn', `Permissions can't be queried. Assuming granted.`);
|
|
11445
|
-
return notifyGranted();
|
|
11446
|
-
}
|
|
11447
|
-
let permissionState;
|
|
11448
|
-
const notify = () => {
|
|
11449
|
-
subscriber.next(
|
|
11450
|
-
// In some browsers, the 'change' event doesn't reliably emit and hence,
|
|
11451
|
-
// permissionState stays in 'prompt' state forever.
|
|
11452
|
-
// Typically, this happens when a user grants one-time permission.
|
|
11453
|
-
// Instead of checking if a permission is granted, we check if it isn't denied
|
|
11454
|
-
permissionState.state !== 'denied');
|
|
11455
|
-
};
|
|
11456
|
-
navigator.permissions
|
|
11457
|
-
.query({ name: this.permissionName })
|
|
11458
|
-
.then((permissionStatus) => {
|
|
11459
|
-
permissionState = permissionStatus;
|
|
11460
|
-
permissionState.addEventListener('change', notify);
|
|
11461
|
-
notify();
|
|
11462
|
-
})
|
|
11463
|
-
.catch(() => {
|
|
11464
|
-
// permission doesn't exist or can't be queried -> assume it's granted
|
|
11465
|
-
// an example would be Firefox,
|
|
11466
|
-
// where neither camera microphone permission can be queried
|
|
11467
|
-
notifyGranted();
|
|
11468
|
-
});
|
|
11469
|
-
return () => {
|
|
11470
|
-
permissionState?.removeEventListener('change', notify);
|
|
11471
|
-
};
|
|
11472
|
-
}).pipe(shareReplay(1));
|
|
11473
11551
|
/**
|
|
11474
11552
|
* Gets the current value of an observable, or undefined if the observable has
|
|
11475
11553
|
* not emitted a value yet.
|
|
@@ -11489,6 +11567,9 @@ class InputMediaDeviceManagerState {
|
|
|
11489
11567
|
* @return the updated value.
|
|
11490
11568
|
*/
|
|
11491
11569
|
this.setCurrentValue = setCurrentValue;
|
|
11570
|
+
this.hasBrowserPermission$ = permission
|
|
11571
|
+
? permission.asObservable().pipe(shareReplay(1))
|
|
11572
|
+
: of(true);
|
|
11492
11573
|
}
|
|
11493
11574
|
/**
|
|
11494
11575
|
* The device status
|
|
@@ -11568,10 +11649,7 @@ class InputMediaDeviceManagerState {
|
|
|
11568
11649
|
|
|
11569
11650
|
class CameraManagerState extends InputMediaDeviceManagerState {
|
|
11570
11651
|
constructor() {
|
|
11571
|
-
super('stop-tracks',
|
|
11572
|
-
// `camera` is not in the W3C standard yet,
|
|
11573
|
-
// but it's supported by Chrome and Safari.
|
|
11574
|
-
'camera');
|
|
11652
|
+
super('stop-tracks', getVideoBrowserPermission());
|
|
11575
11653
|
this.directionSubject = new BehaviorSubject(undefined);
|
|
11576
11654
|
this.direction$ = this.directionSubject
|
|
11577
11655
|
.asObservable()
|
|
@@ -11702,10 +11780,7 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
11702
11780
|
|
|
11703
11781
|
class MicrophoneManagerState extends InputMediaDeviceManagerState {
|
|
11704
11782
|
constructor(disableMode) {
|
|
11705
|
-
super(disableMode,
|
|
11706
|
-
// `microphone` is not in the W3C standard yet,
|
|
11707
|
-
// but it's supported by Chrome and Safari.
|
|
11708
|
-
'microphone');
|
|
11783
|
+
super(disableMode, getAudioBrowserPermission());
|
|
11709
11784
|
this.speakingWhileMutedSubject = new BehaviorSubject(false);
|
|
11710
11785
|
this.speakingWhileMuted$ = this.speakingWhileMutedSubject
|
|
11711
11786
|
.asObservable()
|
|
@@ -15408,7 +15483,7 @@ class StreamClient {
|
|
|
15408
15483
|
});
|
|
15409
15484
|
};
|
|
15410
15485
|
this.getUserAgent = () => {
|
|
15411
|
-
const version = "1.4.
|
|
15486
|
+
const version = "1.4.3" ;
|
|
15412
15487
|
return (this.userAgent ||
|
|
15413
15488
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
15414
15489
|
};
|
|
@@ -15887,5 +15962,5 @@ class StreamVideoClient {
|
|
|
15887
15962
|
}
|
|
15888
15963
|
}
|
|
15889
15964
|
|
|
15890
|
-
export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, BlockListOptionsBehaviorEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, ChannelConfigWithInfoAutomodBehaviorEnum, ChannelConfigWithInfoAutomodEnum, ChannelConfigWithInfoBlocklistBehaviorEnum, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceInfo, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setSdkInfo, setWebRTCInfo, speakerLayoutSortPreset, speaking };
|
|
15965
|
+
export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, BlockListOptionsBehaviorEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, ChannelConfigWithInfoAutomodBehaviorEnum, ChannelConfigWithInfoAutomodEnum, ChannelConfigWithInfoBlocklistBehaviorEnum, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioBrowserPermission, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceInfo, 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, setSdkInfo, setWebRTCInfo, speakerLayoutSortPreset, speaking };
|
|
15891
15966
|
//# sourceMappingURL=index.es.js.map
|