@livekit/react-native 1.2.0 → 1.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 +53 -10
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt +21 -2
- package/android/src/main/java/com/livekit/reactnative/LivekitReactNativeModule.kt +63 -14
- package/android/src/main/java/com/livekit/reactnative/audio/AudioManagerUtils.kt +72 -0
- package/android/src/main/java/com/livekit/reactnative/audio/AudioSwitchManager.java +108 -6
- package/android/src/main/java/com/livekit/reactnative/audio/AudioType.kt +46 -0
- package/android/src/main/java/com/livekit/reactnative/video/SimulcastVideoEncoderFactoryWrapper.kt +2 -1
- package/ios/AudioUtils.h +9 -0
- package/ios/AudioUtils.m +48 -0
- package/ios/LivekitReactNative.m +45 -0
- package/ios/LivekitReactNative.xcodeproj/project.xcworkspace/xcuserdata/davidliu.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/lib/commonjs/audio/AudioManager.js +108 -0
- package/lib/commonjs/audio/AudioManager.js.map +1 -0
- package/lib/commonjs/audio/AudioSession.js +59 -10
- package/lib/commonjs/audio/AudioSession.js.map +1 -1
- package/lib/commonjs/index.js +105 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/logger.js +32 -0
- package/lib/commonjs/logger.js.map +1 -0
- package/lib/module/audio/AudioManager.js +92 -0
- package/lib/module/audio/AudioManager.js.map +1 -0
- package/lib/module/audio/AudioSession.js +54 -9
- package/lib/module/audio/AudioSession.js.map +1 -1
- package/lib/module/index.js +19 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/logger.js +18 -0
- package/lib/module/logger.js.map +1 -0
- package/lib/typescript/audio/AudioManager.d.ts +11 -0
- package/lib/typescript/audio/AudioSession.d.ts +85 -14
- package/lib/typescript/index.d.ts +6 -2
- package/lib/typescript/logger.d.ts +13 -0
- package/package.json +9 -5
- package/src/audio/AudioManager.ts +119 -0
- package/src/audio/AudioSession.ts +206 -23
- package/src/index.tsx +41 -2
- package/src/logger.ts +23 -0
|
@@ -26,17 +26,15 @@ const LivekitReactNative = NativeModules.LivekitReactNative
|
|
|
26
26
|
* This is ignored when an output is manually selected with {@link AudioSession.selectAudioOutput}.
|
|
27
27
|
*
|
|
28
28
|
* By default, the order is set to:
|
|
29
|
-
* 1. `"
|
|
30
|
-
* 2. `"
|
|
31
|
-
* 3. `"
|
|
32
|
-
* 4. `"
|
|
29
|
+
* 1. `"bluetooth"
|
|
30
|
+
* 2. `"headset"``
|
|
31
|
+
* 3. `"speaker"`
|
|
32
|
+
* 4. `"earpiece"`
|
|
33
33
|
*
|
|
34
|
-
* *
|
|
34
|
+
* * audioTypeOptions - An {@link AndroidAudioTypeOptions} object which provides the
|
|
35
|
+
* audio options to use on Android.
|
|
35
36
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* See [AudioManager](https://developer.android.com/reference/android/media/AudioManager) for details
|
|
39
|
-
* on audio and focus modes.
|
|
37
|
+
* See {@link AndroidAudioTypePresets} for pre-configured values.
|
|
40
38
|
*
|
|
41
39
|
* ----
|
|
42
40
|
* iOS
|
|
@@ -48,23 +46,203 @@ const LivekitReactNative = NativeModules.LivekitReactNative
|
|
|
48
46
|
export type AudioConfiguration = {
|
|
49
47
|
android?: {
|
|
50
48
|
preferredOutputList?: ('speaker' | 'earpiece' | 'headset' | 'bluetooth')[];
|
|
51
|
-
|
|
52
|
-
| 'normal'
|
|
53
|
-
| 'callScreening'
|
|
54
|
-
| 'inCall'
|
|
55
|
-
| 'inCommunication'
|
|
56
|
-
| 'ringtone';
|
|
57
|
-
audioFocusMode?:
|
|
58
|
-
| 'gain'
|
|
59
|
-
| 'gainTransient'
|
|
60
|
-
| 'gainTransientExclusive'
|
|
61
|
-
| 'gainTransientMayDuck';
|
|
49
|
+
audioTypeOptions: AndroidAudioTypeOptions;
|
|
62
50
|
};
|
|
63
51
|
ios?: {
|
|
64
52
|
defaultOutput?: 'speaker' | 'earpiece';
|
|
65
53
|
};
|
|
66
54
|
};
|
|
67
55
|
|
|
56
|
+
export type AndroidAudioTypeOptions = {
|
|
57
|
+
/**
|
|
58
|
+
* Whether LiveKit should handle managing the audio focus or not.
|
|
59
|
+
*
|
|
60
|
+
* Defaults to true.
|
|
61
|
+
*/
|
|
62
|
+
manageAudioFocus?: boolean;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Corresponds to {@link https://developer.android.com/reference/android/media/AudioManager#setMode(int)}
|
|
66
|
+
*
|
|
67
|
+
* Defaults to 'inCommunication'.
|
|
68
|
+
*/
|
|
69
|
+
audioMode?:
|
|
70
|
+
| 'normal'
|
|
71
|
+
| 'callScreening'
|
|
72
|
+
| 'inCall'
|
|
73
|
+
| 'inCommunication'
|
|
74
|
+
| 'ringtone';
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Corresponds to the duration hint when requesting audio focus.
|
|
78
|
+
*
|
|
79
|
+
* Defaults to 'gain'.
|
|
80
|
+
*
|
|
81
|
+
* See also {@link https://developer.android.com/reference/android/media/AudioManager#AUDIOFOCUS_GAIN}
|
|
82
|
+
*/
|
|
83
|
+
audioFocusMode?:
|
|
84
|
+
| 'gain'
|
|
85
|
+
| 'gainTransient'
|
|
86
|
+
| 'gainTransientExclusive'
|
|
87
|
+
| 'gainTransientMayDuck';
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Corresponds to Android's AudioAttributes usage type.
|
|
91
|
+
*
|
|
92
|
+
* Defaults to 'voiceCommunication'.
|
|
93
|
+
*
|
|
94
|
+
* See also {@link https://developer.android.com/reference/android/media/AudioAttributes}
|
|
95
|
+
*/
|
|
96
|
+
audioAttributesUsageType?:
|
|
97
|
+
| 'alarm'
|
|
98
|
+
| 'assistanceAccessibility'
|
|
99
|
+
| 'assistanceNavigationGuidance'
|
|
100
|
+
| 'assistanceSonification'
|
|
101
|
+
| 'assistant'
|
|
102
|
+
| 'game'
|
|
103
|
+
| 'media'
|
|
104
|
+
| 'notification'
|
|
105
|
+
| 'notificationEvent'
|
|
106
|
+
| 'notificationRingtone'
|
|
107
|
+
| 'unknown'
|
|
108
|
+
| 'voiceCommunication'
|
|
109
|
+
| 'voiceCommunicationSignalling';
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Corresponds to Android's AndroidAttributes content type.
|
|
113
|
+
*
|
|
114
|
+
* Defaults to 'speech'.
|
|
115
|
+
*
|
|
116
|
+
* See also {@link https://developer.android.com/reference/android/media/AudioAttributes}
|
|
117
|
+
*/
|
|
118
|
+
audioAttributesContentType?:
|
|
119
|
+
| 'movie'
|
|
120
|
+
| 'music'
|
|
121
|
+
| 'sonification'
|
|
122
|
+
| 'speech'
|
|
123
|
+
| 'unknown';
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Corresponds to the stream type when requesting audio focus. Used on pre-O devices.
|
|
127
|
+
*
|
|
128
|
+
* Defaults to 'voiceCall'
|
|
129
|
+
*
|
|
130
|
+
* See also {@link https://developer.android.com/reference/android/media/AudioManager#STREAM_VOICE_CALL}
|
|
131
|
+
*/
|
|
132
|
+
audioStreamType?:
|
|
133
|
+
| 'accessibility'
|
|
134
|
+
| 'alarm'
|
|
135
|
+
| 'dtmf'
|
|
136
|
+
| 'music'
|
|
137
|
+
| 'notification'
|
|
138
|
+
| 'ring'
|
|
139
|
+
| 'system'
|
|
140
|
+
| 'voiceCall';
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* On certain Android devices, audio routing does not function properly and
|
|
144
|
+
* bluetooth microphones will not work unless audio mode is set to
|
|
145
|
+
* `inCommunication` or `inCall`. Audio routing is turned off those cases.
|
|
146
|
+
*
|
|
147
|
+
* If this set to true, will attempt to do audio routing regardless of audio mode.
|
|
148
|
+
*
|
|
149
|
+
* Defaults to false.
|
|
150
|
+
*/
|
|
151
|
+
forceHandleAudioRouting?: boolean;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const AndroidAudioTypePresets: {
|
|
155
|
+
/**
|
|
156
|
+
* A pre-configured AndroidAudioConfiguration for voice communication.
|
|
157
|
+
*/
|
|
158
|
+
communication: AndroidAudioTypeOptions;
|
|
159
|
+
/**
|
|
160
|
+
* A pre-configured AndroidAudioConfiguration for media playback.
|
|
161
|
+
*/
|
|
162
|
+
media: AndroidAudioTypeOptions;
|
|
163
|
+
} = {
|
|
164
|
+
communication: {
|
|
165
|
+
manageAudioFocus: true,
|
|
166
|
+
audioMode: 'inCommunication',
|
|
167
|
+
audioFocusMode: 'gain',
|
|
168
|
+
audioStreamType: 'voiceCall',
|
|
169
|
+
audioAttributesUsageType: 'voiceCommunication',
|
|
170
|
+
audioAttributesContentType: 'speech',
|
|
171
|
+
},
|
|
172
|
+
media: {
|
|
173
|
+
manageAudioFocus: true,
|
|
174
|
+
audioMode: 'normal',
|
|
175
|
+
audioFocusMode: 'gain',
|
|
176
|
+
audioStreamType: 'music',
|
|
177
|
+
audioAttributesUsageType: 'media',
|
|
178
|
+
audioAttributesContentType: 'unknown',
|
|
179
|
+
},
|
|
180
|
+
} as const;
|
|
181
|
+
|
|
182
|
+
export type AppleAudioMode =
|
|
183
|
+
| 'default'
|
|
184
|
+
| 'gameChat'
|
|
185
|
+
| 'measurement'
|
|
186
|
+
| 'moviePlayback'
|
|
187
|
+
| 'spokenAudio'
|
|
188
|
+
| 'videoChat'
|
|
189
|
+
| 'videoRecording'
|
|
190
|
+
| 'voiceChat'
|
|
191
|
+
| 'voicePrompt';
|
|
192
|
+
|
|
193
|
+
export type AppleAudioCategory =
|
|
194
|
+
| 'soloAmbient'
|
|
195
|
+
| 'playback'
|
|
196
|
+
| 'record'
|
|
197
|
+
| 'playAndRecord'
|
|
198
|
+
| 'multiRoute';
|
|
199
|
+
|
|
200
|
+
export type AppleAudioCategoryOption =
|
|
201
|
+
| 'mixWithOthers'
|
|
202
|
+
| 'duckOthers'
|
|
203
|
+
| 'interruptSpokenAudioAndMixWithOthers'
|
|
204
|
+
| 'allowBluetooth'
|
|
205
|
+
| 'allowBluetoothA2DP'
|
|
206
|
+
| 'allowAirPlay'
|
|
207
|
+
| 'defaultToSpeaker';
|
|
208
|
+
|
|
209
|
+
export type AppleAudioConfiguration = {
|
|
210
|
+
audioCategory?: AppleAudioCategory;
|
|
211
|
+
audioCategoryOptions?: AppleAudioCategoryOption[];
|
|
212
|
+
audioMode?: AppleAudioMode;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export type AudioTrackState =
|
|
216
|
+
| 'none'
|
|
217
|
+
| 'remoteOnly'
|
|
218
|
+
| 'localOnly'
|
|
219
|
+
| 'localAndRemote';
|
|
220
|
+
|
|
221
|
+
export function getDefaultAppleAudioConfigurationForMode(
|
|
222
|
+
mode: AudioTrackState,
|
|
223
|
+
preferSpeakerOutput: boolean = true
|
|
224
|
+
): AppleAudioConfiguration {
|
|
225
|
+
if (mode === 'remoteOnly') {
|
|
226
|
+
return {
|
|
227
|
+
audioCategory: 'playback',
|
|
228
|
+
audioCategoryOptions: ['mixWithOthers'],
|
|
229
|
+
audioMode: 'spokenAudio',
|
|
230
|
+
};
|
|
231
|
+
} else if (mode === 'localAndRemote' || mode === 'localOnly') {
|
|
232
|
+
return {
|
|
233
|
+
audioCategory: 'playAndRecord',
|
|
234
|
+
audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],
|
|
235
|
+
audioMode: preferSpeakerOutput ? 'videoChat' : 'voiceChat',
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
audioCategory: 'soloAmbient',
|
|
241
|
+
audioCategoryOptions: [],
|
|
242
|
+
audioMode: 'default',
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
68
246
|
export default class AudioSession {
|
|
69
247
|
/**
|
|
70
248
|
* Applies the provided audio configuration to the underlying AudioSession.
|
|
@@ -100,9 +278,6 @@ export default class AudioSession {
|
|
|
100
278
|
* * "headset"
|
|
101
279
|
* * "bluetooth"
|
|
102
280
|
*
|
|
103
|
-
* Note: For applications targeting SDK versions over 30, the runtime BLUETOOTH_CONNECT
|
|
104
|
-
* permission must be requested to send audio to bluetooth headsets.
|
|
105
|
-
*
|
|
106
281
|
* ----
|
|
107
282
|
*
|
|
108
283
|
* For iOS, due to OS limitations, the only available types are:
|
|
@@ -147,4 +322,12 @@ export default class AudioSession {
|
|
|
147
322
|
await LivekitReactNative.showAudioRoutePicker();
|
|
148
323
|
}
|
|
149
324
|
};
|
|
325
|
+
|
|
326
|
+
static setAppleAudioConfiguration = async (
|
|
327
|
+
config: AppleAudioConfiguration
|
|
328
|
+
) => {
|
|
329
|
+
if (Platform.OS === 'ios') {
|
|
330
|
+
await LivekitReactNative.setAppleAudioConfiguration(config);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
150
333
|
}
|
package/src/index.tsx
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { registerGlobals as webrtcRegisterGlobals } from '@livekit/react-native-webrtc';
|
|
2
2
|
import { setupURLPolyfill } from 'react-native-url-polyfill';
|
|
3
|
-
import
|
|
3
|
+
import 'fastestsmallesttextencoderdecoder';
|
|
4
|
+
import AudioSession, {
|
|
5
|
+
AndroidAudioTypePresets,
|
|
6
|
+
AndroidAudioTypeOptions,
|
|
7
|
+
AppleAudioCategory,
|
|
8
|
+
AppleAudioCategoryOption,
|
|
9
|
+
AppleAudioConfiguration,
|
|
10
|
+
AppleAudioMode,
|
|
11
|
+
AudioTrackState,
|
|
12
|
+
getDefaultAppleAudioConfigurationForMode,
|
|
13
|
+
} from './audio/AudioSession';
|
|
4
14
|
import type { AudioConfiguration } from './audio/AudioSession';
|
|
5
15
|
import { PixelRatio, Platform } from 'react-native';
|
|
6
16
|
import type { LiveKitReactNativeInfo } from 'livekit-client';
|
|
17
|
+
import type { LogLevel, SetLogLevelOptions } from './logger';
|
|
7
18
|
|
|
8
19
|
/**
|
|
9
20
|
* Registers the required globals needed for LiveKit to work.
|
|
@@ -17,6 +28,8 @@ export function registerGlobals() {
|
|
|
17
28
|
fixWebrtcAdapter();
|
|
18
29
|
shimPromiseAllSettled();
|
|
19
30
|
shimArrayAt();
|
|
31
|
+
shimAsyncIterator();
|
|
32
|
+
shimIterator();
|
|
20
33
|
}
|
|
21
34
|
function livekitRegisterGlobals() {
|
|
22
35
|
let lkGlobal: LiveKitReactNativeInfo = {
|
|
@@ -52,7 +65,33 @@ function shimArrayAt() {
|
|
|
52
65
|
}
|
|
53
66
|
}
|
|
54
67
|
|
|
68
|
+
function shimAsyncIterator() {
|
|
69
|
+
var shim = require('well-known-symbols/Symbol.asyncIterator/shim');
|
|
70
|
+
shim();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function shimIterator() {
|
|
74
|
+
var shim = require('well-known-symbols/Symbol.iterator/shim');
|
|
75
|
+
shim();
|
|
76
|
+
}
|
|
77
|
+
|
|
55
78
|
export * from './components/VideoView';
|
|
56
79
|
export * from './useParticipant';
|
|
57
80
|
export * from './useRoom';
|
|
58
|
-
export
|
|
81
|
+
export * from './logger';
|
|
82
|
+
export * from './audio/AudioManager';
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
AudioSession,
|
|
86
|
+
AudioConfiguration,
|
|
87
|
+
AndroidAudioTypeOptions,
|
|
88
|
+
AndroidAudioTypePresets,
|
|
89
|
+
AppleAudioCategory,
|
|
90
|
+
AppleAudioCategoryOption,
|
|
91
|
+
AppleAudioConfiguration,
|
|
92
|
+
AppleAudioMode,
|
|
93
|
+
AudioTrackState,
|
|
94
|
+
getDefaultAppleAudioConfigurationForMode,
|
|
95
|
+
LogLevel,
|
|
96
|
+
SetLogLevelOptions,
|
|
97
|
+
};
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { setLogLevel as setClientSdkLogLevel } from 'livekit-client';
|
|
2
|
+
import loglevel from 'loglevel';
|
|
3
|
+
|
|
4
|
+
export const log = loglevel.getLogger('lk-react-native');
|
|
5
|
+
log.setDefaultLevel('WARN');
|
|
6
|
+
|
|
7
|
+
export type LogLevel = Parameters<typeof setClientSdkLogLevel>[0];
|
|
8
|
+
export type SetLogLevelOptions = {
|
|
9
|
+
liveKitClientLogLevel?: LogLevel;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Set the log level for both the `@livekit/react-native` package and the `@livekit-client` package.
|
|
14
|
+
* To set the `@livekit-client` log independently, use the `liveKitClientLogLevel` prop on the `options` object.
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export function setLogLevel(
|
|
18
|
+
level: LogLevel,
|
|
19
|
+
options: SetLogLevelOptions = {}
|
|
20
|
+
): void {
|
|
21
|
+
log.setLevel(level);
|
|
22
|
+
setClientSdkLogLevel(options.liveKitClientLogLevel ?? level);
|
|
23
|
+
}
|