@stream-io/video-react-sdk 0.0.1-alpha.46 → 0.0.1-alpha.48

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/css/styles.css +1 -3
  3. package/dist/css/styles.css.map +1 -1
  4. package/dist/src/components/CallControls/ToggleAudioButton.js +5 -3
  5. package/dist/src/components/CallControls/ToggleAudioButton.js.map +1 -1
  6. package/dist/src/components/CallControls/ToggleVideoButton.js +6 -4
  7. package/dist/src/components/CallControls/ToggleVideoButton.js.map +1 -1
  8. package/dist/src/components/DeviceSettings/DeviceSelectorAudio.js +5 -3
  9. package/dist/src/components/DeviceSettings/DeviceSelectorAudio.js.map +1 -1
  10. package/dist/src/components/DeviceSettings/DeviceSelectorVideo.js +3 -2
  11. package/dist/src/components/DeviceSettings/DeviceSelectorVideo.js.map +1 -1
  12. package/dist/src/components/Notification/SpeakingWhileMutedNotification.js +4 -2
  13. package/dist/src/components/Notification/SpeakingWhileMutedNotification.js.map +1 -1
  14. package/dist/src/components/Video/VideoPreview.js +10 -5
  15. package/dist/src/components/Video/VideoPreview.js.map +1 -1
  16. package/dist/src/core/contexts/MediaDevicesContext.d.ts +7 -8
  17. package/dist/src/core/contexts/MediaDevicesContext.js +22 -85
  18. package/dist/src/core/contexts/MediaDevicesContext.js.map +1 -1
  19. package/dist/src/core/hooks/index.d.ts +1 -0
  20. package/dist/src/core/hooks/index.js +1 -0
  21. package/dist/src/core/hooks/index.js.map +1 -1
  22. package/dist/src/core/hooks/useAudioPublisher.js +9 -3
  23. package/dist/src/core/hooks/useAudioPublisher.js.map +1 -1
  24. package/dist/src/core/hooks/useDevices.d.ts +68 -0
  25. package/dist/src/core/hooks/useDevices.js +101 -0
  26. package/dist/src/core/hooks/useDevices.js.map +1 -0
  27. package/dist/src/core/hooks/useVideoPublisher.js +35 -6
  28. package/dist/src/core/hooks/useVideoPublisher.js.map +1 -1
  29. package/package.json +5 -5
  30. package/src/components/CallControls/ToggleAudioButton.tsx +7 -3
  31. package/src/components/CallControls/ToggleVideoButton.tsx +7 -4
  32. package/src/components/DeviceSettings/DeviceSelectorAudio.tsx +9 -4
  33. package/src/components/DeviceSettings/DeviceSelectorVideo.tsx +3 -3
  34. package/src/components/Notification/SpeakingWhileMutedNotification.tsx +9 -8
  35. package/src/components/Video/VideoPreview.tsx +16 -6
  36. package/src/core/contexts/MediaDevicesContext.tsx +48 -123
  37. package/src/core/hooks/index.ts +1 -0
  38. package/src/core/hooks/useAudioPublisher.ts +9 -3
  39. package/src/core/hooks/useDevices.ts +145 -0
  40. package/src/core/hooks/useVideoPublisher.ts +36 -4
@@ -1,4 +1,5 @@
1
1
  export * from './useAudioPublisher';
2
+ export * from './useDevices';
2
3
  export * from './useVideoPublisher';
3
4
  export * from './useTrackElementVisibility';
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC"}
@@ -29,7 +29,9 @@ export const useAudioPublisher = ({ initialAudioMuted, audioDeviceId, }) => {
29
29
  throw new Error(`No permission to publish audio`);
30
30
  }
31
31
  try {
32
- const audioStream = yield getAudioStream(audioDeviceId);
32
+ const audioStream = yield getAudioStream({
33
+ deviceId: audioDeviceId,
34
+ });
33
35
  yield call.publishAudioStream(audioStream);
34
36
  }
