@fishjam-cloud/react-client 0.7.1 → 0.8.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/DeviceManager.d.ts +25 -15
- package/dist/DeviceManager.d.ts.map +1 -1
- package/dist/DeviceManager.js +125 -79
- package/dist/devices/MiddlewareManager.d.ts +9 -0
- package/dist/devices/MiddlewareManager.d.ts.map +1 -0
- package/dist/devices/MiddlewareManager.js +26 -0
- package/dist/fishjamProvider.d.ts +5 -2
- package/dist/fishjamProvider.d.ts.map +1 -1
- package/dist/fishjamProvider.js +12 -4
- package/dist/hooks/deviceManagers/useDeviceManager.d.ts.map +1 -1
- package/dist/hooks/deviceManagers/useDeviceManager.js +2 -2
- package/dist/hooks/devices/useCamera.d.ts +7 -0
- package/dist/hooks/devices/useCamera.d.ts.map +1 -0
- package/dist/hooks/devices/useCamera.js +35 -0
- package/dist/hooks/devices/useInitializeDevices.d.ts +8 -0
- package/dist/hooks/devices/useInitializeDevices.d.ts.map +1 -0
- package/dist/hooks/devices/useInitializeDevices.js +41 -0
- package/dist/hooks/devices/useMicrophone.d.ts +7 -0
- package/dist/hooks/devices/useMicrophone.d.ts.map +1 -0
- package/dist/hooks/devices/useMicrophone.js +37 -0
- package/dist/hooks/public.d.ts +3 -1
- package/dist/hooks/public.d.ts.map +1 -1
- package/dist/hooks/public.js +3 -1
- package/dist/hooks/useFishjamContext.d.ts +4 -3
- package/dist/hooks/useFishjamContext.d.ts.map +1 -1
- package/dist/hooks/useScreenShare.d.ts +10 -1
- package/dist/hooks/useScreenShare.d.ts.map +1 -1
- package/dist/hooks/useScreenShare.js +34 -33
- package/dist/hooks/useTrackManager.d.ts +4 -2
- package/dist/hooks/useTrackManager.d.ts.map +1 -1
- package/dist/hooks/useTrackManager.js +55 -71
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/mediaInitializer.d.ts.map +1 -1
- package/dist/mediaInitializer.js +30 -1
- package/dist/types/internal.d.ts +20 -31
- package/dist/types/internal.d.ts.map +1 -1
- package/dist/types/public.d.ts +16 -5
- package/dist/types/public.d.ts.map +1 -1
- package/dist/utils/bandwidth.d.ts +3 -0
- package/dist/utils/bandwidth.d.ts.map +1 -0
- package/dist/utils/bandwidth.js +4 -0
- package/dist/utils/localStorage.d.ts +3 -4
- package/dist/utils/localStorage.d.ts.map +1 -1
- package/dist/utils/localStorage.js +18 -4
- package/dist/utils/track.d.ts +8 -2
- package/dist/utils/track.d.ts.map +1 -1
- package/dist/utils/track.js +23 -0
- package/package.json +5 -5
- package/dist/hooks/deviceManagers/useAudioDeviceManager.d.ts +0 -6
- package/dist/hooks/deviceManagers/useAudioDeviceManager.d.ts.map +0 -1
- package/dist/hooks/deviceManagers/useAudioDeviceManager.js +0 -11
- package/dist/hooks/deviceManagers/useVideoDeviceManager.d.ts +0 -6
- package/dist/hooks/deviceManagers/useVideoDeviceManager.d.ts.map +0 -1
- package/dist/hooks/deviceManagers/useVideoDeviceManager.js +0 -11
- package/dist/hooks/useDevices.d.ts +0 -19
- package/dist/hooks/useDevices.d.ts.map +0 -1
- package/dist/hooks/useDevices.js +0 -98
- package/dist/hooks/useProcessedPreviewStream.d.ts +0 -3
- package/dist/hooks/useProcessedPreviewStream.d.ts.map +0 -1
- package/dist/hooks/useProcessedPreviewStream.js +0 -17
- package/dist/utils/media.d.ts +0 -13
- package/dist/utils/media.d.ts.map +0 -1
- package/dist/utils/media.js +0 -64
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useDeviceManager } from "../deviceManagers/useDeviceManager";
|
|
2
|
+
import { useFishjamContext } from "../useFishjamContext";
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @category Devices
|
|
6
|
+
*/
|
|
7
|
+
export function useMicrophone() {
|
|
8
|
+
const { audioTrackManager, audioDeviceManagerRef } = useFishjamContext();
|
|
9
|
+
const { deviceState, status } = useDeviceManager(audioDeviceManagerRef.current);
|
|
10
|
+
const { currentTrack, ...trackManager } = audioTrackManager;
|
|
11
|
+
const stream = deviceState.media?.stream ?? null;
|
|
12
|
+
const currentMiddleware = deviceState.currentMiddleware ?? null;
|
|
13
|
+
const isStreaming = Boolean(currentTrack?.stream);
|
|
14
|
+
const track = stream?.getAudioTracks()[0] ?? null;
|
|
15
|
+
const trackId = currentTrack?.trackId ?? null;
|
|
16
|
+
const devices = deviceState.devices ?? [];
|
|
17
|
+
const activeDevice = deviceState.media?.deviceInfo ?? null;
|
|
18
|
+
const isAudioPlaying = currentTrack?.vadStatus === "speech";
|
|
19
|
+
const isMuted = !deviceState.media?.enabled;
|
|
20
|
+
const deviceError = deviceState.error ?? null;
|
|
21
|
+
const isDeviceEnabled = Boolean(deviceState.media);
|
|
22
|
+
return {
|
|
23
|
+
...trackManager,
|
|
24
|
+
currentMiddleware,
|
|
25
|
+
isDeviceEnabled,
|
|
26
|
+
status,
|
|
27
|
+
stream,
|
|
28
|
+
track,
|
|
29
|
+
isStreaming,
|
|
30
|
+
trackId,
|
|
31
|
+
devices,
|
|
32
|
+
activeDevice,
|
|
33
|
+
isMuted,
|
|
34
|
+
deviceError,
|
|
35
|
+
isAudioPlaying,
|
|
36
|
+
};
|
|
37
|
+
}
|
package/dist/hooks/public.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { useConnect, useDisconnect } from "./useConnection";
|
|
2
2
|
export { useReconnection } from "./useReconnection";
|
|
3
|
-
export { useCamera
|
|
3
|
+
export { useCamera } from "./devices/useCamera";
|
|
4
|
+
export { useMicrophone } from "./devices/useMicrophone";
|
|
5
|
+
export { useInitializeDevices } from "./devices/useInitializeDevices";
|
|
4
6
|
export { usePeers } from "./usePeers";
|
|
5
7
|
export { useScreenShare } from "./useScreenShare";
|
|
6
8
|
export { useStatus } from "./useStatus";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/hooks/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/hooks/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/hooks/public.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { useConnect, useDisconnect } from "./useConnection";
|
|
2
2
|
export { useReconnection } from "./useReconnection";
|
|
3
|
-
export { useCamera
|
|
3
|
+
export { useCamera } from "./devices/useCamera";
|
|
4
|
+
export { useMicrophone } from "./devices/useMicrophone";
|
|
5
|
+
export { useInitializeDevices } from "./devices/useInitializeDevices";
|
|
4
6
|
export { usePeers } from "./usePeers";
|
|
5
7
|
export { useScreenShare } from "./useScreenShare";
|
|
6
8
|
export { useStatus } from "./useStatus";
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import type { FishjamClient } from "@fishjam-cloud/ts-client";
|
|
2
2
|
import { type MutableRefObject } from "react";
|
|
3
|
-
import type { PeerMetadata, TrackMetadata,
|
|
3
|
+
import type { PeerMetadata, TrackMetadata, TrackManager } from "../types/internal";
|
|
4
4
|
import type { DeviceManager } from "../DeviceManager";
|
|
5
5
|
import type { FishjamClientState } from "./useFishjamClientState";
|
|
6
|
-
import type { PeerStatus } from "../types/public";
|
|
6
|
+
import type { BandwidthLimits, PeerStatus, ScreenshareApi } from "../types/public";
|
|
7
7
|
export type FishjamContextType = {
|
|
8
8
|
fishjamClientRef: MutableRefObject<FishjamClient<PeerMetadata, TrackMetadata>>;
|
|
9
9
|
videoDeviceManagerRef: MutableRefObject<DeviceManager>;
|
|
10
10
|
audioDeviceManagerRef: MutableRefObject<DeviceManager>;
|
|
11
11
|
hasDevicesBeenInitializedRef: MutableRefObject<boolean>;
|
|
12
|
-
|
|
12
|
+
screenShareManager: ScreenshareApi;
|
|
13
13
|
peerStatus: PeerStatus;
|
|
14
14
|
videoTrackManager: TrackManager;
|
|
15
15
|
audioTrackManager: TrackManager;
|
|
16
16
|
clientState: FishjamClientState;
|
|
17
|
+
bandwidthLimits: BandwidthLimits;
|
|
17
18
|
};
|
|
18
19
|
export declare const FishjamContext: import("react").Context<FishjamContextType | null>;
|
|
19
20
|
export declare function useFishjamContext(): FishjamContextType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFishjamContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useFishjamContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAiB,KAAK,gBAAgB,EAAc,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"useFishjamContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useFishjamContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAiB,KAAK,gBAAgB,EAAc,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEnF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,gBAAgB,CAAC,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;IAC/E,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACvD,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACvD,4BAA4B,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACxD,kBAAkB,EAAE,cAAc,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC;IACvB,iBAAiB,EAAE,YAAY,CAAC;IAChC,iBAAiB,EAAE,YAAY,CAAC;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF,eAAO,MAAM,cAAc,oDAAiD,CAAC;AAE7E,wBAAgB,iBAAiB,IAGb,kBAAkB,CACrC"}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FishjamClient } from "@fishjam-cloud/ts-client";
|
|
2
|
+
import type { ScreenshareApi, PeerStatus } from "../types/public";
|
|
3
|
+
import type { PeerMetadata, TrackMetadata } from "../types/internal";
|
|
4
|
+
interface ScreenShareManagerProps {
|
|
5
|
+
fishjamClient: FishjamClient<PeerMetadata, TrackMetadata>;
|
|
6
|
+
getCurrentPeerStatus: () => PeerStatus;
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
*
|
|
4
10
|
* @category Screenshare
|
|
5
11
|
*/
|
|
12
|
+
export declare const useScreenShareManager: ({ fishjamClient, getCurrentPeerStatus, }: ScreenShareManagerProps) => ScreenshareApi;
|
|
6
13
|
export declare const useScreenShare: () => ScreenshareApi;
|
|
14
|
+
export declare const getTracksFromStream: (stream: MediaStream) => [MediaStreamTrack, MediaStreamTrack | null];
|
|
15
|
+
export {};
|
|
7
16
|
//# sourceMappingURL=useScreenShare.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScreenShare.d.ts","sourceRoot":"","sources":["../../src/hooks/useScreenShare.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useScreenShare.d.ts","sourceRoot":"","sources":["../../src/hooks/useScreenShare.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,KAAK,EAAoB,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAoB,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvF,UAAU,uBAAuB;IAC/B,aAAa,EAAE,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAC1D,oBAAoB,EAAE,MAAM,UAAU,CAAC;CACxC;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,6CAG/B,uBAAuB,KAAG,cAqI5B,CAAC;AAEF,eAAO,MAAM,cAAc,sBAI1B,CAAC;AAEF,eAAO,MAAM,mBAAmB,WAAY,WAAW,KAAG,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAKnG,CAAC"}
|
|
@@ -1,49 +1,41 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef } from "react";
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
2
|
import { getRemoteOrLocalTrack } from "../utils/track";
|
|
3
3
|
import { useFishjamContext } from "./useFishjamContext";
|
|
4
|
-
const getTracks = (stream) => {
|
|
5
|
-
const video = stream.getVideoTracks()[0];
|
|
6
|
-
const audio = stream.getAudioTracks()[0] ?? null;
|
|
7
|
-
return [video, audio];
|
|
8
|
-
};
|
|
9
4
|
/**
|
|
10
5
|
*
|
|
11
6
|
* @category Screenshare
|
|
12
7
|
*/
|
|
13
|
-
export const
|
|
14
|
-
const
|
|
15
|
-
const [state, setState] = ctx.screenShareState;
|
|
8
|
+
export const useScreenShareManager = ({ fishjamClient, getCurrentPeerStatus, }) => {
|
|
9
|
+
const [state, setState] = useState({ stream: null, trackIds: null });
|
|
16
10
|
const cleanMiddlewareFnRef = useRef(null);
|
|
17
|
-
const { fishjamClientRef } = useFishjamContext();
|
|
18
|
-
const tsClient = fishjamClientRef.current;
|
|
19
11
|
const stream = state.stream ?? null;
|
|
20
|
-
const [videoTrack, audioTrack] = stream ?
|
|
21
|
-
const getDisplayName = () =>
|
|
12
|
+
const [videoTrack, audioTrack] = stream ? getTracksFromStream(stream) : [null, null];
|
|
13
|
+
const getDisplayName = () => fishjamClient.getLocalPeer()?.metadata?.peer?.displayName;
|
|
22
14
|
const startStreaming = async (props) => {
|
|
23
15
|
const stream = await navigator.mediaDevices.getDisplayMedia({
|
|
24
16
|
video: props?.videoConstraints ?? true,
|
|
25
17
|
audio: props?.audioConstraints ?? true,
|
|
26
18
|
});
|
|
27
19
|
const displayName = getDisplayName();
|
|
28
|
-
let [video, audio] =
|
|
20
|
+
let [video, audio] = getTracksFromStream(stream);
|
|
29
21
|
if (state.tracksMiddleware) {
|
|
30
22
|
const { videoTrack, audioTrack, onClear } = state.tracksMiddleware(video, audio);
|
|
31
23
|
video = videoTrack;
|
|
32
24
|
audio = audioTrack;
|
|
33
25
|
cleanMiddlewareFnRef.current = onClear;
|
|
34
26
|
}
|
|
35
|
-
const addTrackPromises = [
|
|
27
|
+
const addTrackPromises = [fishjamClient.addTrack(video, { displayName, type: "screenShareVideo", paused: false })];
|
|
36
28
|
if (audio)
|
|
37
|
-
addTrackPromises.push(
|
|
29
|
+
addTrackPromises.push(fishjamClient.addTrack(audio, { displayName, type: "screenShareAudio", paused: false }));
|
|
38
30
|
const [videoId, audioId] = await Promise.all(addTrackPromises);
|
|
39
31
|
setState({ stream, trackIds: { videoId, audioId } });
|
|
40
32
|
};
|
|
41
33
|
const replaceTracks = async (newVideoTrack, newAudioTrack) => {
|
|
42
34
|
if (!state?.stream)
|
|
43
35
|
return;
|
|
44
|
-
const addTrackPromises = [
|
|
36
|
+
const addTrackPromises = [fishjamClient.replaceTrack(state.trackIds.videoId, newVideoTrack)];
|
|
45
37
|
if (newAudioTrack && state.trackIds.audioId) {
|
|
46
|
-
addTrackPromises.push(
|
|
38
|
+
addTrackPromises.push(fishjamClient.replaceTrack(state.trackIds.audioId, newAudioTrack));
|
|
47
39
|
}
|
|
48
40
|
await Promise.all(addTrackPromises);
|
|
49
41
|
};
|
|
@@ -54,7 +46,7 @@ export const useScreenShare = () => {
|
|
|
54
46
|
const setTracksMiddleware = async (middleware) => {
|
|
55
47
|
if (!state?.stream)
|
|
56
48
|
return;
|
|
57
|
-
const [video, audio] =
|
|
49
|
+
const [video, audio] = getTracksFromStream(state.stream);
|
|
58
50
|
cleanMiddleware();
|
|
59
51
|
const { videoTrack, audioTrack, onClear } = middleware?.(video, audio) ?? {
|
|
60
52
|
videoTrack: video,
|
|
@@ -69,22 +61,23 @@ export const useScreenShare = () => {
|
|
|
69
61
|
console.warn("No stream to stop");
|
|
70
62
|
return;
|
|
71
63
|
}
|
|
72
|
-
const [video, audio] =
|
|
64
|
+
const [video, audio] = getTracksFromStream(state.stream);
|
|
73
65
|
video.stop();
|
|
74
66
|
if (audio)
|
|
75
67
|
audio.stop();
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
if (getCurrentPeerStatus() === "connected") {
|
|
69
|
+
const removeTrackPromises = [fishjamClient.removeTrack(state.trackIds.videoId)];
|
|
70
|
+
if (state.trackIds.audioId)
|
|
71
|
+
removeTrackPromises.push(fishjamClient.removeTrack(state.trackIds.audioId));
|
|
72
|
+
await Promise.all(removeTrackPromises);
|
|
73
|
+
}
|
|
81
74
|
cleanMiddleware();
|
|
82
75
|
setState(({ tracksMiddleware }) => ({ stream: null, trackIds: null, tracksMiddleware }));
|
|
83
|
-
}, [state,
|
|
76
|
+
}, [state, fishjamClient, setState, cleanMiddleware, getCurrentPeerStatus]);
|
|
84
77
|
useEffect(() => {
|
|
85
78
|
if (!state.stream)
|
|
86
79
|
return;
|
|
87
|
-
const [video, audio] =
|
|
80
|
+
const [video, audio] = getTracksFromStream(state.stream);
|
|
88
81
|
const trackEndedHandler = () => {
|
|
89
82
|
stopStreaming();
|
|
90
83
|
};
|
|
@@ -96,19 +89,18 @@ export const useScreenShare = () => {
|
|
|
96
89
|
};
|
|
97
90
|
}, [state, stopStreaming]);
|
|
98
91
|
useEffect(() => {
|
|
99
|
-
const client = fishjamClientRef.current;
|
|
100
92
|
const onDisconnected = () => {
|
|
101
93
|
if (stream) {
|
|
102
94
|
stopStreaming();
|
|
103
95
|
}
|
|
104
96
|
};
|
|
105
|
-
|
|
97
|
+
fishjamClient.on("disconnected", onDisconnected);
|
|
106
98
|
return () => {
|
|
107
|
-
|
|
99
|
+
fishjamClient.removeListener("disconnected", onDisconnected);
|
|
108
100
|
};
|
|
109
|
-
}, [stopStreaming,
|
|
110
|
-
const videoBroadcast = state.stream ? getRemoteOrLocalTrack(
|
|
111
|
-
const audioBroadcast = state.trackIds?.audioId ? getRemoteOrLocalTrack(
|
|
101
|
+
}, [stopStreaming, fishjamClient, stream]);
|
|
102
|
+
const videoBroadcast = state.stream ? getRemoteOrLocalTrack(fishjamClient, state.trackIds.videoId) : null;
|
|
103
|
+
const audioBroadcast = state.trackIds?.audioId ? getRemoteOrLocalTrack(fishjamClient, state.trackIds.audioId) : null;
|
|
112
104
|
return {
|
|
113
105
|
startStreaming,
|
|
114
106
|
stopStreaming,
|
|
@@ -121,3 +113,12 @@ export const useScreenShare = () => {
|
|
|
121
113
|
currentTracksMiddleware: state?.tracksMiddleware ?? null,
|
|
122
114
|
};
|
|
123
115
|
};
|
|
116
|
+
export const useScreenShare = () => {
|
|
117
|
+
const { screenShareManager } = useFishjamContext();
|
|
118
|
+
return screenShareManager;
|
|
119
|
+
};
|
|
120
|
+
export const getTracksFromStream = (stream) => {
|
|
121
|
+
const video = stream.getVideoTracks()[0];
|
|
122
|
+
const audio = stream.getAudioTracks()[0] ?? null;
|
|
123
|
+
return [video, audio];
|
|
124
|
+
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { FishjamClient } from "@fishjam-cloud/ts-client";
|
|
2
2
|
import type { MediaManager, PeerMetadata, TrackManager, TrackMetadata } from "../types/internal";
|
|
3
|
-
import type { PeerStatus } from "../types/public";
|
|
3
|
+
import type { BandwidthLimits, PeerStatus, StartStreamingProps } from "../types/public";
|
|
4
4
|
interface TrackManagerConfig {
|
|
5
5
|
mediaManager: MediaManager;
|
|
6
6
|
tsClient: FishjamClient<PeerMetadata, TrackMetadata>;
|
|
7
7
|
getCurrentPeerStatus: () => PeerStatus;
|
|
8
|
+
bandwidthLimits: BandwidthLimits;
|
|
9
|
+
autoStreamProps?: StartStreamingProps | false;
|
|
8
10
|
}
|
|
9
|
-
export declare const useTrackManager: ({ mediaManager, tsClient, getCurrentPeerStatus }: TrackManagerConfig) => TrackManager;
|
|
11
|
+
export declare const useTrackManager: ({ mediaManager, tsClient, getCurrentPeerStatus, bandwidthLimits, autoStreamProps, }: TrackManagerConfig) => TrackManager;
|
|
10
12
|
export {};
|
|
11
13
|
//# sourceMappingURL=useTrackManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTrackManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useTrackManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"useTrackManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useTrackManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGjG,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,mBAAmB,EAAmB,MAAM,iBAAiB,CAAC;AAEzG,UAAU,kBAAkB;IAC1B,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IACrD,oBAAoB,EAAE,MAAM,UAAU,CAAC;IACvC,eAAe,EAAE,eAAe,CAAC;IACjC,eAAe,CAAC,EAAE,mBAAmB,GAAG,KAAK,CAAC;CAC/C;AAWD,eAAO,MAAM,eAAe,wFAMzB,kBAAkB,KAAG,YA0LvB,CAAC"}
|
|
@@ -1,51 +1,27 @@
|
|
|
1
|
-
import { getRemoteOrLocalTrack } from "../utils/track";
|
|
2
|
-
import { useCallback, useEffect, useMemo,
|
|
1
|
+
import { getConfigAndBandwidthFromProps, getRemoteOrLocalTrack } from "../utils/track";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
3
|
const TRACK_TYPE_TO_DEVICE = {
|
|
4
4
|
video: "camera",
|
|
5
5
|
audio: "microphone",
|
|
6
6
|
};
|
|
7
|
-
|
|
7
|
+
const getDeviceType = (mediaManager) => TRACK_TYPE_TO_DEVICE[mediaManager.getDeviceType()];
|
|
8
|
+
export const useTrackManager = ({ mediaManager, tsClient, getCurrentPeerStatus, bandwidthLimits, autoStreamProps, }) => {
|
|
8
9
|
const [currentTrackId, setCurrentTrackId] = useState(null);
|
|
9
10
|
const [paused, setPaused] = useState(false);
|
|
10
|
-
const clearMiddlewareFnRef = useRef(null);
|
|
11
|
-
const [currentTrackMiddleware, setCurrentTrackMiddleware] = useState(null);
|
|
12
|
-
const type = TRACK_TYPE_TO_DEVICE[mediaManager.getDeviceType()];
|
|
13
|
-
const metadata = useMemo(() => ({ type, paused }), [type, paused]);
|
|
14
11
|
const currentTrack = useMemo(() => getRemoteOrLocalTrack(tsClient, currentTrackId), [tsClient, currentTrackId]);
|
|
15
|
-
function clearMiddleware() {
|
|
16
|
-
clearMiddlewareFnRef.current?.();
|
|
17
|
-
clearMiddlewareFnRef.current = null;
|
|
18
|
-
}
|
|
19
|
-
const clearAndGetProcessedTrack = useCallback((inputTrack) => {
|
|
20
|
-
clearMiddleware();
|
|
21
|
-
const { onClear, track } = currentTrackMiddleware?.(inputTrack) ?? {};
|
|
22
|
-
if (onClear)
|
|
23
|
-
clearMiddlewareFnRef.current = onClear;
|
|
24
|
-
return track ?? inputTrack;
|
|
25
|
-
}, [currentTrackMiddleware]);
|
|
26
12
|
async function setTrackMiddleware(middleware) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (!currentTrack || !mediaTrack)
|
|
30
|
-
return;
|
|
31
|
-
clearMiddleware();
|
|
32
|
-
const { onClear, track } = middleware?.(mediaTrack) ?? { track: mediaTrack };
|
|
33
|
-
if (onClear)
|
|
34
|
-
clearMiddlewareFnRef.current = onClear;
|
|
35
|
-
await tsClient.replaceTrack(currentTrack.trackId, track);
|
|
13
|
+
mediaManager.setTrackMiddleware(middleware);
|
|
14
|
+
await refreshStreamedTrack();
|
|
36
15
|
}
|
|
37
16
|
async function initialize(deviceId) {
|
|
38
17
|
await mediaManager?.start(deviceId);
|
|
39
18
|
if (!currentTrackId)
|
|
40
19
|
return;
|
|
41
|
-
const newTrack = mediaManager.
|
|
42
|
-
await tsClient.replaceTrack(currentTrackId,
|
|
43
|
-
}
|
|
44
|
-
function stop() {
|
|
45
|
-
clearMiddleware();
|
|
46
|
-
return mediaManager?.stop();
|
|
20
|
+
const newTrack = mediaManager.getMedia()?.track ?? null;
|
|
21
|
+
await tsClient.replaceTrack(currentTrackId, newTrack);
|
|
47
22
|
}
|
|
48
|
-
const
|
|
23
|
+
const stop = useCallback(() => mediaManager.stop(), [mediaManager]);
|
|
24
|
+
const startStreaming = useCallback(async (props = { simulcast: ["l", "m", "h"] }) => {
|
|
49
25
|
if (currentTrackId)
|
|
50
26
|
throw Error("Track already added");
|
|
51
27
|
const media = mediaManager.getMedia();
|
|
@@ -57,56 +33,57 @@ export const useTrackManager = ({ mediaManager, tsClient, getCurrentPeerStatus }
|
|
|
57
33
|
// see `getRemoteOrLocalTrackContext()` explanation
|
|
58
34
|
setCurrentTrackId(media.track.id);
|
|
59
35
|
const displayName = tsClient.getLocalPeer()?.metadata?.peer?.displayName;
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
const
|
|
36
|
+
const deviceType = getDeviceType(mediaManager);
|
|
37
|
+
const trackMetadata = { type: deviceType, displayName, paused: false };
|
|
38
|
+
const [maxBandwidth, simulcastConfig] = getConfigAndBandwidthFromProps(props.simulcast, bandwidthLimits);
|
|
39
|
+
const remoteTrackId = await tsClient.addTrack(media.track, trackMetadata, simulcastConfig, maxBandwidth);
|
|
63
40
|
setCurrentTrackId(remoteTrackId);
|
|
64
41
|
setPaused(false);
|
|
65
42
|
return remoteTrackId;
|
|
66
|
-
}, [
|
|
67
|
-
|
|
43
|
+
}, [currentTrackId, mediaManager, tsClient, bandwidthLimits]);
|
|
44
|
+
const refreshStreamedTrack = useCallback(async () => {
|
|
68
45
|
if (!currentTrack)
|
|
69
46
|
return;
|
|
70
|
-
const newTrack = mediaManager.
|
|
47
|
+
const newTrack = mediaManager.getMedia()?.track ?? null;
|
|
71
48
|
if (!newTrack)
|
|
72
49
|
throw Error("New track is empty");
|
|
73
|
-
return tsClient.replaceTrack(currentTrack.trackId,
|
|
74
|
-
}
|
|
75
|
-
|
|
50
|
+
return tsClient.replaceTrack(currentTrack.trackId, newTrack);
|
|
51
|
+
}, [currentTrack, mediaManager, tsClient]);
|
|
52
|
+
const stopStreaming = useCallback(async () => {
|
|
76
53
|
if (!currentTrack)
|
|
77
54
|
return;
|
|
78
|
-
clearMiddleware();
|
|
79
55
|
setCurrentTrackId(null);
|
|
80
56
|
setPaused(true);
|
|
81
57
|
return tsClient.removeTrack(currentTrack.trackId);
|
|
82
|
-
}
|
|
83
|
-
|
|
58
|
+
}, [currentTrack, tsClient]);
|
|
59
|
+
const pauseStreaming = useCallback(async () => {
|
|
84
60
|
if (!currentTrack)
|
|
85
61
|
return;
|
|
86
62
|
setPaused(true);
|
|
87
63
|
await tsClient.replaceTrack(currentTrack.trackId, null);
|
|
88
|
-
const
|
|
64
|
+
const deviceType = getDeviceType(mediaManager);
|
|
65
|
+
const trackMetadata = { type: deviceType, paused: true };
|
|
89
66
|
return tsClient.updateTrackMetadata(currentTrack.trackId, trackMetadata);
|
|
90
|
-
}
|
|
91
|
-
|
|
67
|
+
}, [currentTrack, mediaManager, tsClient]);
|
|
68
|
+
const resumeStreaming = useCallback(async () => {
|
|
92
69
|
if (!currentTrack)
|
|
93
70
|
return;
|
|
94
71
|
const media = mediaManager.getMedia();
|
|
72
|
+
const deviceType = getDeviceType(mediaManager);
|
|
95
73
|
if (!media)
|
|
96
74
|
throw Error("Device is unavailable");
|
|
97
|
-
const processedTrack = media.track ? clearAndGetProcessedTrack(media.track) : null;
|
|
98
75
|
setPaused(false);
|
|
99
|
-
await tsClient.replaceTrack(currentTrack.trackId,
|
|
100
|
-
const trackMetadata = {
|
|
76
|
+
await tsClient.replaceTrack(currentTrack.trackId, media.track);
|
|
77
|
+
const trackMetadata = { type: deviceType, paused: false };
|
|
101
78
|
return tsClient.updateTrackMetadata(currentTrack.trackId, trackMetadata);
|
|
102
|
-
}
|
|
103
|
-
|
|
79
|
+
}, [currentTrack, mediaManager, tsClient]);
|
|
80
|
+
const disableTrack = useCallback(() => {
|
|
104
81
|
mediaManager.disable();
|
|
105
|
-
}
|
|
106
|
-
|
|
82
|
+
}, [mediaManager]);
|
|
83
|
+
const enableTrack = useCallback(() => {
|
|
107
84
|
mediaManager.enable();
|
|
108
|
-
}
|
|
109
|
-
const stream = async () => {
|
|
85
|
+
}, [mediaManager]);
|
|
86
|
+
const stream = useCallback(async () => {
|
|
110
87
|
if (getCurrentPeerStatus() !== "connected")
|
|
111
88
|
return;
|
|
112
89
|
if (currentTrack?.trackId) {
|
|
@@ -115,13 +92,10 @@ export const useTrackManager = ({ mediaManager, tsClient, getCurrentPeerStatus }
|
|
|
115
92
|
else {
|
|
116
93
|
await startStreaming();
|
|
117
94
|
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
* @see {@link TrackManager#toggle} for more details.
|
|
121
|
-
*/
|
|
122
|
-
async function toggle(mode = "hard") {
|
|
95
|
+
}, [currentTrack?.trackId, getCurrentPeerStatus, resumeStreaming, startStreaming]);
|
|
96
|
+
const toggle = useCallback(async (mode) => {
|
|
123
97
|
const mediaStream = mediaManager.getMedia()?.stream;
|
|
124
|
-
const track = mediaManager.
|
|
98
|
+
const track = mediaManager.getMedia()?.track ?? null;
|
|
125
99
|
const enabled = Boolean(track?.enabled);
|
|
126
100
|
if (mediaStream && enabled) {
|
|
127
101
|
mediaManager.disable();
|
|
@@ -129,7 +103,7 @@ export const useTrackManager = ({ mediaManager, tsClient, getCurrentPeerStatus }
|
|
|
129
103
|
await pauseStreaming();
|
|
130
104
|
}
|
|
131
105
|
if (mode === "hard") {
|
|
132
|
-
|
|
106
|
+
mediaManager.stop();
|
|
133
107
|
}
|
|
134
108
|
}
|
|
135
109
|
else if (mediaStream && !enabled) {
|
|
@@ -140,11 +114,21 @@ export const useTrackManager = ({ mediaManager, tsClient, getCurrentPeerStatus }
|
|
|
140
114
|
await mediaManager.start();
|
|
141
115
|
await stream();
|
|
142
116
|
}
|
|
143
|
-
}
|
|
117
|
+
}, [currentTrack, mediaManager, pauseStreaming, stream]);
|
|
118
|
+
/**
|
|
119
|
+
* @see {@link TrackManager#toggleMute} for more details.
|
|
120
|
+
*/
|
|
121
|
+
const toggleMute = useCallback(() => toggle("soft"), [toggle]);
|
|
122
|
+
/**
|
|
123
|
+
* @see {@link TrackManager#toggleDevice} for more details.
|
|
124
|
+
*/
|
|
125
|
+
const toggleDevice = useCallback(() => toggle("hard"), [toggle]);
|
|
144
126
|
useEffect(() => {
|
|
127
|
+
if (autoStreamProps === false)
|
|
128
|
+
return;
|
|
145
129
|
const joinedHandler = () => {
|
|
146
|
-
if (mediaManager.
|
|
147
|
-
startStreaming();
|
|
130
|
+
if (mediaManager.getMedia()?.track) {
|
|
131
|
+
startStreaming(autoStreamProps);
|
|
148
132
|
}
|
|
149
133
|
};
|
|
150
134
|
const disconnectedHandler = () => {
|
|
@@ -156,7 +140,7 @@ export const useTrackManager = ({ mediaManager, tsClient, getCurrentPeerStatus }
|
|
|
156
140
|
tsClient.off("joined", joinedHandler);
|
|
157
141
|
tsClient.off("disconnected", disconnectedHandler);
|
|
158
142
|
};
|
|
159
|
-
}, [mediaManager, startStreaming, tsClient]);
|
|
143
|
+
}, [mediaManager, startStreaming, tsClient, autoStreamProps]);
|
|
160
144
|
return {
|
|
161
145
|
currentTrack,
|
|
162
146
|
setTrackMiddleware,
|
|
@@ -168,9 +152,9 @@ export const useTrackManager = ({ mediaManager, tsClient, getCurrentPeerStatus }
|
|
|
168
152
|
resumeStreaming,
|
|
169
153
|
disableTrack,
|
|
170
154
|
enableTrack,
|
|
171
|
-
currentTrackMiddleware,
|
|
172
155
|
refreshStreamedTrack,
|
|
173
156
|
paused,
|
|
174
|
-
|
|
157
|
+
toggleMute,
|
|
158
|
+
toggleDevice,
|
|
175
159
|
};
|
|
176
160
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { useConnect, useDisconnect, useReconnection, useCamera, useMicrophone, useInitializeDevices, usePeers, useScreenShare, useStatus, } from "./hooks/public";
|
|
2
2
|
export { FishjamProvider } from "./fishjamProvider";
|
|
3
|
-
export { Track, TrackMiddleware, TracksMiddleware, PeerStatus,
|
|
3
|
+
export { Track, TrackMiddleware, TracksMiddleware, PeerStatus, Device, AudioDevice, PeerWithTracks, ConnectConfig, PersistLastDeviceHandlers, ScreenshareApi, StartStreamingProps, } from "./types/public";
|
|
4
4
|
export { AUDIO_TRACK_CONSTRAINTS, VIDEO_TRACK_CONSTRAINTS, SCREEN_SHARING_MEDIA_CONSTRAINTS } from "./constraints";
|
|
5
5
|
export type { Peer, MessageEvents, CreateConfig, TrackBandwidthLimit, SimulcastBandwidthLimit, BandwidthLimit, WebRTCEndpointEvents, TrackContextEvents, Endpoint, SimulcastConfig, TrackContext, VadStatus, EncodingReason, MetadataParser, AuthErrorReason, Encoding, } from "@fishjam-cloud/ts-client";
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,QAAQ,EACR,cAAc,EACd,SAAS,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EACL,KAAK,EACL,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,QAAQ,EACR,cAAc,EACd,SAAS,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EACL,KAAK,EACL,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,MAAM,EACN,WAAW,EACX,cAAc,EACd,aAAa,EACb,yBAAyB,EACzB,cAAc,EACd,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC;AAEnH,YAAY,EACV,IAAI,EACJ,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,SAAS,EACT,cAAc,EACd,cAAc,EACd,eAAe,EACf,QAAQ,GACT,MAAM,0BAA0B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mediaInitializer.d.ts","sourceRoot":"","sources":["../src/mediaInitializer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"mediaInitializer.d.ts","sourceRoot":"","sources":["../src/mediaInitializer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpE,KAAK,UAAU,CAAC,CAAC,IAAI;IAAE,KAAK,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE5C,KAAK,gBAAgB,GAAG,UAAU,CAAC,qBAAqB,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;AAEhF,KAAK,eAAe,GAAG,UAAU,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;AAsB1D,eAAO,MAAM,iBAAiB,gBACf,sBAAsB,iBACrB,UAAU,CAAC,WAAW,GAAG,IAAI,CAAC,KAC3C,OAAO,CAAC,CAAC,WAAW,GAAG,IAAI,EAAE,UAAU,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAuB9D,CAAC;AAIF,eAAO,MAAM,kBAAkB,WACrB,WAAW,gBACL,UAAU,CAAC,WAAW,GAAG,IAAI,CAAC,WACnC,eAAe,EAAE,eACb,gBAAgB,mBACZ,eAAe,KAC/B,OAAO,CAAC,CAAC,WAAW,GAAG,IAAI,EAAE,UAAU,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAsB9D,CAAC"}
|
package/dist/mediaInitializer.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { prepareConstraints } from "./constraints";
|
|
2
2
|
import { NOT_FOUND_ERROR, OVERCONSTRAINED_ERROR, PERMISSION_DENIED, UNHANDLED_ERROR } from "./utils/errors";
|
|
3
|
-
import { getCurrentDevicesSettings, stopTracks, isAnyDeviceDifferentFromLastSession, removeSpecifiedDeviceFromConstraints, } from "./utils/media";
|
|
4
3
|
const defaultErrors = { audio: null, video: null };
|
|
5
4
|
const tryToGetAudioOnlyThenVideoOnly = async (constraints, deviceErrors = defaultErrors, transformConstraint = () => false) => {
|
|
6
5
|
const audioOnly = await getAvailableMedia({ ...constraints, video: transformConstraint(constraints.video) }, { ...deviceErrors, audio: null });
|
|
@@ -46,3 +45,33 @@ export const getCorrectedResult = async (stream, deviceErrors, devices, constrai
|
|
|
46
45
|
};
|
|
47
46
|
return await getAvailableMedia(exactConstraints, deviceErrors);
|
|
48
47
|
};
|
|
48
|
+
const getCurrentDevicesSettings = (requestedDevices, mediaDeviceInfos) => {
|
|
49
|
+
const currentDevices = { videoinput: null, audioinput: null };
|
|
50
|
+
for (const track of requestedDevices.getTracks()) {
|
|
51
|
+
const settings = track.getSettings();
|
|
52
|
+
if (settings.deviceId) {
|
|
53
|
+
const currentDevice = mediaDeviceInfos.find((device) => device.deviceId == settings.deviceId);
|
|
54
|
+
const kind = currentDevice?.kind ?? null;
|
|
55
|
+
if ((currentDevice && kind === "videoinput") || kind === "audioinput") {
|
|
56
|
+
currentDevices[kind] = currentDevice ?? null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return currentDevices;
|
|
61
|
+
};
|
|
62
|
+
const isDeviceDifferentFromLastSession = (lastDevice, currentDevice) => lastDevice && (currentDevice?.deviceId !== lastDevice.deviceId || currentDevice?.label !== lastDevice?.label);
|
|
63
|
+
const isAnyDeviceDifferentFromLastSession = (lastVideoDevice, lastAudioDevice, currentDevices) => !!((currentDevices?.videoinput &&
|
|
64
|
+
isDeviceDifferentFromLastSession(lastVideoDevice, currentDevices?.videoinput || null)) ||
|
|
65
|
+
(currentDevices?.audioinput &&
|
|
66
|
+
isDeviceDifferentFromLastSession(lastAudioDevice, currentDevices?.audioinput || null)));
|
|
67
|
+
const stopTracks = (requestedDevices) => {
|
|
68
|
+
for (const track of requestedDevices.getTracks()) {
|
|
69
|
+
track.stop();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const removeSpecifiedDeviceFromConstraints = (trackConstraints) => {
|
|
73
|
+
if (typeof trackConstraints === "object") {
|
|
74
|
+
return { ...trackConstraints, deviceId: undefined };
|
|
75
|
+
}
|
|
76
|
+
return trackConstraints;
|
|
77
|
+
};
|