@elevenlabs/react-native 0.5.5 → 0.5.7

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.
@@ -2,7 +2,7 @@
2
2
  import React from 'react';
3
3
  import { LiveKitRoom } from '@livekit/react-native';
4
4
  import type { LocalParticipant } from 'livekit-client';
5
- import type { Callbacks, ClientToolsConfig } from '../types';
5
+ import type { Callbacks, ClientToolsConfig, AudioSessionConfig } from '../types';
6
6
  import { MessageHandler } from './MessageHandler';
7
7
 
8
8
  interface LiveKitRoomWrapperProps {
@@ -20,6 +20,8 @@ interface LiveKitRoomWrapperProps {
20
20
  clientTools: ClientToolsConfig['clientTools'];
21
21
  onEndSession: (reason?: "user" | "agent") => void;
22
22
  updateCurrentEventId?: (eventId: number) => void;
23
+ audioSessionConfig?: AudioSessionConfig;
24
+ textOnly?: boolean;
23
25
  }
24
26
 
25
27
  export const LiveKitRoomWrapper = ({
@@ -37,13 +39,37 @@ export const LiveKitRoomWrapper = ({
37
39
  clientTools,
38
40
  updateCurrentEventId,
39
41
  onEndSession,
42
+ audioSessionConfig,
43
+ textOnly = false,
40
44
  }: LiveKitRoomWrapperProps) => {
45
+ // Configure audio options based on audioSessionConfig
46
+ const audioOptions = React.useMemo(() => {
47
+ if (textOnly) {
48
+ return false;
49
+ }
50
+
51
+ if (!audioSessionConfig?.allowMixingWithOthers) {
52
+ return true;
53
+ }
54
+
55
+ // When mixing is enabled, configure audio to allow concurrent playback
56
+ return {
57
+ audio: {
58
+ noiseSuppression: true,
59
+ echoCancellation: true,
60
+ },
61
+ audioSessionConfiguration: {
62
+ allowMixingWithOthers: true,
63
+ },
64
+ };
65
+ }, [audioSessionConfig, textOnly]);
66
+
41
67
  return (
42
68
  <LiveKitRoom
43
69
  serverUrl={serverUrl}
44
70
  token={token}
45
71
  connect={connect}
46
- audio={true}
72
+ audio={audioOptions}
47
73
  video={false}
48
74
  options={{
49
75
  adaptiveStream: { pixelDensity: 'screen' },
@@ -7,12 +7,14 @@ export const useLiveKitRoom = (
7
7
  callbacksRef: { current: Callbacks },
8
8
  setStatus: (status: ConversationStatus) => void,
9
9
  conversationId: string,
10
- status: ConversationStatus
10
+ status: ConversationStatus,
11
+ textOnly: boolean = false
11
12
  ) => {
12
13
  const [roomConnected, setRoomConnected] = useState(false);
13
14
  const [localParticipant, setLocalParticipant] =
14
15
  useState<LocalParticipant | null>(null);
15
16
  const hasCalledOnConnectRef = useRef(false);
17
+ const audioSessionActiveRef = useRef(false);
16
18
 
17
19
  // Reset room state when conversationId changes (new session starting)
18
20
  useEffect(() => {
@@ -24,15 +26,23 @@ export const useLiveKitRoom = (
24
26
  }, [conversationId]);
25
27
 
26
28
  useEffect(() => {
27
- const start = async () => {
28
- await AudioSession.startAudioSession();
29
- };
29
+ const shouldHaveAudio = !textOnly && !!conversationId;
30
30
 
31
- start();
32
- return () => {
31
+ if (shouldHaveAudio && !audioSessionActiveRef.current) {
32
+ audioSessionActiveRef.current = true;
33
+ AudioSession.startAudioSession();
34
+ } else if (!shouldHaveAudio && audioSessionActiveRef.current) {
35
+ audioSessionActiveRef.current = false;
33
36
  AudioSession.stopAudioSession();
37
+ }
38
+
39
+ return () => {
40
+ if (audioSessionActiveRef.current) {
41
+ audioSessionActiveRef.current = false;
42
+ AudioSession.stopAudioSession();
43
+ }
34
44
  };
35
- }, []);
45
+ }, [textOnly, conversationId]);
36
46
 
37
47
  // Fire onConnect when both participant and room are fully ready
38
48
  useEffect(() => {
package/src/index.ts CHANGED
@@ -12,4 +12,5 @@ export type {
12
12
  ConversationOptions,
13
13
  ConversationConfig,
14
14
  ConversationEvent,
15
+ AudioSessionConfig,
15
16
  } from "./types";
package/src/types.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import type * as Types from "@elevenlabs/types";
2
2
  import type {
3
+ AsrInitiationMetadataEvent as AsrMetadataEvent,
4
+ Callbacks,
5
+ ConversationMetadata,
6
+ Mode as ConversationMode,
3
7
  Incoming,
4
- Outgoing,
5
8
  Interruption,
6
- ConversationMetadata,
7
- Ping,
8
9
  Role as MessageRole,
9
- Mode as ConversationMode,
10
+ Outgoing,
11
+ Ping,
10
12
  Status,
11
- Callbacks,
12
- AsrInitiationMetadataEvent as AsrMetadataEvent,
13
13
  } from "@elevenlabs/types";
14
14
  export type { Callbacks } from "@elevenlabs/types";
15
15
 
@@ -70,6 +70,7 @@ export type ConversationConfig = {
70
70
  };
71
71
  tts?: {
72
72
  voiceId?: string;
73
+ speed?: number;
73
74
  };
74
75
  conversation?: {
75
76
  textOnly?: boolean;
@@ -139,3 +140,20 @@ export type ConversationEvent =
139
140
  | ConversationMetadataEvent
140
141
  | AsrInitiationMetadataEvent
141
142
  | AgentChatResponsePartEvent;
143
+
144
+ /**
145
+ * Audio session configuration for controlling how the SDK handles audio
146
+ */
147
+ export interface AudioSessionConfig {
148
+ /**
149
+ * Whether audio should mix with other audio sources.
150
+ * When true, the SDK will configure the audio session to allow
151
+ * concurrent audio playback with other audio sources.
152
+ *
153
+ * iOS: Adds AVAudioSessionCategoryOptionMixWithOthers
154
+ * Android: Uses AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
155
+ *
156
+ * @default false (exclusive audio session)
157
+ */
158
+ allowMixingWithOthers?: boolean;
159
+ }
@@ -17,6 +17,7 @@ export function constructOverrides(
17
17
  },
18
18
  tts: {
19
19
  voice_id: config.overrides.tts?.voiceId,
20
+ speed: config.overrides.tts?.speed,
20
21
  },
21
22
  conversation: {
22
23
  text_only: config.overrides.conversation?.textOnly,
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated during build
2
- export const PACKAGE_VERSION = "0.5.5";
2
+ export const PACKAGE_VERSION = "0.5.7";