35
37
  catch (e) {
@@ -69,12 +71,16 @@ export const useAudioPublisher = ({ initialAudioMuted, audioDeviceId, }) => {
69
71
  // We need to stop the original track first in order
70
72
  // we can retrieve the new default device stream
71
73
  track.stop();
72
- const audioStream = yield getAudioStream('default');
74
+ const audioStream = yield getAudioStream({
75
+ deviceId: 'default',
76
+ });
73
77
  yield call.publishAudioStream(audioStream);
74
78
  }));
75
79
  const handleTrackEnded = () => __awaiter(void 0, void 0, void 0, function* () {
76
80
  if (selectedAudioDeviceId === audioDeviceId) {
77
- const audioStream = yield getAudioStream(audioDeviceId);
81
+ const audioStream = yield getAudioStream({
82
+ deviceId: audioDeviceId,
83
+ });
78
84
  yield call.publishAudioStream(audioStream);
79
85
  }
80
86
  });
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioPublisher.js","sourceRoot":"","sources":["../../../../src/core/hooks/useAudioPublisher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAudioPublisher.js","sourceRoot":"","sources":["../../../../src/core/hooks/useAudioPublisher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { Observable } from 'rxjs';
2
+ /**
3
+ * Observes changes in connected devices and maintains an up-to-date array of connected MediaDeviceInfo objects.
4
+ * @param observeDevices
5
+ * @category Device Management
6
+ */
7
+ export declare const useDevices: (observeDevices: () => Observable<MediaDeviceInfo[]>) => MediaDeviceInfo[];
8
+ /**
9
+ * Observes changes and maintains an array of connected video input devices
10
+ * @category Device Management
11
+ */
12
+ export declare const useVideoDevices: () => MediaDeviceInfo[];
13
+ /**
14
+ * Observes changes and maintains an array of connected audio input devices
15
+ * @category Device Management
16
+ */
17
+ export declare const useAudioInputDevices: () => MediaDeviceInfo[];
18
+ /**
19
+ * Observes changes and maintains an array of connected audio output devices
20
+ * @category Device Management
21
+ */
22
+ export declare const useAudioOutputDevices: () => MediaDeviceInfo[];
23
+ /**
24
+ * Verifies that newly selected device id exists among the registered devices.
25
+ * If the selected device id is not found among existing devices, switches to the default device.
26
+ * @param devices$
27
+ * @param switchToDefaultDevice
28
+ * @param selectedDeviceId
29
+ * @category Device Management
30
+ */
31
+ export declare const useDeviceFallback: (devices$: Observable<MediaDeviceInfo[]>, switchToDefaultDevice: () => void, selectedDeviceId?: string) => void;
32
+ /**
33
+ * Verifies that newly selected video device id exists among the registered devices.
34
+ * If the selected device id is not found among existing devices, switches to the default video device.
35
+ * @param switchToDefaultDevice
36
+ * @param selectedDeviceId
37
+ * @category Device Management
38
+ */
39
+ export declare const useVideoDeviceFallback: (switchToDefaultDevice: () => void, selectedDeviceId?: string) => void;
40
+ /**
41
+ * Verifies that newly selected audio input device id exists among the registered devices.
42
+ * If the selected device id is not found among existing devices, switches to the default audio input device.
43
+ * @param switchToDefaultDevice
44
+ * @param selectedDeviceId
45
+ * @category Device Management
46
+ */
47
+ export declare const useAudioInputDeviceFallback: (switchToDefaultDevice: () => void, selectedDeviceId?: string) => void;
48
+ /**
49
+ * Verifies that newly selected audio output device id exists among the registered devices.
50
+ * If the selected device id is not found among existing devices, switches to the default audio output device.
51
+ * @param switchToDefaultDevice
52
+ * @param selectedDeviceId
53
+ * @category Device Management
54
+ */
55
+ export declare const useAudioOutputDeviceFallback: (switchToDefaultDevice: () => void, selectedDeviceId?: string) => void;
56
+ /**
57
+ * Observes devices of certain kind are made unavailable and executes onDisconnect callback
58
+ * @param observeDevices
59
+ * @param onDisconnect
60
+ * @category Device Management
61
+ */
62
+ export declare const useOnUnavailableDevices: (observeDevices: () => Observable<MediaDeviceInfo[]>, onDisconnect: () => void) => void;
63
+ /**
64
+ * Observes disconnect of all video devices and executes onDisconnect callback
65
+ * @param onDisconnect
66
+ * @category Device Management
67
+ */
68
+ export declare const useOnUnavailableVideoDevices: (onDisconnect: () => void) => void;
@@ -0,0 +1,101 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { pairwise } from 'rxjs';
3
+ import { getAudioDevices, getAudioOutputDevices, getVideoDevices, } from '@stream-io/video-client';
4
+ /**
5
+ * Observes changes in connected devices and maintains an up-to-date array of connected MediaDeviceInfo objects.
6
+ * @param observeDevices
7
+ * @category Device Management
8
+ */
9
+ export const useDevices = (observeDevices) => {
10
+ const [devices, setDevices] = useState([]);
11
+ useEffect(() => {
12
+ const subscription = observeDevices().subscribe(setDevices);
13
+ return () => {
14
+ subscription.unsubscribe();
15
+ };
16
+ }, [observeDevices]);
17
+ return devices;
18
+ };
19
+ /**
20
+ * Observes changes and maintains an array of connected video input devices
21
+ * @category Device Management
22
+ */
23
+ export const useVideoDevices = () => useDevices(getVideoDevices);
24
+ /**
25
+ * Observes changes and maintains an array of connected audio input devices
26
+ * @category Device Management
27
+ */
28
+ export const useAudioInputDevices = () => useDevices(getAudioDevices);
29
+ /**
30
+ * Observes changes and maintains an array of connected audio output devices
31
+ * @category Device Management
32
+ */
33
+ export const useAudioOutputDevices = () => useDevices(getAudioOutputDevices);
34
+ /**
35
+ * Verifies that newly selected device id exists among the registered devices.
36
+ * If the selected device id is not found among existing devices, switches to the default device.
37
+ * @param devices$
38
+ * @param switchToDefaultDevice
39
+ * @param selectedDeviceId
40
+ * @category Device Management
41
+ */
42
+ export const useDeviceFallback = (devices$, switchToDefaultDevice, selectedDeviceId) => {
43
+ useEffect(() => {
44
+ const validateDeviceId = devices$.pipe().subscribe((devices) => {
45
+ const deviceFound = devices.find((device) => device.deviceId === selectedDeviceId);
46
+ if (!deviceFound)
47
+ switchToDefaultDevice();
48
+ });
49
+ return () => {
50
+ validateDeviceId.unsubscribe();
51
+ };
52
+ }, [devices$, selectedDeviceId, switchToDefaultDevice]);
53
+ };
54
+ /**
55
+ * Verifies that newly selected video device id exists among the registered devices.
56
+ * If the selected device id is not found among existing devices, switches to the default video device.
57
+ * @param switchToDefaultDevice
58
+ * @param selectedDeviceId
59
+ * @category Device Management
60
+ */
61
+ export const useVideoDeviceFallback = (switchToDefaultDevice, selectedDeviceId) => useDeviceFallback(getVideoDevices(), switchToDefaultDevice, selectedDeviceId);
62
+ /**
63
+ * Verifies that newly selected audio input device id exists among the registered devices.
64
+ * If the selected device id is not found among existing devices, switches to the default audio input device.
65
+ * @param switchToDefaultDevice
66
+ * @param selectedDeviceId
67
+ * @category Device Management
68
+ */
69
+ export const useAudioInputDeviceFallback = (switchToDefaultDevice, selectedDeviceId) => useDeviceFallback(getAudioDevices(), switchToDefaultDevice, selectedDeviceId);
70
+ /**
71
+ * Verifies that newly selected audio output device id exists among the registered devices.
72
+ * If the selected device id is not found among existing devices, switches to the default audio output device.
73
+ * @param switchToDefaultDevice
74
+ * @param selectedDeviceId
75
+ * @category Device Management
76
+ */
77
+ export const useAudioOutputDeviceFallback = (switchToDefaultDevice, selectedDeviceId) => useDeviceFallback(getAudioOutputDevices(), switchToDefaultDevice, selectedDeviceId);
78
+ /**
79
+ * Observes devices of certain kind are made unavailable and executes onDisconnect callback
80
+ * @param observeDevices
81
+ * @param onDisconnect
82
+ * @category Device Management
83
+ */
84
+ export const useOnUnavailableDevices = (observeDevices, onDisconnect) => {
85
+ useEffect(() => {
86
+ const subscription = observeDevices()
87
+ .pipe(pairwise())
88
+ .subscribe(([prev, current]) => {
89
+ if (prev.length > 0 && current.length === 0)
90
+ onDisconnect();
91
+ });
92
+ return () => subscription.unsubscribe();
93
+ }, [observeDevices, onDisconnect]);
94
+ };
95
+ /**
96
+ * Observes disconnect of all video devices and executes onDisconnect callback
97
+ * @param onDisconnect
98
+ * @category Device Management
99
+ */
100
+ export const useOnUnavailableVideoDevices = (onDisconnect) => useOnUnavailableDevices(getVideoDevices, onDisconnect);
101
+ //# sourceMappingURL=useDevices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDevices.js","sourceRoot":"","sources":["../../../../src/core/hooks/useDevices.ts"],"names":[],"mappings":"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"}
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { useCallback, useEffect } from 'react';
11
11
  import { map } from 'rxjs';
