@pipecat-ai/client-react 0.3.4 → 0.4.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/README.md +66 -1
- package/dist/index.d.ts +67 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +213 -53
- package/dist/index.js.map +1 -1
- package/dist/index.module.js +211 -55
- package/dist/index.module.js.map +1 -1
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -93,17 +93,58 @@ Creates a new `<video>` element that renders either the bot or local participant
|
|
|
93
93
|
/>
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
+
### RTVIClientCamToggle
|
|
97
|
+
|
|
98
|
+
This is a stateful headless component and exposes the user's camEnabled state and an `onClick` handler to toggle the state.
|
|
99
|
+
|
|
100
|
+
#### Props
|
|
101
|
+
|
|
102
|
+
- `onCamEnabledChanged(enabled: boolean)` (function, optional): Triggered when the user's camEnabled state changes
|
|
103
|
+
- `disabled` (boolean, optional): Disables the cam toggle
|
|
104
|
+
|
|
105
|
+
```jsx
|
|
106
|
+
<RTVIClientCamToggle>
|
|
107
|
+
{({ disabled, isCamEnabled, onClick }) => (
|
|
108
|
+
<button disabled={disabled} onClick={onClick}>
|
|
109
|
+
{isCamEnabled ? "Turn off" : "Turn on"} camera
|
|
110
|
+
</button>
|
|
111
|
+
)}
|
|
112
|
+
</RTVIClientCamToggle>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### RTVIClientMicToggle
|
|
116
|
+
|
|
117
|
+
This is a stateful headless component and exposes the user's micEnabled state and an `onClick` handler to toggle the state.
|
|
118
|
+
|
|
119
|
+
#### Props
|
|
120
|
+
|
|
121
|
+
- `onMicEnabledChanged(enabled: boolean)` (function, optional): Triggered when the user's micEnabled state changes
|
|
122
|
+
- `disabled` (boolean, optional): Disables the mic toggle
|
|
123
|
+
|
|
124
|
+
```jsx
|
|
125
|
+
<RTVIClientMicToggle>
|
|
126
|
+
{({ disabled, isMicEnabled, onClick }) => (
|
|
127
|
+
<button disabled={disabled} onClick={onClick}>
|
|
128
|
+
{isMicEnabled ? "Mute" : "Unmute"} microphone
|
|
129
|
+
</button>
|
|
130
|
+
)}
|
|
131
|
+
</RTVIClientMicToggle>
|
|
132
|
+
```
|
|
133
|
+
|
|
96
134
|
### VoiceVisualizer
|
|
97
135
|
|
|
98
136
|
Renders a visual representation of audio input levels on a `<canvas>` element.
|
|
99
|
-
The visualization consists of
|
|
137
|
+
The visualization consists of vertical bars.
|
|
100
138
|
|
|
101
139
|
#### Props
|
|
102
140
|
|
|
103
141
|
- `participantType` (string, required): The participant type to visualize audio for.
|
|
104
142
|
- `backgroundColor` (string, optional): The background color of the canvas. Default: 'transparent'.
|
|
105
143
|
- `barColor` (string, optional): The color of the audio level bars. Default: 'black'.
|
|
144
|
+
- `barCount` (number, optional): The amount of bars to render. Default: 5
|
|
106
145
|
- `barGap` (number, optional): The gap between bars in pixels. Default: 12.
|
|
146
|
+
- `barLineCap` ('round' | 'square', optional): The line cap for each bar. Default: 'round'
|
|
147
|
+
- `barOrigin` ('bottom' | 'center' | 'top', optional): The origin from where the bars grow to full height. Default: 'center'
|
|
107
148
|
- `barWidth` (number, optional): The width of each bar in pixels. Default: 30.
|
|
108
149
|
- `barMaxHeight` (number, optional): The maximum height at full volume of each bar in pixels. Default: 120.
|
|
109
150
|
|
|
@@ -157,6 +198,30 @@ function EventListener() {
|
|
|
157
198
|
}
|
|
158
199
|
```
|
|
159
200
|
|
|
201
|
+
### useRTVIClientCamControl
|
|
202
|
+
|
|
203
|
+
Allows to control the user's camera state.
|
|
204
|
+
|
|
205
|
+
```jsx
|
|
206
|
+
import { useRTVIClientCamControl } from "@pipecat-ai/client-react";
|
|
207
|
+
|
|
208
|
+
function CustomCamToggle() {
|
|
209
|
+
const { enableCam, isCamEnabled } = useRTVIClientCamControl();
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### useRTVIClientMicControl
|
|
214
|
+
|
|
215
|
+
Allows to control the user's microphone state.
|
|
216
|
+
|
|
217
|
+
```jsx
|
|
218
|
+
import { useRTVIClientMicControl } from "@pipecat-ai/client-react";
|
|
219
|
+
|
|
220
|
+
function CustomMicToggle() {
|
|
221
|
+
const { enableMic, isMicEnabled } = useRTVIClientMicControl();
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
160
225
|
### useRTVIClientMediaDevices
|
|
161
226
|
|
|
162
227
|
Manage and list available media devices.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RTVIClient, RTVIEvent, RTVIEventHandler, Tracks, TransportState } from "@pipecat-ai/client-js";
|
|
2
2
|
import { Provider } from "jotai/react";
|
|
3
|
-
import { JSX } from "react/jsx-runtime";
|
|
4
3
|
import React from "react";
|
|
4
|
+
import { JSX } from "react/jsx-runtime";
|
|
5
5
|
interface Props {
|
|
6
6
|
client: RTVIClient;
|
|
7
7
|
jotaiStore?: React.ComponentProps<typeof Provider>["store"];
|
|
@@ -16,6 +16,68 @@ export const RTVIClientAudio: {
|
|
|
16
16
|
(): JSX.Element;
|
|
17
17
|
displayName: string;
|
|
18
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* Hook to control camera state
|
|
21
|
+
*/
|
|
22
|
+
export const useRTVIClientCamControl: () => {
|
|
23
|
+
enableCam: (enabled: boolean) => void;
|
|
24
|
+
isCamEnabled: boolean;
|
|
25
|
+
};
|
|
26
|
+
interface RTVIClientCamToggleProps {
|
|
27
|
+
/**
|
|
28
|
+
* Callback fired when camera state changes
|
|
29
|
+
*/
|
|
30
|
+
onCamEnabledChanged?: (enabled: boolean) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Optional prop to disable the cam toggle.
|
|
33
|
+
* When disabled, changes are not applied to the client.
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Render prop that provides state and handlers to the children
|
|
39
|
+
*/
|
|
40
|
+
children: (props: {
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
isCamEnabled: boolean;
|
|
43
|
+
onClick: () => void;
|
|
44
|
+
}) => React.ReactNode;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Headless component for controlling camera state
|
|
48
|
+
*/
|
|
49
|
+
export const RTVIClientCamToggle: React.FC<RTVIClientCamToggleProps>;
|
|
50
|
+
/**
|
|
51
|
+
* Hook to control microphone state
|
|
52
|
+
*/
|
|
53
|
+
export const useRTVIClientMicControl: () => {
|
|
54
|
+
enableMic: (enabled: boolean) => void;
|
|
55
|
+
isMicEnabled: boolean;
|
|
56
|
+
};
|
|
57
|
+
interface RTVIClientMicToggleProps {
|
|
58
|
+
/**
|
|
59
|
+
* Callback fired when microphone state changes
|
|
60
|
+
*/
|
|
61
|
+
onMicEnabledChanged?: (enabled: boolean) => void;
|
|
62
|
+
/**
|
|
63
|
+
* Optional prop to disable the mic toggle.
|
|
64
|
+
* When disabled, changes are not applied to the client.
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
disabled?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Render prop that provides state and handlers to the children
|
|
70
|
+
*/
|
|
71
|
+
children: (props: {
|
|
72
|
+
disabled?: boolean;
|
|
73
|
+
isMicEnabled: boolean;
|
|
74
|
+
onClick: () => void;
|
|
75
|
+
}) => React.ReactNode;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Headless component for controlling microphone state
|
|
79
|
+
*/
|
|
80
|
+
export const RTVIClientMicToggle: React.FC<RTVIClientMicToggleProps>;
|
|
19
81
|
interface RTVIClientVideoInterface {
|
|
20
82
|
aspectRatio: number;
|
|
21
83
|
height: number;
|
|
@@ -59,9 +121,12 @@ type _ParticipantType1 = Parameters<typeof useRTVIClientMediaTrack>[1];
|
|
|
59
121
|
interface _Props2 {
|
|
60
122
|
backgroundColor?: string;
|
|
61
123
|
barColor?: string;
|
|
124
|
+
barCount?: number;
|
|
62
125
|
barGap?: number;
|
|
63
|
-
|
|
126
|
+
barLineCap?: "round" | "square";
|
|
64
127
|
barMaxHeight?: number;
|
|
128
|
+
barOrigin?: "top" | "bottom" | "center";
|
|
129
|
+
barWidth?: number;
|
|
65
130
|
participantType: _ParticipantType1;
|
|
66
131
|
}
|
|
67
132
|
export const VoiceVisualizer: React.FC<_Props2>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;
|
|
1
|
+
{"mappings":"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","sources":["client-react/src/src/RTVIClientProvider.tsx","client-react/src/src/useRTVIClient.ts","client-react/src/src/useRTVIClientEvent.ts","client-react/src/src/useRTVIClientMediaTrack.ts","client-react/src/src/RTVIClientAudio.tsx","client-react/src/src/useRTVIClientCamControl.ts","client-react/src/src/RTVIClientCamToggle.tsx","client-react/src/src/useRTVIClientMicControl.ts","client-react/src/src/RTVIClientMicToggle.tsx","client-react/src/src/useMergedRef.ts","client-react/src/src/RTVIClientVideo.tsx","client-react/src/src/useRTVIClientMediaDevices.ts","client-react/src/src/useRTVIClientTransportState.ts","client-react/src/src/VoiceVisualizer.tsx","client-react/src/src/index.ts","client-react/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"/**\n * Copyright (c) 2024, Daily.\n *\n * SPDX-License-Identifier: BSD-2-Clause\n */\n\nimport { RTVIClientAudio } from \"./RTVIClientAudio\";\nimport { RTVIClientCamToggle } from \"./RTVIClientCamToggle\";\nimport { RTVIClientMicToggle } from \"./RTVIClientMicToggle\";\nimport { RTVIClientProvider } from \"./RTVIClientProvider\";\nimport { RTVIClientVideo } from \"./RTVIClientVideo\";\nimport { useRTVIClient } from \"./useRTVIClient\";\nimport { useRTVIClientCamControl } from \"./useRTVIClientCamControl\";\nimport { useRTVIClientEvent } from \"./useRTVIClientEvent\";\nimport { useRTVIClientMediaDevices } from \"./useRTVIClientMediaDevices\";\nimport { useRTVIClientMediaTrack } from \"./useRTVIClientMediaTrack\";\nimport { useRTVIClientMicControl } from \"./useRTVIClientMicControl\";\nimport { useRTVIClientTransportState } from \"./useRTVIClientTransportState\";\nimport { VoiceVisualizer } from \"./VoiceVisualizer\";\n\nexport {\n RTVIClientAudio,\n RTVIClientCamToggle,\n RTVIClientMicToggle,\n RTVIClientProvider,\n RTVIClientVideo,\n useRTVIClient,\n useRTVIClientCamControl,\n useRTVIClientEvent,\n useRTVIClientMediaDevices,\n useRTVIClientMediaTrack,\n useRTVIClientMicControl,\n useRTVIClientTransportState,\n VoiceVisualizer,\n};\n"],"names":[],"version":3,"file":"index.d.ts.map"}
|
package/dist/index.js
CHANGED
|
@@ -15,12 +15,16 @@ function $parcel$interopDefault(a) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
$parcel$export(module.exports, "RTVIClientAudio", () => $e6a9aa6ceb34e585$export$ba1245f7cbf3ae02);
|
|
18
|
+
$parcel$export(module.exports, "RTVIClientCamToggle", () => $e7a27a30474b270e$export$156c26e16246ae3e);
|
|
19
|
+
$parcel$export(module.exports, "RTVIClientMicToggle", () => $8a175691955798a2$export$bf1c2c9ca877628d);
|
|
18
20
|
$parcel$export(module.exports, "RTVIClientProvider", () => $0befa35d025c789a$export$4a4ae2d5dc96782);
|
|
19
21
|
$parcel$export(module.exports, "RTVIClientVideo", () => $c1952f9ddec789e5$export$d090a384943608eb);
|
|
20
22
|
$parcel$export(module.exports, "useRTVIClient", () => $8ee07494475a7fa7$export$31a5f6a22c9b8fba);
|
|
23
|
+
$parcel$export(module.exports, "useRTVIClientCamControl", () => $affd351738e2f16c$export$46099a7ec2fe8ac5);
|
|
21
24
|
$parcel$export(module.exports, "useRTVIClientEvent", () => $8a6b68ebf0332682$export$33a6ac53b8f02625);
|
|
22
25
|
$parcel$export(module.exports, "useRTVIClientMediaDevices", () => $01bcacdf0a25e20c$export$652c54907b83a48d);
|
|
23
26
|
$parcel$export(module.exports, "useRTVIClientMediaTrack", () => $e5be552b22401c66$export$7c03381e0d26a6c3);
|
|
27
|
+
$parcel$export(module.exports, "useRTVIClientMicControl", () => $b5946020fafb75c5$export$805915964ad7bc25);
|
|
24
28
|
$parcel$export(module.exports, "useRTVIClientTransportState", () => $6b6c1a9f794236bd$export$599fa01283bd4ece);
|
|
25
29
|
$parcel$export(module.exports, "VoiceVisualizer", () => $a1dfa75b13e6bb9b$export$59bf27bd43679db6);
|
|
26
30
|
/**
|
|
@@ -125,18 +129,18 @@ const $e5be552b22401c66$export$7c03381e0d26a6c3 = (trackType, participantType)=>
|
|
|
125
129
|
const oldTrack = get(atom);
|
|
126
130
|
if (oldTrack?.id === track.id) return;
|
|
127
131
|
set(atom, track);
|
|
128
|
-
}, [
|
|
129
|
-
participantType,
|
|
130
|
-
track,
|
|
131
|
-
trackType
|
|
132
|
-
]));
|
|
132
|
+
}, []));
|
|
133
133
|
(0, $8a6b68ebf0332682$export$33a6ac53b8f02625)((0, $5Zyvw$pipecataiclientjs.RTVIEvent).TrackStarted, (0, $5Zyvw$react.useCallback)((track, participant)=>{
|
|
134
134
|
updateTrack(track, track.kind, Boolean(participant?.local));
|
|
135
|
-
}, [
|
|
135
|
+
}, [
|
|
136
|
+
updateTrack
|
|
137
|
+
]));
|
|
136
138
|
(0, $8a6b68ebf0332682$export$33a6ac53b8f02625)((0, $5Zyvw$pipecataiclientjs.RTVIEvent).ScreenTrackStarted, (0, $5Zyvw$react.useCallback)((track, participant)=>{
|
|
137
139
|
const trackType = track.kind === "audio" ? "screenAudio" : "screenVideo";
|
|
138
140
|
updateTrack(track, trackType, Boolean(participant?.local));
|
|
139
|
-
}, [
|
|
141
|
+
}, [
|
|
142
|
+
updateTrack
|
|
143
|
+
]));
|
|
140
144
|
(0, $5Zyvw$react.useEffect)(()=>{
|
|
141
145
|
if (!client) return;
|
|
142
146
|
const tracks = client.tracks();
|
|
@@ -186,6 +190,108 @@ $e6a9aa6ceb34e585$export$ba1245f7cbf3ae02.displayName = "RTVIClientAudio";
|
|
|
186
190
|
|
|
187
191
|
|
|
188
192
|
|
|
193
|
+
|
|
194
|
+
const $affd351738e2f16c$export$46099a7ec2fe8ac5 = ()=>{
|
|
195
|
+
const client = (0, $8ee07494475a7fa7$export$31a5f6a22c9b8fba)();
|
|
196
|
+
const [isCamEnabled, setIsCamEnabled] = (0, $5Zyvw$react.useState)(client?.isCamEnabled ?? false);
|
|
197
|
+
// Sync component state with client state initially
|
|
198
|
+
(0, $5Zyvw$react.useEffect)(()=>{
|
|
199
|
+
if (!client) return;
|
|
200
|
+
setIsCamEnabled(client.isCamEnabled);
|
|
201
|
+
}, [
|
|
202
|
+
client
|
|
203
|
+
]);
|
|
204
|
+
const enableCam = (0, $5Zyvw$react.useCallback)((enabled)=>{
|
|
205
|
+
setIsCamEnabled(enabled);
|
|
206
|
+
client?.enableCam?.(enabled);
|
|
207
|
+
}, [
|
|
208
|
+
client
|
|
209
|
+
]);
|
|
210
|
+
return {
|
|
211
|
+
enableCam: enableCam,
|
|
212
|
+
isCamEnabled: isCamEnabled
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
const $e7a27a30474b270e$export$156c26e16246ae3e = ({ onCamEnabledChanged: onCamEnabledChanged, disabled: disabled = false, children: children })=>{
|
|
218
|
+
const { isCamEnabled: isCamEnabled, enableCam: enableCam } = (0, $affd351738e2f16c$export$46099a7ec2fe8ac5)();
|
|
219
|
+
const handleToggleCam = (0, $5Zyvw$react.useCallback)(()=>{
|
|
220
|
+
if (disabled) return;
|
|
221
|
+
const newEnabledState = !isCamEnabled;
|
|
222
|
+
enableCam(newEnabledState);
|
|
223
|
+
onCamEnabledChanged?.(newEnabledState);
|
|
224
|
+
}, [
|
|
225
|
+
disabled,
|
|
226
|
+
enableCam,
|
|
227
|
+
isCamEnabled,
|
|
228
|
+
onCamEnabledChanged
|
|
229
|
+
]);
|
|
230
|
+
return (0, $5Zyvw$reactjsxruntime.jsx)((0, $5Zyvw$reactjsxruntime.Fragment), {
|
|
231
|
+
children: children({
|
|
232
|
+
isCamEnabled: isCamEnabled,
|
|
233
|
+
onClick: handleToggleCam,
|
|
234
|
+
disabled: disabled
|
|
235
|
+
})
|
|
236
|
+
});
|
|
237
|
+
};
|
|
238
|
+
var $e7a27a30474b270e$export$2e2bcd8739ae039 = $e7a27a30474b270e$export$156c26e16246ae3e;
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
const $b5946020fafb75c5$export$805915964ad7bc25 = ()=>{
|
|
246
|
+
const client = (0, $8ee07494475a7fa7$export$31a5f6a22c9b8fba)();
|
|
247
|
+
const [isMicEnabled, setIsMicEnabled] = (0, $5Zyvw$react.useState)(client?.isMicEnabled ?? false);
|
|
248
|
+
// Sync component state with client state initially
|
|
249
|
+
(0, $5Zyvw$react.useEffect)(()=>{
|
|
250
|
+
if (!client) return;
|
|
251
|
+
setIsMicEnabled(client.isMicEnabled);
|
|
252
|
+
}, [
|
|
253
|
+
client
|
|
254
|
+
]);
|
|
255
|
+
const enableMic = (0, $5Zyvw$react.useCallback)((enabled)=>{
|
|
256
|
+
setIsMicEnabled(enabled);
|
|
257
|
+
client?.enableMic?.(enabled);
|
|
258
|
+
}, [
|
|
259
|
+
client
|
|
260
|
+
]);
|
|
261
|
+
return {
|
|
262
|
+
enableMic: enableMic,
|
|
263
|
+
isMicEnabled: isMicEnabled
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
const $8a175691955798a2$export$bf1c2c9ca877628d = ({ onMicEnabledChanged: onMicEnabledChanged, disabled: disabled = false, children: children })=>{
|
|
269
|
+
const { enableMic: enableMic, isMicEnabled: isMicEnabled } = (0, $b5946020fafb75c5$export$805915964ad7bc25)();
|
|
270
|
+
const handleToggleMic = (0, $5Zyvw$react.useCallback)(()=>{
|
|
271
|
+
if (disabled) return;
|
|
272
|
+
const newEnabledState = !isMicEnabled;
|
|
273
|
+
enableMic(newEnabledState);
|
|
274
|
+
onMicEnabledChanged?.(newEnabledState);
|
|
275
|
+
}, [
|
|
276
|
+
disabled,
|
|
277
|
+
enableMic,
|
|
278
|
+
isMicEnabled,
|
|
279
|
+
onMicEnabledChanged
|
|
280
|
+
]);
|
|
281
|
+
return (0, $5Zyvw$reactjsxruntime.jsx)((0, $5Zyvw$reactjsxruntime.Fragment), {
|
|
282
|
+
children: children({
|
|
283
|
+
isMicEnabled: isMicEnabled,
|
|
284
|
+
onClick: handleToggleMic,
|
|
285
|
+
disabled: disabled
|
|
286
|
+
})
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
var $8a175691955798a2$export$2e2bcd8739ae039 = $8a175691955798a2$export$bf1c2c9ca877628d;
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
189
295
|
/**
|
|
190
296
|
* Copyright (c) 2024, Daily.
|
|
191
297
|
*
|
|
@@ -334,6 +440,7 @@ $c1952f9ddec789e5$export$d090a384943608eb.displayName = "RTVIClientVideo";
|
|
|
334
440
|
|
|
335
441
|
|
|
336
442
|
|
|
443
|
+
|
|
337
444
|
const $01bcacdf0a25e20c$var$availableMicsAtom = (0, $5Zyvw$jotai.atom)([]);
|
|
338
445
|
const $01bcacdf0a25e20c$var$availableCamsAtom = (0, $5Zyvw$jotai.atom)([]);
|
|
339
446
|
const $01bcacdf0a25e20c$var$availableSpeakersAtom = (0, $5Zyvw$jotai.atom)([]);
|
|
@@ -348,6 +455,25 @@ const $01bcacdf0a25e20c$export$652c54907b83a48d = ()=>{
|
|
|
348
455
|
const selectedCam = (0, $5Zyvw$jotai.useAtomValue)($01bcacdf0a25e20c$var$selectedCamAtom);
|
|
349
456
|
const selectedMic = (0, $5Zyvw$jotai.useAtomValue)($01bcacdf0a25e20c$var$selectedMicAtom);
|
|
350
457
|
const selectedSpeaker = (0, $5Zyvw$jotai.useAtomValue)($01bcacdf0a25e20c$var$selectedSpeakerAtom);
|
|
458
|
+
const initDevices = (0, $5Zyvw$jotaiutils.useAtomCallback)((0, $5Zyvw$react.useCallback)(async (_get, set)=>{
|
|
459
|
+
if (!client) return;
|
|
460
|
+
const availableCams = await client.getAllCams();
|
|
461
|
+
const availableMics = await client.getAllMics();
|
|
462
|
+
const availableSpeakers = await client.getAllSpeakers();
|
|
463
|
+
set($01bcacdf0a25e20c$var$availableCamsAtom, availableCams);
|
|
464
|
+
set($01bcacdf0a25e20c$var$availableMicsAtom, availableMics);
|
|
465
|
+
set($01bcacdf0a25e20c$var$availableSpeakersAtom, availableSpeakers);
|
|
466
|
+
set($01bcacdf0a25e20c$var$selectedCamAtom, client.selectedCam);
|
|
467
|
+
set($01bcacdf0a25e20c$var$selectedMicAtom, client.selectedMic);
|
|
468
|
+
set($01bcacdf0a25e20c$var$selectedSpeakerAtom, client.selectedSpeaker);
|
|
469
|
+
}, [
|
|
470
|
+
client
|
|
471
|
+
]));
|
|
472
|
+
(0, $5Zyvw$react.useEffect)(()=>{
|
|
473
|
+
initDevices();
|
|
474
|
+
}, [
|
|
475
|
+
initDevices
|
|
476
|
+
]);
|
|
351
477
|
(0, $8a6b68ebf0332682$export$33a6ac53b8f02625)((0, $5Zyvw$pipecataiclientjs.RTVIEvent).AvailableCamsUpdated, (0, $5Zyvw$jotaiutils.useAtomCallback)((0, $5Zyvw$react.useCallback)((_get, set, cams)=>{
|
|
352
478
|
set($01bcacdf0a25e20c$var$availableCamsAtom, cams);
|
|
353
479
|
}, [])));
|
|
@@ -396,6 +522,7 @@ const $01bcacdf0a25e20c$export$652c54907b83a48d = ()=>{
|
|
|
396
522
|
|
|
397
523
|
|
|
398
524
|
|
|
525
|
+
|
|
399
526
|
/**
|
|
400
527
|
* Copyright (c) 2024, Daily.
|
|
401
528
|
*
|
|
@@ -414,12 +541,12 @@ const $6b6c1a9f794236bd$export$599fa01283bd4ece = ()=>{
|
|
|
414
541
|
|
|
415
542
|
|
|
416
543
|
|
|
417
|
-
const $a1dfa75b13e6bb9b$export$59bf27bd43679db6 = /*#__PURE__*/ (0, ($parcel$interopDefault($5Zyvw$react))).memo(({ backgroundColor: backgroundColor = "transparent", barColor: barColor = "black",
|
|
544
|
+
const $a1dfa75b13e6bb9b$export$59bf27bd43679db6 = /*#__PURE__*/ (0, ($parcel$interopDefault($5Zyvw$react))).memo(({ backgroundColor: backgroundColor = "transparent", barColor: barColor = "black", barCount: barCount = 5, barGap: barGap = 12, barLineCap: barLineCap = "round", barMaxHeight: barMaxHeight = 120, barOrigin: barOrigin = "center", barWidth: barWidth = 30, participantType: participantType })=>{
|
|
418
545
|
const canvasRef = (0, $5Zyvw$react.useRef)(null);
|
|
419
546
|
const track = (0, $e5be552b22401c66$export$7c03381e0d26a6c3)("audio", participantType);
|
|
420
547
|
(0, $5Zyvw$react.useEffect)(()=>{
|
|
421
548
|
if (!canvasRef.current) return;
|
|
422
|
-
const canvasWidth =
|
|
549
|
+
const canvasWidth = barCount * barWidth + (barCount - 1) * barGap;
|
|
423
550
|
const canvasHeight = barMaxHeight;
|
|
424
551
|
const canvas = canvasRef.current;
|
|
425
552
|
const scaleFactor = 2;
|
|
@@ -429,7 +556,7 @@ const $a1dfa75b13e6bb9b$export$59bf27bd43679db6 = /*#__PURE__*/ (0, ($parcel$int
|
|
|
429
556
|
canvas.height = canvasHeight * scaleFactor;
|
|
430
557
|
canvas.style.width = `${canvasWidth}px`;
|
|
431
558
|
canvas.style.height = `${canvasHeight}px`;
|
|
432
|
-
canvasCtx.lineCap =
|
|
559
|
+
canvasCtx.lineCap = barLineCap;
|
|
433
560
|
canvasCtx.scale(scaleFactor, scaleFactor);
|
|
434
561
|
};
|
|
435
562
|
const canvasCtx = canvas.getContext("2d");
|
|
@@ -443,34 +570,29 @@ const $a1dfa75b13e6bb9b$export$59bf27bd43679db6 = /*#__PURE__*/ (0, ($parcel$int
|
|
|
443
570
|
analyser.fftSize = 1024;
|
|
444
571
|
source.connect(analyser);
|
|
445
572
|
const frequencyData = new Uint8Array(analyser.frequencyBinCount);
|
|
446
|
-
canvasCtx.lineCap =
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
573
|
+
canvasCtx.lineCap = barLineCap;
|
|
574
|
+
// Create frequency bands based on barCount
|
|
575
|
+
const bands = Array.from({
|
|
576
|
+
length: barCount
|
|
577
|
+
}, (_, i)=>{
|
|
578
|
+
// Use improved logarithmic scale for better frequency distribution
|
|
579
|
+
const minFreq = barCount > 20 ? 200 : 80; // Adjust min frequency based on bar count
|
|
580
|
+
const maxFreq = 10000; // Cover most important audio frequencies
|
|
581
|
+
// Use Mel scale inspired approach for more perceptually uniform distribution
|
|
582
|
+
// This helps with a large number of bars by placing fewer in the very low range
|
|
583
|
+
// https://en.wikipedia.org/wiki/Mel_scale
|
|
584
|
+
const melMin = 2595 * Math.log10(1 + minFreq / 700);
|
|
585
|
+
const melMax = 2595 * Math.log10(1 + maxFreq / 700);
|
|
586
|
+
const melStep = (melMax - melMin) / barCount;
|
|
587
|
+
const melValue = melMin + i * melStep;
|
|
588
|
+
const startFreq = 700 * (Math.pow(10, melValue / 2595) - 1);
|
|
589
|
+
const endFreq = 700 * (Math.pow(10, (melValue + melStep) / 2595) - 1);
|
|
590
|
+
return {
|
|
591
|
+
startFreq: startFreq,
|
|
592
|
+
endFreq: endFreq,
|
|
461
593
|
smoothValue: 0
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
startFreq: 2000,
|
|
465
|
-
endFreq: 4000,
|
|
466
|
-
smoothValue: 0
|
|
467
|
-
},
|
|
468
|
-
{
|
|
469
|
-
startFreq: 4000,
|
|
470
|
-
endFreq: 8000,
|
|
471
|
-
smoothValue: 0
|
|
472
|
-
}
|
|
473
|
-
];
|
|
594
|
+
};
|
|
595
|
+
});
|
|
474
596
|
const getFrequencyBinIndex = (frequency)=>{
|
|
475
597
|
const nyquist = audioContext.sampleRate / 2;
|
|
476
598
|
return Math.round(frequency / nyquist * (analyser.frequencyBinCount - 1));
|
|
@@ -497,9 +619,25 @@ const $a1dfa75b13e6bb9b$export$59bf27bd43679db6 = /*#__PURE__*/ (0, ($parcel$int
|
|
|
497
619
|
}
|
|
498
620
|
const x = startX + i * (barWidth + barGap);
|
|
499
621
|
// Calculate bar height with a maximum cap
|
|
500
|
-
const
|
|
501
|
-
const
|
|
502
|
-
|
|
622
|
+
const minHeight = 0;
|
|
623
|
+
const barHeight = Math.max(minHeight, Math.min(band.smoothValue / 255 * barMaxHeight, barMaxHeight));
|
|
624
|
+
let yTop, yBottom;
|
|
625
|
+
const canvasHeight = canvas.height / scaleFactor;
|
|
626
|
+
switch(barOrigin){
|
|
627
|
+
case "top":
|
|
628
|
+
yTop = adjustedCircleRadius;
|
|
629
|
+
yBottom = Math.min(adjustedCircleRadius + barHeight, canvasHeight - adjustedCircleRadius);
|
|
630
|
+
break;
|
|
631
|
+
case "bottom":
|
|
632
|
+
yBottom = canvasHeight - adjustedCircleRadius;
|
|
633
|
+
yTop = Math.max(yBottom - barHeight, adjustedCircleRadius);
|
|
634
|
+
break;
|
|
635
|
+
case "center":
|
|
636
|
+
default:
|
|
637
|
+
yTop = Math.max(canvasHeight / 2 - barHeight / 2, adjustedCircleRadius);
|
|
638
|
+
yBottom = Math.min(canvasHeight / 2 + barHeight / 2, canvasHeight - adjustedCircleRadius);
|
|
639
|
+
break;
|
|
640
|
+
}
|
|
503
641
|
if (band.smoothValue > 0) {
|
|
504
642
|
canvasCtx.beginPath();
|
|
505
643
|
canvasCtx.moveTo(x + barWidth / 2, yTop);
|
|
@@ -507,28 +645,47 @@ const $a1dfa75b13e6bb9b$export$59bf27bd43679db6 = /*#__PURE__*/ (0, ($parcel$int
|
|
|
507
645
|
canvasCtx.lineWidth = barWidth;
|
|
508
646
|
canvasCtx.strokeStyle = barColor;
|
|
509
647
|
canvasCtx.stroke();
|
|
510
|
-
} else
|
|
511
|
-
canvasCtx.beginPath();
|
|
512
|
-
canvasCtx.arc(x + barWidth / 2, canvas.height / scaleFactor / 2, adjustedCircleRadius, 0, 2 * Math.PI);
|
|
513
|
-
canvasCtx.fillStyle = barColor;
|
|
514
|
-
canvasCtx.fill();
|
|
515
|
-
canvasCtx.closePath();
|
|
516
|
-
}
|
|
648
|
+
} else drawInactiveCircle(adjustedCircleRadius, barColor, x, yTop);
|
|
517
649
|
});
|
|
518
650
|
if (!isActive) drawInactiveCircles(adjustedCircleRadius, barColor);
|
|
519
651
|
requestAnimationFrame(drawSpectrum);
|
|
520
652
|
}
|
|
653
|
+
function drawInactiveCircle(circleRadius, color, x, y) {
|
|
654
|
+
switch(barLineCap){
|
|
655
|
+
case "square":
|
|
656
|
+
canvasCtx.fillStyle = color;
|
|
657
|
+
canvasCtx.fillRect(x + barWidth / 2 - circleRadius, y - circleRadius, circleRadius * 2, circleRadius * 2);
|
|
658
|
+
break;
|
|
659
|
+
case "round":
|
|
660
|
+
default:
|
|
661
|
+
canvasCtx.beginPath();
|
|
662
|
+
canvasCtx.arc(x + barWidth / 2, y, circleRadius, 0, 2 * Math.PI);
|
|
663
|
+
canvasCtx.fillStyle = color;
|
|
664
|
+
canvasCtx.fill();
|
|
665
|
+
canvasCtx.closePath();
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
521
669
|
function drawInactiveCircles(circleRadius, color) {
|
|
522
670
|
const totalBarsWidth = bands.length * barWidth + (bands.length - 1) * barGap;
|
|
523
671
|
const startX = (canvas.width / scaleFactor - totalBarsWidth) / 2;
|
|
524
|
-
const
|
|
672
|
+
const canvasHeight = canvas.height / scaleFactor;
|
|
673
|
+
let y;
|
|
674
|
+
switch(barOrigin){
|
|
675
|
+
case "top":
|
|
676
|
+
y = circleRadius;
|
|
677
|
+
break;
|
|
678
|
+
case "bottom":
|
|
679
|
+
y = canvasHeight - circleRadius;
|
|
680
|
+
break;
|
|
681
|
+
case "center":
|
|
682
|
+
default:
|
|
683
|
+
y = canvasHeight / 2;
|
|
684
|
+
break;
|
|
685
|
+
}
|
|
525
686
|
bands.forEach((_, i)=>{
|
|
526
687
|
const x = startX + i * (barWidth + barGap);
|
|
527
|
-
|
|
528
|
-
canvasCtx.arc(x + barWidth / 2, y, circleRadius, 0, 2 * Math.PI);
|
|
529
|
-
canvasCtx.fillStyle = color;
|
|
530
|
-
canvasCtx.fill();
|
|
531
|
-
canvasCtx.closePath();
|
|
688
|
+
drawInactiveCircle(circleRadius, color, x, y);
|
|
532
689
|
});
|
|
533
690
|
}
|
|
534
691
|
drawSpectrum();
|
|
@@ -541,8 +698,11 @@ const $a1dfa75b13e6bb9b$export$59bf27bd43679db6 = /*#__PURE__*/ (0, ($parcel$int
|
|
|
541
698
|
}, [
|
|
542
699
|
backgroundColor,
|
|
543
700
|
barColor,
|
|
701
|
+
barCount,
|
|
544
702
|
barGap,
|
|
703
|
+
barLineCap,
|
|
545
704
|
barMaxHeight,
|
|
705
|
+
barOrigin,
|
|
546
706
|
barWidth,
|
|
547
707
|
track
|
|
548
708
|
]);
|