12
- import { CallingState, getVideoStream, OwnCapability, SfuModels, watchForAddedDefaultVideoDevice, watchForDisconnectedVideoDevice, } from '@stream-io/video-client';
13
- import { useCall, useCallCallingState, useCallState, useLocalParticipant, } from '@stream-io/video-react-bindings';
12
+ import { CallingState, getVideoStream, OwnCapability, SfuModels, VideoSettingsCameraFacingEnum, watchForAddedDefaultVideoDevice, watchForDisconnectedVideoDevice, } from '@stream-io/video-client';
13
+ import { useCall, useCallCallingState, useCallMetadata, useCallState, useLocalParticipant, } from '@stream-io/video-react-bindings';
14
14
  import { useDebugPreferredVideoCodec } from '../../components/Debug/useIsDebugMode';
15
15
  /**
16
16
  * @internal
@@ -24,6 +24,9 @@ export const useVideoPublisher = ({ initialVideoMuted, videoDeviceId, }) => {
24
24
  const { localParticipant$ } = callState;
25
25
  const preferredCodec = useDebugPreferredVideoCodec();
26
26
  const isPublishingVideo = participant === null || participant === void 0 ? void 0 : participant.publishedTracks.includes(SfuModels.TrackType.VIDEO);
27
+ const metadata = useCallMetadata();
28
+ const videoSettings = metadata === null || metadata === void 0 ? void 0 : metadata.settings.video;
29
+ const targetResolution = videoSettings === null || videoSettings === void 0 ? void 0 : videoSettings.target_resolution;
27
30
  const publishVideoStream = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
28
31
  if (!call)
29
32
  return;
@@ -31,13 +34,25 @@ export const useVideoPublisher = ({ initialVideoMuted, videoDeviceId, }) => {
31
34
  throw new Error(`No permission to publish video`);
32
35
  }
33
36
  try {
34
- const videoStream = yield getVideoStream(videoDeviceId);
37
+ const videoStream = yield getVideoStream({
38
+ deviceId: videoDeviceId,
39
+ width: targetResolution === null || targetResolution === void 0 ? void 0 : targetResolution.width,
40
+ height: targetResolution === null || targetResolution === void 0 ? void 0 : targetResolution.height,
41
+ facingMode: toFacingMode(videoSettings === null || videoSettings === void 0 ? void 0 : videoSettings.camera_facing),
42
+ });
35
43
  yield call.publishVideoStream(videoStream, { preferredCodec });
36
44
  }
37
45
  catch (e) {
38
46
  console.log('Failed to publish video stream', e);
39
47
  }
40
- }), [call, preferredCodec, videoDeviceId]);
48
+ }), [
49
+ call,
50
+ preferredCodec,
51
+ targetResolution === null || targetResolution === void 0 ? void 0 : targetResolution.height,
52
+ targetResolution === null || targetResolution === void 0 ? void 0 : targetResolution.width,
53
+ videoDeviceId,
54
+ videoSettings === null || videoSettings === void 0 ? void 0 : videoSettings.camera_facing,
55
+ ]);
41
56
  useEffect(() => {
42
57
  if (callingState === CallingState.JOINED && !initialVideoMuted) {
43
58
  publishVideoStream().catch((e) => {
@@ -71,12 +86,16 @@ export const useVideoPublisher = ({ initialVideoMuted, videoDeviceId, }) => {
71
86
  // We need to stop the original track first in order
72
87
  // we can retrieve the new default device stream
73
88
  track.stop();
74
- const videoStream = yield getVideoStream('default');
89
+ const videoStream = yield getVideoStream({
90
+ deviceId: 'default',
91
+ });
75
92
  yield call.publishVideoStream(videoStream);
76
93
  }));
77
94
  const handleTrackEnded = () => __awaiter(void 0, void 0, void 0, function* () {
78
95
  if (selectedVideoDeviceId === videoDeviceId) {
79
- const videoStream = yield getVideoStream(videoDeviceId);
96
+ const videoStream = yield getVideoStream({
97
+ deviceId: videoDeviceId,
98
+ });
80
99
  yield call.publishVideoStream(videoStream);
81
100
  }
82
101
  });
@@ -88,4 +107,14 @@ export const useVideoPublisher = ({ initialVideoMuted, videoDeviceId, }) => {
88
107
  }, [videoDeviceId, call, participant === null || participant === void 0 ? void 0 : participant.videoStream, isPublishingVideo]);
89
108
  return publishVideoStream;
90
109
  };
110
+ const toFacingMode = (value) => {
111
+ switch (value) {
112
+ case VideoSettingsCameraFacingEnum.FRONT:
113
+ return 'user';
114
+ case VideoSettingsCameraFacingEnum.BACK:
115
+ return 'environment';
116
+ default:
117
+ return undefined;
118
+ }
119
+ };
91
120
  //# sourceMappingURL=useVideoPublisher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useVideoPublisher.js","sourceRoot":"","sources":["../../../../src/core/hooks/useVideoPublisher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useVideoPublisher.js","sourceRoot":"","sources":["../../../../src/core/hooks/useVideoPublisher.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -25,9 +25,9 @@
25
25
  "@floating-ui/react": "^0.22.0",
26
26
  "@nivo/core": "^0.80.0",
27
27
  "@nivo/line": "^0.80.0",
28
- "@stream-io/i18n": "^0.0.1-alpha.30",
29
- "@stream-io/video-client": "^0.0.1-alpha.154",
30
- "@stream-io/video-react-bindings": "^0.0.1-alpha.41",
28
+ "@stream-io/i18n": "^0.0.1-alpha.32",
29
+ "@stream-io/video-client": "^0.0.1-alpha.156",
30
+ "@stream-io/video-react-bindings": "^0.0.1-alpha.43",
31
31
  "clsx": "^1.2.1",
32
32
  "rxjs": "~7.8.1"
33
33
  },
@@ -36,7 +36,7 @@
36
36
  "react-dom": "^18.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@stream-io/video-styling": "^0.0.1-alpha.24",
39
+ "@stream-io/video-styling": "^0.0.1-alpha.26",
40
40
  "@types/rimraf": "^3.0.2",
41
41
  "react": "^18.2.0",
42
42
  "react-dom": "^18.2.0",
@@ -45,5 +45,5 @@
45
45
  "typedoc": "^0.24.7",
46
46
  "typescript": "^4.9.5"
47
47
  },
48
- "version": "0.0.1-alpha.46"
48
+ "version": "0.0.1-alpha.48"
49
49
  }
@@ -18,7 +18,8 @@ export type ToggleAudioPreviewButtonProps = { caption?: string };
18
18
  export const ToggleAudioPreviewButton = ({
19
19
  caption,
20
20
  }: ToggleAudioPreviewButtonProps) => {
21
- const { initialAudioEnabled, toggleAudioMuteState } = useMediaDevices();
21
+ const { initialAudioEnabled, toggleInitialAudioMuteState } =
22
+ useMediaDevices();
22
23
  const { t } = useI18n();
23
24
 
24
25
  return (
@@ -29,7 +30,7 @@ export const ToggleAudioPreviewButton = ({
29
30
  >
30
31
  <IconButton
31
32
  icon={initialAudioEnabled ? 'mic' : 'mic-off'}
32
- onClick={toggleAudioMuteState}
33
+ onClick={toggleInitialAudioMuteState}
33
34
  />
34
35
  </CompositeButton>
35
36
  );
@@ -42,7 +43,8 @@ export type ToggleAudioPublishingButtonProps = {
42
43
  export const ToggleAudioPublishingButton = (
43
44
  props: ToggleAudioPublishingButtonProps,
44
45
  ) => {
45
- const { publishAudioStream, stopPublishingAudio } = useMediaDevices();
46
+ const { publishAudioStream, stopPublishingAudio, setInitialAudioEnabled } =
47
+ useMediaDevices();
46
48
  const localParticipant = useLocalParticipant();
47
49
  const { t } = useI18n();
48
50
 
@@ -79,6 +81,7 @@ export const ToggleAudioPublishingButton = (
79
81
  }
80
82
  if (isAudioMute) {
81
83
  if (hasPermission) {
84
+ setInitialAudioEnabled(true);
82
85
  await publishAudioStream();
83
86
  } else {
84
87
  console.log('Cannot publish audio stream. Insufficient permissions.');
@@ -91,6 +94,7 @@ export const ToggleAudioPublishingButton = (
91
94
  hasPermission,
92
95
  isAudioMute,
93
96
  publishAudioStream,
97
+ setInitialAudioEnabled,
94
98
  stopPublishingAudio,
95
99
  ]);
96
100
 
@@ -8,7 +8,7 @@ import {
8
8
 
9
9
  import { OwnCapability, SfuModels } from '@stream-io/video-client';
10
10
  import { CompositeButton, IconButton } from '../Button/';
11
- import { useMediaDevices } from '../../core';
11
+ import { DEVICE_STATE, useMediaDevices } from '../../core';
12
12
  import { DeviceSelectorVideo } from '../DeviceSettings';
13
13
  import { PermissionNotification } from '../Notification';
14
14
 
@@ -17,7 +17,7 @@ export type ToggleVideoPreviewButtonProps = { caption?: string };
17
17
  export const ToggleVideoPreviewButton = ({
18
18
  caption = 'Video',
19
19
  }: ToggleVideoPreviewButtonProps) => {
20
- const { toggleVideoMuteState, initialVideoState } = useMediaDevices();
20
+ const { toggleInitialVideoMuteState, initialVideoState } = useMediaDevices();
21
21
 
22
22
  return (
23
23
  <CompositeButton
@@ -27,7 +27,7 @@ export const ToggleVideoPreviewButton = ({
27
27
  >
28
28
  <IconButton
29
29
  icon={initialVideoState.enabled ? 'camera' : 'camera-off'}
30
- onClick={toggleVideoMuteState}
30
+ onClick={toggleInitialVideoMuteState}
31
31
  />
32
32
  </CompositeButton>
33
33
  );
@@ -40,7 +40,8 @@ type ToggleVideoPublishingButtonProps = {
40
40
  export const ToggleVideoPublishingButton = ({
41
41
  caption = 'Video',
42
42
  }: ToggleVideoPublishingButtonProps) => {
43
- const { publishVideoStream, stopPublishingVideo } = useMediaDevices();
43
+ const { publishVideoStream, stopPublishingVideo, setInitialVideoState } =
44
+ useMediaDevices();
44
45
  const localParticipant = useLocalParticipant();
45
46
  const isVideoMute = !localParticipant?.publishedTracks.includes(
46
47
  SfuModels.TrackType.VIDEO,
@@ -73,6 +74,7 @@ export const ToggleVideoPublishingButton = ({
73
74
  }
74
75
  if (isVideoMute) {
75
76
  if (hasPermission) {
77
+ setInitialVideoState(DEVICE_STATE.playing);
76
78
  await publishVideoStream();
77
79
  } else {
78
80
  console.log('Cannot publish video. Insufficient permissions.');
@@ -85,6 +87,7 @@ export const ToggleVideoPublishingButton = ({
85
87
  hasPermission,
86
88
  isVideoMute,
87
89
  publishVideoStream,
90
+ setInitialVideoState,
88
91
  stopPublishingVideo,
89
92
  ]);
90
93
 
@@ -1,5 +1,9 @@
1
1
  import { DeviceSelector } from './DeviceSelector';
2
- import { useMediaDevices } from '../../core/contexts';
2
+ import {
3
+ useMediaDevices,
4
+ useAudioInputDevices,
5
+ useAudioOutputDevices,
6
+ } from '../../core';
3
7
 
4
8
  export type DeviceSelectorAudioInputProps = {
5
9
  title?: string;
@@ -8,8 +12,8 @@ export type DeviceSelectorAudioInputProps = {
8
12
  export const DeviceSelectorAudioInput = ({
9
13
  title = 'Select a Mic',
10
14
  }: DeviceSelectorAudioInputProps) => {
11
- const { audioInputDevices, selectedAudioInputDeviceId, switchDevice } =
12
- useMediaDevices();
15
+ const { selectedAudioInputDeviceId, switchDevice } = useMediaDevices();
16
+ const audioInputDevices = useAudioInputDevices();
13
17
 
14
18
  return (
15
19
  <DeviceSelector
@@ -31,12 +35,13 @@ export const DeviceSelectorAudioOutput = ({
31
35
  title = 'Select speakers',
32
36
  }: DeviceSelectorAudioOutputProps) => {
33
37
  const {
34
- audioOutputDevices,
35
38
  isAudioOutputChangeSupported,
36
39
  selectedAudioOutputDeviceId,
37
40
  switchDevice,
38
41
  } = useMediaDevices();
39
42
 
43
+ const audioOutputDevices = useAudioOutputDevices();
44
+
40
45
  if (!isAudioOutputChangeSupported) return null;
41
46
 
42
47
  return (
@@ -1,13 +1,13 @@
1
1
  import { DeviceSelector } from './DeviceSelector';
2
- import { useMediaDevices } from '../../core/contexts';
2
+ import { useMediaDevices, useVideoDevices } from '../../core';
3
3
 
4
4
  export type DeviceSelectorVideoProps = {
5
5
  title?: string;
6
6
  };
7
7
 
8
8
  export const DeviceSelectorVideo = ({ title }: DeviceSelectorVideoProps) => {
9
- const { videoDevices, selectedVideoDeviceId, switchDevice } =
10
- useMediaDevices();
9
+ const { selectedVideoDeviceId, switchDevice } = useMediaDevices();
10
+ const videoDevices = useVideoDevices();
11
11
 
12
12
  return (
13
13
  <DeviceSelector
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
2
2
  import { createSoundDetector, SfuModels } from '@stream-io/video-client';
3
3
  import { useLocalParticipant } from '@stream-io/video-react-bindings';
4
4
 
5
- import { useMediaDevices } from '../../core/contexts';
5
+ import { useMediaDevices } from '../../core';
6
6
  import { Notification } from './Notification';
7
7
  import { ChildrenOnly } from '../../types';
8
8
 
@@ -18,13 +18,14 @@ export const SpeakingWhileMutedNotification = ({ children }: ChildrenOnly) => {
18
18
  useEffect(() => {
19
19
  // do nothing when not muted
20
20
  if (!isAudioMute) return;
21
- const disposeSoundDetector = getAudioStream(audioDeviceId).then(
22
- (audioStream) =>
23
- createSoundDetector(audioStream, (isSpeechDetected) => {
24
- setIsSpeakingWhileMuted((isNotified) =>
25
- isNotified ? isNotified : isSpeechDetected,
26
- );
27
- }),
21
+ const disposeSoundDetector = getAudioStream({
22
+ deviceId: audioDeviceId,
23
+ }).then((audioStream) =>
24
+ createSoundDetector(audioStream, (isSpeechDetected) => {
25
+ setIsSpeakingWhileMuted((isNotified) =>
26
+ isNotified ? isNotified : isSpeechDetected,
27
+ );
28
+ }),
28
29
  );
29
30
  disposeSoundDetector.catch((err) => {
30
31
  console.error('Error while creating sound detector', err);
@@ -7,8 +7,13 @@ import {
7
7
  } from 'react';
8
8
  import clsx from 'clsx';
9
9
  import { disposeOfMediaStream } from '@stream-io/video-client';
10
- import { BaseVideo } from '../../core/components/Video/BaseVideo';
11
- import { DEVICE_STATE, useMediaDevices } from '../../core/contexts';
10
+ import { BaseVideo } from '../../core/components/Video';
11
+ import {
12
+ DEVICE_STATE,
13
+ useMediaDevices,
14
+ useOnUnavailableVideoDevices,
15
+ useVideoDevices,
16
+ } from '../../core';
12
17
  import { LoadingIndicator } from '../LoadingIndicator';
13
18
 
14
19
  const DefaultDisabledVideoPreview = () => {
@@ -47,19 +52,24 @@ export const VideoPreview = ({
47
52
  VideoErrorPreview = DefaultVideoErrorPreview,
48
53
  }: VideoPreviewProps) => {
49
54
  const [stream, setStream] = useState<MediaStream>();
50
-
51
55
  const {
52
- videoDevices,
53
56
  selectedVideoDeviceId,
54
57
  getVideoStream,
55
58
  initialVideoState,
56
59
  setInitialVideoState,
57
60
  } = useMediaDevices();
61
+ // When there are 0 video devices (e.g. when laptop lid closed),
62
+ // we do not restart the video automatically when the device is again available,
63
+ // but rather leave turning the video on manually to the user.
64
+ useOnUnavailableVideoDevices(() =>
65
+ setInitialVideoState(DEVICE_STATE.stopped),
66
+ );
67
+ const videoDevices = useVideoDevices();
58
68
 
59
69
  useEffect(() => {
60
- if (!initialVideoState.enabled || videoDevices.length === 0) return;
70
+ if (!initialVideoState.enabled) return;
61
71
 
62
- getVideoStream(selectedVideoDeviceId)
72
+ getVideoStream({ deviceId: selectedVideoDeviceId })
63
73
  .then((s) => {
64
74
  setStream((previousStream) => {
65
75
  if (previousStream) {