@livekit/react-native 2.5.1 → 2.6.1
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 +4 -3
- package/android/build.gradle +2 -1
- package/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt +61 -5
- package/android/src/main/java/com/livekit/reactnative/LivekitReactNativeModule.kt +81 -4
- package/android/src/main/java/com/livekit/reactnative/audio/events/Events.kt +6 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/AudioFormat.kt +2 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/AudioProcessingController.kt +27 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/AudioProcessorInterface.kt +52 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/AudioRecordSamplesDispatcher.kt +72 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkManager.kt +75 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/CustomAudioProcessingFactory.kt +78 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/MultibandVolumeProcessor.kt +181 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/VolumeProcessor.kt +67 -0
- package/android/src/main/java/com/livekit/reactnative/audio/processing/fft/FFTAudioAnalyzer.kt +224 -0
- package/ios/AudioUtils.swift +49 -0
- package/ios/LKAudioProcessingAdapter.h +26 -0
- package/ios/LKAudioProcessingAdapter.m +117 -0
- package/ios/LKAudioProcessingManager.h +34 -0
- package/ios/LKAudioProcessingManager.m +63 -0
- package/ios/LiveKitReactNativeModule.swift +234 -0
- package/ios/LivekitReactNative-Bridging-Header.h +5 -2
- package/ios/LivekitReactNative.h +2 -6
- package/ios/LivekitReactNative.m +3 -166
- package/ios/LivekitReactNativeModule.m +42 -0
- package/ios/Logging.swift +4 -0
- package/ios/audio/AVAudioPCMBuffer.swift +136 -0
- package/ios/audio/AudioProcessing.swift +163 -0
- package/ios/audio/AudioRendererManager.swift +71 -0
- package/ios/audio/FFTProcessor.swift +147 -0
- package/ios/audio/MultibandVolumeAudioRenderer.swift +67 -0
- package/ios/audio/RingBuffer.swift +51 -0
- package/ios/audio/VolumeAudioRenderer.swift +50 -0
- package/lib/commonjs/LKNativeModule.js +18 -0
- package/lib/commonjs/LKNativeModule.js.map +1 -0
- package/lib/commonjs/audio/AudioSession.js +9 -17
- package/lib/commonjs/audio/AudioSession.js.map +1 -1
- package/lib/commonjs/components/BarVisualizer.js +192 -0
- package/lib/commonjs/components/BarVisualizer.js.map +1 -0
- package/lib/commonjs/events/EventEmitter.js +45 -0
- package/lib/commonjs/events/EventEmitter.js.map +1 -0
- package/lib/commonjs/hooks/useMultibandTrackVolume.js +64 -0
- package/lib/commonjs/hooks/useMultibandTrackVolume.js.map +1 -0
- package/lib/commonjs/hooks/useTrackVolume.js +45 -0
- package/lib/commonjs/hooks/useTrackVolume.js.map +1 -0
- package/lib/commonjs/hooks.js +24 -0
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/commonjs/index.js +14 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/LKNativeModule.js +12 -0
- package/lib/module/LKNativeModule.js.map +1 -0
- package/lib/module/audio/AudioSession.js +9 -17
- package/lib/module/audio/AudioSession.js.map +1 -1
- package/lib/module/components/BarVisualizer.js +182 -0
- package/lib/module/components/BarVisualizer.js.map +1 -0
- package/lib/module/events/EventEmitter.js +36 -0
- package/lib/module/events/EventEmitter.js.map +1 -0
- package/lib/module/hooks/useMultibandTrackVolume.js +58 -0
- package/lib/module/hooks/useMultibandTrackVolume.js.map +1 -0
- package/lib/module/hooks/useTrackVolume.js +39 -0
- package/lib/module/hooks/useTrackVolume.js.map +1 -0
- package/lib/module/hooks.js +2 -0
- package/lib/module/hooks.js.map +1 -1
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/lib/commonjs/LKNativeModule.d.ts +3 -0
- package/lib/typescript/lib/commonjs/components/BarVisualizer.d.ts +32 -0
- package/lib/typescript/lib/commonjs/events/EventEmitter.d.ts +4 -0
- package/lib/typescript/lib/commonjs/hooks/useMultibandTrackVolume.d.ts +8 -0
- package/lib/typescript/lib/commonjs/hooks/useTrackVolume.d.ts +8 -0
- package/lib/typescript/lib/module/LKNativeModule.d.ts +2 -0
- package/lib/typescript/lib/module/components/BarVisualizer.d.ts +10 -0
- package/lib/typescript/lib/module/events/EventEmitter.d.ts +3 -0
- package/lib/typescript/lib/module/hooks/useMultibandTrackVolume.d.ts +7 -0
- package/lib/typescript/lib/module/hooks/useTrackVolume.d.ts +7 -0
- package/lib/typescript/lib/module/hooks.d.ts +2 -0
- package/lib/typescript/lib/module/index.d.ts +1 -0
- package/lib/typescript/src/LKNativeModule.d.ts +2 -0
- package/lib/typescript/src/components/BarVisualizer.d.ts +49 -0
- package/lib/typescript/src/events/EventEmitter.d.ts +6 -0
- package/lib/typescript/src/hooks/useMultibandTrackVolume.d.ts +31 -0
- package/lib/typescript/src/hooks/useTrackVolume.d.ts +9 -0
- package/lib/typescript/src/hooks.d.ts +2 -0
- package/lib/typescript/src/index.d.ts +1 -0
- package/livekit-react-native.podspec +26 -6
- package/package.json +5 -5
- package/src/LKNativeModule.ts +19 -0
- package/src/audio/AudioSession.ts +9 -24
- package/src/components/BarVisualizer.tsx +252 -0
- package/src/events/EventEmitter.ts +51 -0
- package/src/hooks/useMultibandTrackVolume.ts +97 -0
- package/src/hooks/useTrackVolume.ts +62 -0
- package/src/hooks.ts +2 -0
- package/src/index.tsx +3 -0
- package/ios/AudioUtils.h +0 -9
- package/ios/AudioUtils.m +0 -48
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NativeModules, Platform } from 'react-native';
|
|
2
|
+
const LINKING_ERROR = `The package '@livekit/react-native' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
|
|
3
|
+
ios: "- You have run 'pod install'\n",
|
|
4
|
+
default: ''
|
|
5
|
+
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n';
|
|
6
|
+
const LiveKitModule = NativeModules.LivekitReactNativeModule ? NativeModules.LivekitReactNativeModule : new Proxy({}, {
|
|
7
|
+
get() {
|
|
8
|
+
throw new Error(LINKING_ERROR);
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
export default LiveKitModule;
|
|
12
|
+
//# sourceMappingURL=LKNativeModule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","LiveKitModule","LivekitReactNativeModule","Proxy","get","Error"],"sources":["LKNativeModule.ts"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\nconst LINKING_ERROR =\n `The package '@livekit/react-native' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\nconst LiveKitModule = NativeModules.LivekitReactNativeModule\n ? NativeModules.LivekitReactNativeModule\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\nexport default LiveKitModule;\n"],"mappings":"AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AACtD,MAAMC,aAAa,GACjB,gFAAgF,GAChFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,6CAA6C;AAE/C,MAAMC,aAAa,GAAGN,aAAa,CAACO,wBAAwB,GACxDP,aAAa,CAACO,wBAAwB,GACtC,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACR,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,eAAeI,aAAa","ignoreList":[]}
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
2
2
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
3
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
ios: "- You have run 'pod install'\n",
|
|
7
|
-
default: ''
|
|
8
|
-
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n';
|
|
9
|
-
const LivekitReactNative = NativeModules.LivekitReactNative ? NativeModules.LivekitReactNative : new Proxy({}, {
|
|
10
|
-
get() {
|
|
11
|
-
throw new Error(LINKING_ERROR);
|
|
12
|
-
}
|
|
13
|
-
});
|
|
4
|
+
import { Platform } from 'react-native';
|
|
5
|
+
import LiveKitModule from '../LKNativeModule';
|
|
14
6
|
|
|
15
7
|
/**
|
|
16
8
|
* Configuration for the underlying AudioSession.
|
|
@@ -87,19 +79,19 @@ export default class AudioSession {}
|
|
|
87
79
|
* See also useIOSAudioManagement for automatic configuration of iOS audio options.
|
|
88
80
|
*/
|
|
89
81
|
_defineProperty(AudioSession, "configureAudio", async config => {
|
|
90
|
-
await
|
|
82
|
+
await LiveKitModule.configureAudio(config);
|
|
91
83
|
});
|
|
92
84
|
/**
|
|
93
85
|
* Starts an AudioSession.
|
|
94
86
|
*/
|
|
95
87
|
_defineProperty(AudioSession, "startAudioSession", async () => {
|
|
96
|
-
await
|
|
88
|
+
await LiveKitModule.startAudioSession();
|
|
97
89
|
});
|
|
98
90
|
/**
|
|
99
91
|
* Stops the existing AudioSession.
|
|
100
92
|
*/
|
|
101
93
|
_defineProperty(AudioSession, "stopAudioSession", async () => {
|
|
102
|
-
await
|
|
94
|
+
await LiveKitModule.stopAudioSession();
|
|
103
95
|
});
|
|
104
96
|
/**
|
|
105
97
|
* Gets the available audio outputs for use with {@link selectAudioOutput}.
|
|
@@ -129,7 +121,7 @@ _defineProperty(AudioSession, "getAudioOutputs", async () => {
|
|
|
129
121
|
if (Platform.OS === 'ios') {
|
|
130
122
|
return ['default', 'force_speaker'];
|
|
131
123
|
} else if (Platform.OS === 'android') {
|
|
132
|
-
return await
|
|
124
|
+
return await LiveKitModule.getAudioOutputs();
|
|
133
125
|
} else {
|
|
134
126
|
return [];
|
|
135
127
|
}
|
|
@@ -142,7 +134,7 @@ _defineProperty(AudioSession, "getAudioOutputs", async () => {
|
|
|
142
134
|
* @param deviceId A deviceId retrieved from {@link getAudioOutputs}
|
|
143
135
|
*/
|
|
144
136
|
_defineProperty(AudioSession, "selectAudioOutput", async deviceId => {
|
|
145
|
-
await
|
|
137
|
+
await LiveKitModule.selectAudioOutput(deviceId);
|
|
146
138
|
});
|
|
147
139
|
/**
|
|
148
140
|
* iOS only, requires iOS 11+.
|
|
@@ -151,7 +143,7 @@ _defineProperty(AudioSession, "selectAudioOutput", async deviceId => {
|
|
|
151
143
|
*/
|
|
152
144
|
_defineProperty(AudioSession, "showAudioRoutePicker", async () => {
|
|
153
145
|
if (Platform.OS === 'ios') {
|
|
154
|
-
await
|
|
146
|
+
await LiveKitModule.showAudioRoutePicker();
|
|
155
147
|
}
|
|
156
148
|
});
|
|
157
149
|
/**
|
|
@@ -162,7 +154,7 @@ _defineProperty(AudioSession, "showAudioRoutePicker", async () => {
|
|
|
162
154
|
*/
|
|
163
155
|
_defineProperty(AudioSession, "setAppleAudioConfiguration", async config => {
|
|
164
156
|
if (Platform.OS === 'ios') {
|
|
165
|
-
await
|
|
157
|
+
await LiveKitModule.setAppleAudioConfiguration(config);
|
|
166
158
|
}
|
|
167
159
|
});
|
|
168
160
|
//# sourceMappingURL=AudioSession.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","LivekitReactNative","Proxy","get","Error","AndroidAudioTypePresets","communication","manageAudioFocus","audioMode","audioFocusMode","audioStreamType","audioAttributesUsageType","audioAttributesContentType","media","getDefaultAppleAudioConfigurationForMode","mode","preferSpeakerOutput","audioCategory","audioCategoryOptions","AudioSession","_defineProperty","config","configureAudio","startAudioSession","stopAudioSession","OS","getAudioOutputs","deviceId","selectAudioOutput","showAudioRoutePicker","setAppleAudioConfiguration"],"sources":["AudioSession.ts"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\nconst LINKING_ERROR =\n `The package '@livekit/react-native' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\nconst LivekitReactNative = NativeModules.LivekitReactNative\n ? NativeModules.LivekitReactNative\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\n/**\n * Configuration for the underlying AudioSession.\n *\n * ----\n * Android specific options:\n *\n * * preferredOutputList - The preferred order in which to automatically select an audio output.\n * This is ignored when an output is manually selected with {@link AudioSession.selectAudioOutput}.\n *\n * By default, the order is set to:\n * 1. `\"bluetooth\"\n * 2. `\"headset\"``\n * 3. `\"speaker\"`\n * 4. `\"earpiece\"`\n *\n * * audioTypeOptions - An {@link AndroidAudioTypeOptions} object which provides the\n * audio options to use on Android.\n *\n * See {@link AndroidAudioTypePresets} for pre-configured values.\n *\n * ----\n * iOS\n *\n * * defaultOutput - The default preferred output to use when a wired headset or bluetooth output is unavailable.\n *\n * By default, this is set to `\"speaker\"`\n */\nexport type AudioConfiguration = {\n android?: {\n preferredOutputList?: ('speaker' | 'earpiece' | 'headset' | 'bluetooth')[];\n audioTypeOptions: AndroidAudioTypeOptions;\n };\n ios?: {\n defaultOutput?: 'speaker' | 'earpiece';\n };\n};\n\nexport type AndroidAudioTypeOptions = {\n /**\n * Whether LiveKit should handle managing the audio focus or not.\n *\n * Defaults to true.\n */\n manageAudioFocus?: boolean;\n\n /**\n * Corresponds to {@link https://developer.android.com/reference/android/media/AudioManager#setMode(int)}\n *\n * Defaults to 'inCommunication'.\n */\n audioMode?:\n | 'normal'\n | 'callScreening'\n | 'inCall'\n | 'inCommunication'\n | 'ringtone';\n\n /**\n * Corresponds to the duration hint when requesting audio focus.\n *\n * Defaults to 'gain'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#AUDIOFOCUS_GAIN}\n */\n audioFocusMode?:\n | 'gain'\n | 'gainTransient'\n | 'gainTransientExclusive'\n | 'gainTransientMayDuck';\n\n /**\n * Corresponds to Android's AudioAttributes usage type.\n *\n * Defaults to 'voiceCommunication'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesUsageType?:\n | 'alarm'\n | 'assistanceAccessibility'\n | 'assistanceNavigationGuidance'\n | 'assistanceSonification'\n | 'assistant'\n | 'game'\n | 'media'\n | 'notification'\n | 'notificationEvent'\n | 'notificationRingtone'\n | 'unknown'\n | 'voiceCommunication'\n | 'voiceCommunicationSignalling';\n\n /**\n * Corresponds to Android's AndroidAttributes content type.\n *\n * Defaults to 'speech'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesContentType?:\n | 'movie'\n | 'music'\n | 'sonification'\n | 'speech'\n | 'unknown';\n\n /**\n * Corresponds to the stream type when requesting audio focus. Used on pre-O devices.\n *\n * Defaults to 'voiceCall'\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#STREAM_VOICE_CALL}\n */\n audioStreamType?:\n | 'accessibility'\n | 'alarm'\n | 'dtmf'\n | 'music'\n | 'notification'\n | 'ring'\n | 'system'\n | 'voiceCall';\n\n /**\n * On certain Android devices, audio routing does not function properly and\n * bluetooth microphones will not work unless audio mode is set to\n * `inCommunication` or `inCall`. Audio routing is turned off those cases.\n *\n * If this set to true, will attempt to do audio routing regardless of audio mode.\n *\n * Defaults to false.\n */\n forceHandleAudioRouting?: boolean;\n};\n\nexport const AndroidAudioTypePresets: {\n /**\n * A pre-configured AndroidAudioConfiguration for voice communication.\n */\n communication: AndroidAudioTypeOptions;\n /**\n * A pre-configured AndroidAudioConfiguration for media playback.\n */\n media: AndroidAudioTypeOptions;\n} = {\n communication: {\n manageAudioFocus: true,\n audioMode: 'inCommunication',\n audioFocusMode: 'gain',\n audioStreamType: 'voiceCall',\n audioAttributesUsageType: 'voiceCommunication',\n audioAttributesContentType: 'speech',\n },\n media: {\n manageAudioFocus: true,\n audioMode: 'normal',\n audioFocusMode: 'gain',\n audioStreamType: 'music',\n audioAttributesUsageType: 'media',\n audioAttributesContentType: 'unknown',\n },\n} as const;\n\nexport type AppleAudioMode =\n | 'default'\n | 'gameChat'\n | 'measurement'\n | 'moviePlayback'\n | 'spokenAudio'\n | 'videoChat'\n | 'videoRecording'\n | 'voiceChat'\n | 'voicePrompt';\n\nexport type AppleAudioCategory =\n | 'soloAmbient'\n | 'playback'\n | 'record'\n | 'playAndRecord'\n | 'multiRoute';\n\nexport type AppleAudioCategoryOption =\n | 'mixWithOthers'\n | 'duckOthers'\n | 'interruptSpokenAudioAndMixWithOthers'\n | 'allowBluetooth'\n | 'allowBluetoothA2DP'\n | 'allowAirPlay'\n | 'defaultToSpeaker';\n\nexport type AppleAudioConfiguration = {\n audioCategory?: AppleAudioCategory;\n audioCategoryOptions?: AppleAudioCategoryOption[];\n audioMode?: AppleAudioMode;\n};\n\nexport type AudioTrackState =\n | 'none'\n | 'remoteOnly'\n | 'localOnly'\n | 'localAndRemote';\n\nexport function getDefaultAppleAudioConfigurationForMode(\n mode: AudioTrackState,\n preferSpeakerOutput: boolean = true\n): AppleAudioConfiguration {\n if (mode === 'remoteOnly') {\n return {\n audioCategory: 'playback',\n audioCategoryOptions: ['mixWithOthers'],\n audioMode: 'spokenAudio',\n };\n } else if (mode === 'localAndRemote' || mode === 'localOnly') {\n return {\n audioCategory: 'playAndRecord',\n audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],\n audioMode: preferSpeakerOutput ? 'videoChat' : 'voiceChat',\n };\n }\n\n return {\n audioCategory: 'soloAmbient',\n audioCategoryOptions: [],\n audioMode: 'default',\n };\n}\n\nexport default class AudioSession {\n /**\n * Applies the provided audio configuration to the underlying AudioSession.\n *\n * Must be called prior to connecting to a Room for the configuration to apply correctly.\n *\n * See also useIOSAudioManagement for automatic configuration of iOS audio options.\n */\n static configureAudio = async (config: AudioConfiguration) => {\n await LivekitReactNative.configureAudio(config);\n };\n\n /**\n * Starts an AudioSession.\n */\n static startAudioSession = async () => {\n await LivekitReactNative.startAudioSession();\n };\n\n /**\n * Stops the existing AudioSession.\n */\n static stopAudioSession = async () => {\n await LivekitReactNative.stopAudioSession();\n };\n\n /**\n * Gets the available audio outputs for use with {@link selectAudioOutput}.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * For Android, will return if available:\n * * \"speaker\"\n * * \"earpiece\"\n * * \"headset\"\n * * \"bluetooth\"\n *\n * ----\n *\n * For iOS, due to OS limitations, the only available types are:\n * * \"default\" - Use default iOS audio routing\n * * \"force_speaker\" - Force audio output through speaker\n *\n * See also {@link showAudioRoutePicker} to display a route picker that\n * can choose between other audio devices (i.e. headset/bluetooth/airplay),\n * or use a library like `react-native-avroutepicker` for a native platform\n * control.\n *\n * @returns the available audio output types\n */\n static getAudioOutputs = async (): Promise<string[]> => {\n if (Platform.OS === 'ios') {\n return ['default', 'force_speaker'];\n } else if (Platform.OS === 'android') {\n return (await LivekitReactNative.getAudioOutputs()) as string[];\n } else {\n return [];\n }\n };\n\n /**\n * Select the provided audio output if available.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * @param deviceId A deviceId retrieved from {@link getAudioOutputs}\n */\n static selectAudioOutput = async (deviceId: string) => {\n await LivekitReactNative.selectAudioOutput(deviceId);\n };\n\n /**\n * iOS only, requires iOS 11+.\n *\n * Displays an AVRoutePickerView for the user to choose their audio output.\n */\n static showAudioRoutePicker = async () => {\n if (Platform.OS === 'ios') {\n await LivekitReactNative.showAudioRoutePicker();\n }\n };\n\n /**\n * Directly change the AVAudioSession category/mode.\n *\n * @param config The configuration to use. Null values will be omitted and the\n * existing values will be unchanged.\n */\n static setAppleAudioConfiguration = async (\n config: AppleAudioConfiguration\n ) => {\n if (Platform.OS === 'ios') {\n await LivekitReactNative.setAppleAudioConfiguration(config);\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["Platform","LiveKitModule","AndroidAudioTypePresets","communication","manageAudioFocus","audioMode","audioFocusMode","audioStreamType","audioAttributesUsageType","audioAttributesContentType","media","getDefaultAppleAudioConfigurationForMode","mode","preferSpeakerOutput","audioCategory","audioCategoryOptions","AudioSession","_defineProperty","config","configureAudio","startAudioSession","stopAudioSession","OS","getAudioOutputs","deviceId","selectAudioOutput","showAudioRoutePicker","setAppleAudioConfiguration"],"sources":["AudioSession.ts"],"sourcesContent":["import { Platform } from 'react-native';\nimport LiveKitModule from '../LKNativeModule';\n\n/**\n * Configuration for the underlying AudioSession.\n *\n * ----\n * Android specific options:\n *\n * * preferredOutputList - The preferred order in which to automatically select an audio output.\n * This is ignored when an output is manually selected with {@link AudioSession.selectAudioOutput}.\n *\n * By default, the order is set to:\n * 1. `\"bluetooth\"\n * 2. `\"headset\"``\n * 3. `\"speaker\"`\n * 4. `\"earpiece\"`\n *\n * * audioTypeOptions - An {@link AndroidAudioTypeOptions} object which provides the\n * audio options to use on Android.\n *\n * See {@link AndroidAudioTypePresets} for pre-configured values.\n *\n * ----\n * iOS\n *\n * * defaultOutput - The default preferred output to use when a wired headset or bluetooth output is unavailable.\n *\n * By default, this is set to `\"speaker\"`\n */\nexport type AudioConfiguration = {\n android?: {\n preferredOutputList?: ('speaker' | 'earpiece' | 'headset' | 'bluetooth')[];\n audioTypeOptions: AndroidAudioTypeOptions;\n };\n ios?: {\n defaultOutput?: 'speaker' | 'earpiece';\n };\n};\n\nexport type AndroidAudioTypeOptions = {\n /**\n * Whether LiveKit should handle managing the audio focus or not.\n *\n * Defaults to true.\n */\n manageAudioFocus?: boolean;\n\n /**\n * Corresponds to {@link https://developer.android.com/reference/android/media/AudioManager#setMode(int)}\n *\n * Defaults to 'inCommunication'.\n */\n audioMode?:\n | 'normal'\n | 'callScreening'\n | 'inCall'\n | 'inCommunication'\n | 'ringtone';\n\n /**\n * Corresponds to the duration hint when requesting audio focus.\n *\n * Defaults to 'gain'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#AUDIOFOCUS_GAIN}\n */\n audioFocusMode?:\n | 'gain'\n | 'gainTransient'\n | 'gainTransientExclusive'\n | 'gainTransientMayDuck';\n\n /**\n * Corresponds to Android's AudioAttributes usage type.\n *\n * Defaults to 'voiceCommunication'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesUsageType?:\n | 'alarm'\n | 'assistanceAccessibility'\n | 'assistanceNavigationGuidance'\n | 'assistanceSonification'\n | 'assistant'\n | 'game'\n | 'media'\n | 'notification'\n | 'notificationEvent'\n | 'notificationRingtone'\n | 'unknown'\n | 'voiceCommunication'\n | 'voiceCommunicationSignalling';\n\n /**\n * Corresponds to Android's AndroidAttributes content type.\n *\n * Defaults to 'speech'.\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioAttributes}\n */\n audioAttributesContentType?:\n | 'movie'\n | 'music'\n | 'sonification'\n | 'speech'\n | 'unknown';\n\n /**\n * Corresponds to the stream type when requesting audio focus. Used on pre-O devices.\n *\n * Defaults to 'voiceCall'\n *\n * See also {@link https://developer.android.com/reference/android/media/AudioManager#STREAM_VOICE_CALL}\n */\n audioStreamType?:\n | 'accessibility'\n | 'alarm'\n | 'dtmf'\n | 'music'\n | 'notification'\n | 'ring'\n | 'system'\n | 'voiceCall';\n\n /**\n * On certain Android devices, audio routing does not function properly and\n * bluetooth microphones will not work unless audio mode is set to\n * `inCommunication` or `inCall`. Audio routing is turned off those cases.\n *\n * If this set to true, will attempt to do audio routing regardless of audio mode.\n *\n * Defaults to false.\n */\n forceHandleAudioRouting?: boolean;\n};\n\nexport const AndroidAudioTypePresets: {\n /**\n * A pre-configured AndroidAudioConfiguration for voice communication.\n */\n communication: AndroidAudioTypeOptions;\n /**\n * A pre-configured AndroidAudioConfiguration for media playback.\n */\n media: AndroidAudioTypeOptions;\n} = {\n communication: {\n manageAudioFocus: true,\n audioMode: 'inCommunication',\n audioFocusMode: 'gain',\n audioStreamType: 'voiceCall',\n audioAttributesUsageType: 'voiceCommunication',\n audioAttributesContentType: 'speech',\n },\n media: {\n manageAudioFocus: true,\n audioMode: 'normal',\n audioFocusMode: 'gain',\n audioStreamType: 'music',\n audioAttributesUsageType: 'media',\n audioAttributesContentType: 'unknown',\n },\n} as const;\n\nexport type AppleAudioMode =\n | 'default'\n | 'gameChat'\n | 'measurement'\n | 'moviePlayback'\n | 'spokenAudio'\n | 'videoChat'\n | 'videoRecording'\n | 'voiceChat'\n | 'voicePrompt';\n\nexport type AppleAudioCategory =\n | 'soloAmbient'\n | 'playback'\n | 'record'\n | 'playAndRecord'\n | 'multiRoute';\n\nexport type AppleAudioCategoryOption =\n | 'mixWithOthers'\n | 'duckOthers'\n | 'interruptSpokenAudioAndMixWithOthers'\n | 'allowBluetooth'\n | 'allowBluetoothA2DP'\n | 'allowAirPlay'\n | 'defaultToSpeaker';\n\nexport type AppleAudioConfiguration = {\n audioCategory?: AppleAudioCategory;\n audioCategoryOptions?: AppleAudioCategoryOption[];\n audioMode?: AppleAudioMode;\n};\n\nexport type AudioTrackState =\n | 'none'\n | 'remoteOnly'\n | 'localOnly'\n | 'localAndRemote';\n\nexport function getDefaultAppleAudioConfigurationForMode(\n mode: AudioTrackState,\n preferSpeakerOutput: boolean = true\n): AppleAudioConfiguration {\n if (mode === 'remoteOnly') {\n return {\n audioCategory: 'playback',\n audioCategoryOptions: ['mixWithOthers'],\n audioMode: 'spokenAudio',\n };\n } else if (mode === 'localAndRemote' || mode === 'localOnly') {\n return {\n audioCategory: 'playAndRecord',\n audioCategoryOptions: ['allowBluetooth', 'mixWithOthers'],\n audioMode: preferSpeakerOutput ? 'videoChat' : 'voiceChat',\n };\n }\n\n return {\n audioCategory: 'soloAmbient',\n audioCategoryOptions: [],\n audioMode: 'default',\n };\n}\n\nexport default class AudioSession {\n /**\n * Applies the provided audio configuration to the underlying AudioSession.\n *\n * Must be called prior to connecting to a Room for the configuration to apply correctly.\n *\n * See also useIOSAudioManagement for automatic configuration of iOS audio options.\n */\n static configureAudio = async (config: AudioConfiguration) => {\n await LiveKitModule.configureAudio(config);\n };\n\n /**\n * Starts an AudioSession.\n */\n static startAudioSession = async () => {\n await LiveKitModule.startAudioSession();\n };\n\n /**\n * Stops the existing AudioSession.\n */\n static stopAudioSession = async () => {\n await LiveKitModule.stopAudioSession();\n };\n\n /**\n * Gets the available audio outputs for use with {@link selectAudioOutput}.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * For Android, will return if available:\n * * \"speaker\"\n * * \"earpiece\"\n * * \"headset\"\n * * \"bluetooth\"\n *\n * ----\n *\n * For iOS, due to OS limitations, the only available types are:\n * * \"default\" - Use default iOS audio routing\n * * \"force_speaker\" - Force audio output through speaker\n *\n * See also {@link showAudioRoutePicker} to display a route picker that\n * can choose between other audio devices (i.e. headset/bluetooth/airplay),\n * or use a library like `react-native-avroutepicker` for a native platform\n * control.\n *\n * @returns the available audio output types\n */\n static getAudioOutputs = async (): Promise<string[]> => {\n if (Platform.OS === 'ios') {\n return ['default', 'force_speaker'];\n } else if (Platform.OS === 'android') {\n return (await LiveKitModule.getAudioOutputs()) as string[];\n } else {\n return [];\n }\n };\n\n /**\n * Select the provided audio output if available.\n *\n * {@link startAudioSession} must be called prior to using this method.\n *\n * @param deviceId A deviceId retrieved from {@link getAudioOutputs}\n */\n static selectAudioOutput = async (deviceId: string) => {\n await LiveKitModule.selectAudioOutput(deviceId);\n };\n\n /**\n * iOS only, requires iOS 11+.\n *\n * Displays an AVRoutePickerView for the user to choose their audio output.\n */\n static showAudioRoutePicker = async () => {\n if (Platform.OS === 'ios') {\n await LiveKitModule.showAudioRoutePicker();\n }\n };\n\n /**\n * Directly change the AVAudioSession category/mode.\n *\n * @param config The configuration to use. Null values will be omitted and the\n * existing values will be unchanged.\n */\n static setAppleAudioConfiguration = async (\n config: AppleAudioConfiguration\n ) => {\n if (Platform.OS === 'ios') {\n await LiveKitModule.setAppleAudioConfiguration(config);\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { useMaybeTrackRefContext } from '@livekit/components-react';
|
|
2
|
+
import { Animated, StyleSheet, View } from 'react-native';
|
|
3
|
+
import { useMultibandTrackVolume } from '../hooks';
|
|
4
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
5
|
+
const defaultBarOptions = {
|
|
6
|
+
maxHeight: 1,
|
|
7
|
+
minHeight: 0.2,
|
|
8
|
+
barColor: '#888888',
|
|
9
|
+
barWidth: 24,
|
|
10
|
+
barBorderRadius: 12
|
|
11
|
+
};
|
|
12
|
+
const sequencerIntervals = new Map([['connecting', 2000], ['initializing', 2000], ['listening', 500], ['thinking', 150]]);
|
|
13
|
+
const getSequencerInterval = (state, barCount) => {
|
|
14
|
+
if (state === undefined) {
|
|
15
|
+
return 1000;
|
|
16
|
+
}
|
|
17
|
+
let interval = sequencerIntervals.get(state);
|
|
18
|
+
if (interval) {
|
|
19
|
+
switch (state) {
|
|
20
|
+
case 'connecting':
|
|
21
|
+
// case 'thinking':
|
|
22
|
+
interval /= barCount;
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return interval;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* @beta
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Visualizes audio signals from a TrackReference as bars.
|
|
36
|
+
* If the `state` prop is set, it automatically transitions between VoiceAssistant states.
|
|
37
|
+
* @beta
|
|
38
|
+
*
|
|
39
|
+
* @remarks For VoiceAssistant state transitions this component requires a voice assistant agent running with livekit-agents \>= 0.9.0
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* function SimpleVoiceAssistant() {
|
|
44
|
+
* const { state, audioTrack } = useVoiceAssistant();
|
|
45
|
+
* return (
|
|
46
|
+
* <BarVisualizer
|
|
47
|
+
* state={state}
|
|
48
|
+
* trackRef={audioTrack}
|
|
49
|
+
* />
|
|
50
|
+
* );
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export const BarVisualizer = ({
|
|
55
|
+
style = {},
|
|
56
|
+
state,
|
|
57
|
+
barCount = 5,
|
|
58
|
+
trackRef,
|
|
59
|
+
options
|
|
60
|
+
}) => {
|
|
61
|
+
let trackReference = useMaybeTrackRefContext();
|
|
62
|
+
if (trackRef) {
|
|
63
|
+
trackReference = trackRef;
|
|
64
|
+
}
|
|
65
|
+
const opacityAnimations = useRef([]).current;
|
|
66
|
+
let magnitudes = useMultibandTrackVolume(trackReference, {
|
|
67
|
+
bands: barCount
|
|
68
|
+
});
|
|
69
|
+
let opts = {
|
|
70
|
+
...defaultBarOptions,
|
|
71
|
+
...options
|
|
72
|
+
};
|
|
73
|
+
const highlightedIndices = useBarAnimator(state, barCount, getSequencerInterval(state, barCount) ?? 100);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
let animations = [];
|
|
76
|
+
for (let i = 0; i < barCount; i++) {
|
|
77
|
+
if (!opacityAnimations[i]) {
|
|
78
|
+
opacityAnimations[i] = new Animated.Value(0.3);
|
|
79
|
+
}
|
|
80
|
+
let targetOpacity = 0.3;
|
|
81
|
+
if (highlightedIndices.includes(i)) {
|
|
82
|
+
targetOpacity = 1;
|
|
83
|
+
}
|
|
84
|
+
animations.push(Animated.timing(opacityAnimations[i], {
|
|
85
|
+
toValue: targetOpacity,
|
|
86
|
+
duration: 250,
|
|
87
|
+
useNativeDriver: true
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
let parallel = Animated.parallel(animations);
|
|
91
|
+
parallel.start();
|
|
92
|
+
return () => {
|
|
93
|
+
parallel.stop();
|
|
94
|
+
};
|
|
95
|
+
}, [highlightedIndices, barCount, opacityAnimations]);
|
|
96
|
+
let bars = [];
|
|
97
|
+
magnitudes.forEach((value, index) => {
|
|
98
|
+
let coerced = Math.min(opts.maxHeight, Math.max(opts.minHeight, value));
|
|
99
|
+
let coercedPercent = Math.min(100, Math.max(0, coerced * 100 + 5));
|
|
100
|
+
let opacity = opacityAnimations[index] ?? new Animated.Value(0.3);
|
|
101
|
+
let barStyle = {
|
|
102
|
+
opacity: opacity,
|
|
103
|
+
backgroundColor: opts.barColor,
|
|
104
|
+
borderRadius: opts.barBorderRadius,
|
|
105
|
+
width: opts.barWidth
|
|
106
|
+
};
|
|
107
|
+
bars.push( /*#__PURE__*/React.createElement(Animated.View, {
|
|
108
|
+
key: index,
|
|
109
|
+
style: [{
|
|
110
|
+
height: `${coercedPercent}%`
|
|
111
|
+
}, barStyle, styles.volumeIndicator]
|
|
112
|
+
}));
|
|
113
|
+
});
|
|
114
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
115
|
+
style: {
|
|
116
|
+
...style,
|
|
117
|
+
...styles.container
|
|
118
|
+
}
|
|
119
|
+
}, bars);
|
|
120
|
+
};
|
|
121
|
+
const styles = StyleSheet.create({
|
|
122
|
+
container: {
|
|
123
|
+
flexDirection: 'row',
|
|
124
|
+
alignItems: 'center',
|
|
125
|
+
justifyContent: 'space-evenly'
|
|
126
|
+
},
|
|
127
|
+
volumeIndicator: {
|
|
128
|
+
borderRadius: 12
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
export const useBarAnimator = (state, columns, interval) => {
|
|
132
|
+
const [index, setIndex] = useState(0);
|
|
133
|
+
const [sequence, setSequence] = useState([[]]);
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
if (state === 'thinking') {
|
|
136
|
+
setSequence(generateListeningSequenceBar(columns));
|
|
137
|
+
} else if (state === 'connecting' || state === 'initializing') {
|
|
138
|
+
const seq = [...generateConnectingSequenceBar(columns)];
|
|
139
|
+
setSequence(seq);
|
|
140
|
+
} else if (state === 'listening') {
|
|
141
|
+
setSequence(generateListeningSequenceBar(columns));
|
|
142
|
+
} else if (state === undefined) {
|
|
143
|
+
// highlight everything
|
|
144
|
+
setSequence([new Array(columns).fill(0).map((_, idx) => idx)]);
|
|
145
|
+
} else {
|
|
146
|
+
setSequence([[]]);
|
|
147
|
+
}
|
|
148
|
+
setIndex(0);
|
|
149
|
+
}, [state, columns]);
|
|
150
|
+
const animationFrameId = useRef(null);
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
let startTime = performance.now();
|
|
153
|
+
const animate = time => {
|
|
154
|
+
const timeElapsed = time - startTime;
|
|
155
|
+
if (timeElapsed >= interval) {
|
|
156
|
+
setIndex(prev => prev + 1);
|
|
157
|
+
startTime = time;
|
|
158
|
+
}
|
|
159
|
+
animationFrameId.current = requestAnimationFrame(animate);
|
|
160
|
+
};
|
|
161
|
+
animationFrameId.current = requestAnimationFrame(animate);
|
|
162
|
+
return () => {
|
|
163
|
+
if (animationFrameId.current !== null) {
|
|
164
|
+
cancelAnimationFrame(animationFrameId.current);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}, [interval, columns, state, sequence.length]);
|
|
168
|
+
return sequence[index % sequence.length];
|
|
169
|
+
};
|
|
170
|
+
const generateListeningSequenceBar = columns => {
|
|
171
|
+
const center = Math.floor(columns / 2);
|
|
172
|
+
const noIndex = -1;
|
|
173
|
+
return [[center], [noIndex]];
|
|
174
|
+
};
|
|
175
|
+
const generateConnectingSequenceBar = columns => {
|
|
176
|
+
const seq = [[]];
|
|
177
|
+
for (let x = 0; x < columns; x++) {
|
|
178
|
+
seq.push([x, columns - 1 - x]);
|
|
179
|
+
}
|
|
180
|
+
return seq;
|
|
181
|
+
};
|
|
182
|
+
//# sourceMappingURL=BarVisualizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useMaybeTrackRefContext","Animated","StyleSheet","View","useMultibandTrackVolume","React","useEffect","useRef","useState","defaultBarOptions","maxHeight","minHeight","barColor","barWidth","barBorderRadius","sequencerIntervals","Map","getSequencerInterval","state","barCount","undefined","interval","get","BarVisualizer","style","trackRef","options","trackReference","opacityAnimations","current","magnitudes","bands","opts","highlightedIndices","useBarAnimator","animations","i","Value","targetOpacity","includes","push","timing","toValue","duration","useNativeDriver","parallel","start","stop","bars","forEach","value","index","coerced","Math","min","max","coercedPercent","opacity","barStyle","backgroundColor","borderRadius","width","createElement","key","height","styles","volumeIndicator","container","create","flexDirection","alignItems","justifyContent","columns","setIndex","sequence","setSequence","generateListeningSequenceBar","seq","generateConnectingSequenceBar","Array","fill","map","_","idx","animationFrameId","startTime","performance","now","animate","time","timeElapsed","prev","requestAnimationFrame","cancelAnimationFrame","length","center","floor","noIndex","x"],"sources":["BarVisualizer.tsx"],"sourcesContent":["import {\n type AgentState,\n type TrackReferenceOrPlaceholder,\n useMaybeTrackRefContext,\n} from '@livekit/components-react';\nimport {\n Animated,\n StyleSheet,\n View,\n type ColorValue,\n type DimensionValue,\n type ViewStyle,\n} from 'react-native';\nimport { useMultibandTrackVolume } from '../hooks';\nimport React, { useEffect, useRef, useState } from 'react';\nexport type BarVisualizerOptions = {\n /** decimal values from 0 to 1 */\n maxHeight?: number;\n /** decimal values from 0 to 1 */\n minHeight?: number;\n\n barColor?: ColorValue;\n barWidth?: DimensionValue;\n barBorderRadius?: number;\n};\n\nconst defaultBarOptions = {\n maxHeight: 1,\n minHeight: 0.2,\n barColor: '#888888',\n barWidth: 24,\n barBorderRadius: 12,\n} as const satisfies BarVisualizerOptions;\n\nconst sequencerIntervals = new Map<AgentState, number>([\n ['connecting', 2000],\n ['initializing', 2000],\n ['listening', 500],\n ['thinking', 150],\n]);\n\nconst getSequencerInterval = (\n state: AgentState | undefined,\n barCount: number\n): number | undefined => {\n if (state === undefined) {\n return 1000;\n }\n let interval = sequencerIntervals.get(state);\n if (interval) {\n switch (state) {\n case 'connecting':\n // case 'thinking':\n interval /= barCount;\n break;\n\n default:\n break;\n }\n }\n return interval;\n};\n/**\n * @beta\n */\nexport interface BarVisualizerProps {\n /** If set, the visualizer will transition between different voice assistant states */\n state?: AgentState;\n /** Number of bars that show up in the visualizer */\n barCount?: number;\n trackRef?: TrackReferenceOrPlaceholder;\n options?: BarVisualizerOptions;\n /**\n * Custom React Native styles for the container.\n */\n style?: ViewStyle;\n}\n\n/**\n * Visualizes audio signals from a TrackReference as bars.\n * If the `state` prop is set, it automatically transitions between VoiceAssistant states.\n * @beta\n *\n * @remarks For VoiceAssistant state transitions this component requires a voice assistant agent running with livekit-agents \\>= 0.9.0\n *\n * @example\n * ```tsx\n * function SimpleVoiceAssistant() {\n * const { state, audioTrack } = useVoiceAssistant();\n * return (\n * <BarVisualizer\n * state={state}\n * trackRef={audioTrack}\n * />\n * );\n * }\n * ```\n */\nexport const BarVisualizer = ({\n style = {},\n state,\n barCount = 5,\n trackRef,\n options,\n}: BarVisualizerProps) => {\n let trackReference = useMaybeTrackRefContext();\n\n if (trackRef) {\n trackReference = trackRef;\n }\n\n const opacityAnimations = useRef<Animated.Value[]>([]).current;\n let magnitudes = useMultibandTrackVolume(trackReference, { bands: barCount });\n\n let opts = { ...defaultBarOptions, ...options };\n\n const highlightedIndices = useBarAnimator(\n state,\n barCount,\n getSequencerInterval(state, barCount) ?? 100\n );\n\n useEffect(() => {\n let animations = [];\n for (let i = 0; i < barCount; i++) {\n if (!opacityAnimations[i]) {\n opacityAnimations[i] = new Animated.Value(0.3);\n }\n let targetOpacity = 0.3;\n if (highlightedIndices.includes(i)) {\n targetOpacity = 1;\n }\n animations.push(\n Animated.timing(opacityAnimations[i], {\n toValue: targetOpacity,\n duration: 250,\n useNativeDriver: true,\n })\n );\n }\n\n let parallel = Animated.parallel(animations);\n parallel.start();\n return () => {\n parallel.stop();\n };\n }, [highlightedIndices, barCount, opacityAnimations]);\n\n let bars: React.ReactNode[] = [];\n magnitudes.forEach((value, index) => {\n let coerced = Math.min(opts.maxHeight, Math.max(opts.minHeight, value));\n let coercedPercent = Math.min(100, Math.max(0, coerced * 100 + 5));\n let opacity = opacityAnimations[index] ?? new Animated.Value(0.3);\n let barStyle = {\n opacity: opacity,\n backgroundColor: opts.barColor,\n borderRadius: opts.barBorderRadius,\n width: opts.barWidth,\n };\n bars.push(\n <Animated.View\n key={index}\n style={[\n { height: `${coercedPercent}%` },\n barStyle,\n styles.volumeIndicator,\n ]}\n />\n );\n });\n\n return <View style={{ ...style, ...styles.container }}>{bars}</View>;\n};\nconst styles = StyleSheet.create({\n container: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-evenly',\n },\n volumeIndicator: {\n borderRadius: 12,\n },\n});\n\nexport const useBarAnimator = (\n state: AgentState | undefined,\n columns: number,\n interval: number\n): number[] => {\n const [index, setIndex] = useState(0);\n const [sequence, setSequence] = useState<number[][]>([[]]);\n\n useEffect(() => {\n if (state === 'thinking') {\n setSequence(generateListeningSequenceBar(columns));\n } else if (state === 'connecting' || state === 'initializing') {\n const seq = [...generateConnectingSequenceBar(columns)];\n setSequence(seq);\n } else if (state === 'listening') {\n setSequence(generateListeningSequenceBar(columns));\n } else if (state === undefined) {\n // highlight everything\n setSequence([new Array(columns).fill(0).map((_, idx) => idx)]);\n } else {\n setSequence([[]]);\n }\n setIndex(0);\n }, [state, columns]);\n\n const animationFrameId = useRef<number | null>(null);\n useEffect(() => {\n let startTime = performance.now();\n\n const animate = (time: number) => {\n const timeElapsed = time - startTime;\n\n if (timeElapsed >= interval) {\n setIndex((prev) => prev + 1);\n startTime = time;\n }\n\n animationFrameId.current = requestAnimationFrame(animate);\n };\n\n animationFrameId.current = requestAnimationFrame(animate);\n\n return () => {\n if (animationFrameId.current !== null) {\n cancelAnimationFrame(animationFrameId.current);\n }\n };\n }, [interval, columns, state, sequence.length]);\n\n return sequence[index % sequence.length];\n};\n\nconst generateListeningSequenceBar = (columns: number): number[][] => {\n const center = Math.floor(columns / 2);\n const noIndex = -1;\n\n return [[center], [noIndex]];\n};\n\nconst generateConnectingSequenceBar = (columns: number): number[][] => {\n const seq: number[][] = [[]];\n\n for (let x = 0; x < columns; x++) {\n seq.push([x, columns - 1 - x]);\n }\n\n return seq;\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { NativeEventEmitter } from 'react-native';
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
import EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';
|
|
4
|
+
import LiveKitModule from '../LKNativeModule';
|
|
5
|
+
|
|
6
|
+
// This emitter is going to be used to listen to all the native events (once) and then
|
|
7
|
+
// re-emit them on a JS-only emitter.
|
|
8
|
+
const nativeEmitter = new NativeEventEmitter(LiveKitModule);
|
|
9
|
+
const NATIVE_EVENTS = ['LK_VOLUME_PROCESSED', 'LK_MULTIBAND_PROCESSED'];
|
|
10
|
+
const eventEmitter = new EventEmitter();
|
|
11
|
+
export function setupNativeEvents() {
|
|
12
|
+
for (const eventName of NATIVE_EVENTS) {
|
|
13
|
+
nativeEmitter.addListener(eventName, (...args) => {
|
|
14
|
+
eventEmitter.emit(eventName, ...args);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const _subscriptions = new Map();
|
|
19
|
+
export function addListener(listener, eventName, eventHandler) {
|
|
20
|
+
var _subscriptions$get;
|
|
21
|
+
if (!NATIVE_EVENTS.includes(eventName)) {
|
|
22
|
+
throw new Error(`Invalid event: ${eventName}`);
|
|
23
|
+
}
|
|
24
|
+
if (!_subscriptions.has(listener)) {
|
|
25
|
+
_subscriptions.set(listener, []);
|
|
26
|
+
}
|
|
27
|
+
(_subscriptions$get = _subscriptions.get(listener)) === null || _subscriptions$get === void 0 || _subscriptions$get.push(eventEmitter.addListener(eventName, eventHandler));
|
|
28
|
+
}
|
|
29
|
+
export function removeListener(listener) {
|
|
30
|
+
var _subscriptions$get2;
|
|
31
|
+
(_subscriptions$get2 = _subscriptions.get(listener)) === null || _subscriptions$get2 === void 0 || _subscriptions$get2.forEach(sub => {
|
|
32
|
+
sub.remove();
|
|
33
|
+
});
|
|
34
|
+
_subscriptions.delete(listener);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=EventEmitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","EventEmitter","LiveKitModule","nativeEmitter","NATIVE_EVENTS","eventEmitter","setupNativeEvents","eventName","addListener","args","emit","_subscriptions","Map","listener","eventHandler","_subscriptions$get","includes","Error","has","set","get","push","removeListener","_subscriptions$get2","forEach","sub","remove","delete"],"sources":["EventEmitter.ts"],"sourcesContent":["import { NativeEventEmitter, type EmitterSubscription } from 'react-native';\n// @ts-ignore\nimport EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';\nimport LiveKitModule from '../LKNativeModule';\n\n// This emitter is going to be used to listen to all the native events (once) and then\n// re-emit them on a JS-only emitter.\nconst nativeEmitter = new NativeEventEmitter(LiveKitModule);\n\nconst NATIVE_EVENTS = ['LK_VOLUME_PROCESSED', 'LK_MULTIBAND_PROCESSED'];\n\nconst eventEmitter = new EventEmitter();\n\nexport function setupNativeEvents() {\n for (const eventName of NATIVE_EVENTS) {\n nativeEmitter.addListener(eventName, (...args) => {\n eventEmitter.emit(eventName, ...args);\n });\n }\n}\n\ntype EventHandler = (event: unknown) => void;\ntype Listener = unknown;\n\nconst _subscriptions: Map<Listener, EmitterSubscription[]> = new Map();\n\nexport function addListener(\n listener: Listener,\n eventName: string,\n eventHandler: EventHandler\n): void {\n if (!NATIVE_EVENTS.includes(eventName)) {\n throw new Error(`Invalid event: ${eventName}`);\n }\n\n if (!_subscriptions.has(listener)) {\n _subscriptions.set(listener, []);\n }\n\n _subscriptions\n .get(listener)\n ?.push(eventEmitter.addListener(eventName, eventHandler));\n}\n\nexport function removeListener(listener: Listener): void {\n _subscriptions.get(listener)?.forEach((sub) => {\n sub.remove();\n });\n\n _subscriptions.delete(listener);\n}\n"],"mappings":"AAAA,SAASA,kBAAkB,QAAkC,cAAc;AAC3E;AACA,OAAOC,YAAY,MAAM,oDAAoD;AAC7E,OAAOC,aAAa,MAAM,mBAAmB;;AAE7C;AACA;AACA,MAAMC,aAAa,GAAG,IAAIH,kBAAkB,CAACE,aAAa,CAAC;AAE3D,MAAME,aAAa,GAAG,CAAC,qBAAqB,EAAE,wBAAwB,CAAC;AAEvE,MAAMC,YAAY,GAAG,IAAIJ,YAAY,CAAC,CAAC;AAEvC,OAAO,SAASK,iBAAiBA,CAAA,EAAG;EAClC,KAAK,MAAMC,SAAS,IAAIH,aAAa,EAAE;IACrCD,aAAa,CAACK,WAAW,CAACD,SAAS,EAAE,CAAC,GAAGE,IAAI,KAAK;MAChDJ,YAAY,CAACK,IAAI,CAACH,SAAS,EAAE,GAAGE,IAAI,CAAC;IACvC,CAAC,CAAC;EACJ;AACF;AAKA,MAAME,cAAoD,GAAG,IAAIC,GAAG,CAAC,CAAC;AAEtE,OAAO,SAASJ,WAAWA,CACzBK,QAAkB,EAClBN,SAAiB,EACjBO,YAA0B,EACpB;EAAA,IAAAC,kBAAA;EACN,IAAI,CAACX,aAAa,CAACY,QAAQ,CAACT,SAAS,CAAC,EAAE;IACtC,MAAM,IAAIU,KAAK,CAAC,kBAAkBV,SAAS,EAAE,CAAC;EAChD;EAEA,IAAI,CAACI,cAAc,CAACO,GAAG,CAACL,QAAQ,CAAC,EAAE;IACjCF,cAAc,CAACQ,GAAG,CAACN,QAAQ,EAAE,EAAE,CAAC;EAClC;EAEA,CAAAE,kBAAA,GAAAJ,cAAc,CACXS,GAAG,CAACP,QAAQ,CAAC,cAAAE,kBAAA,eADhBA,kBAAA,CAEIM,IAAI,CAAChB,YAAY,CAACG,WAAW,CAACD,SAAS,EAAEO,YAAY,CAAC,CAAC;AAC7D;AAEA,OAAO,SAASQ,cAAcA,CAACT,QAAkB,EAAQ;EAAA,IAAAU,mBAAA;EACvD,CAAAA,mBAAA,GAAAZ,cAAc,CAACS,GAAG,CAACP,QAAQ,CAAC,cAAAU,mBAAA,eAA5BA,mBAAA,CAA8BC,OAAO,CAAEC,GAAG,IAAK;IAC7CA,GAAG,CAACC,MAAM,CAAC,CAAC;EACd,CAAC,CAAC;EAEFf,cAAc,CAACgB,MAAM,CAACd,QAAQ,CAAC;AACjC","ignoreList":[]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Track } from 'livekit-client';
|
|
2
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { addListener, removeListener } from '../events/EventEmitter';
|
|
4
|
+
import LiveKitModule from '../LKNativeModule';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Interface for configuring options for the useMultibandTrackVolume hook.
|
|
8
|
+
* @alpha
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const multibandDefaults = {
|
|
12
|
+
bands: 5,
|
|
13
|
+
minFrequency: 1000,
|
|
14
|
+
maxFrequency: 8000,
|
|
15
|
+
updateInterval: 40
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A hook for tracking the volume of an audio track across multiple frequency bands.
|
|
20
|
+
*
|
|
21
|
+
* @param trackOrTrackReference
|
|
22
|
+
* @returns A number array containing the volume for each frequency band.
|
|
23
|
+
*/
|
|
24
|
+
export function useMultibandTrackVolume(trackOrTrackReference, options = {}) {
|
|
25
|
+
var _trackOrTrackReferenc;
|
|
26
|
+
const track = trackOrTrackReference instanceof Track ? trackOrTrackReference : trackOrTrackReference === null || trackOrTrackReference === void 0 || (_trackOrTrackReferenc = trackOrTrackReference.publication) === null || _trackOrTrackReferenc === void 0 ? void 0 : _trackOrTrackReferenc.track;
|
|
27
|
+
const opts = useMemo(() => {
|
|
28
|
+
return {
|
|
29
|
+
...multibandDefaults,
|
|
30
|
+
...options
|
|
31
|
+
};
|
|
32
|
+
}, [options]);
|
|
33
|
+
const mediaStreamTrack = track === null || track === void 0 ? void 0 : track.mediaStreamTrack;
|
|
34
|
+
let [magnitudes, setMagnitudes] = useState([]);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
let listener = Object();
|
|
37
|
+
let reactTag = null;
|
|
38
|
+
if (mediaStreamTrack) {
|
|
39
|
+
reactTag = LiveKitModule.createMultibandVolumeProcessor(opts, mediaStreamTrack._peerConnectionId ?? -1, mediaStreamTrack.id);
|
|
40
|
+
addListener(listener, 'LK_MULTIBAND_PROCESSED', event => {
|
|
41
|
+
if (event.magnitudes && reactTag && event.id === reactTag) {
|
|
42
|
+
console.log('event received: ', event.magnitudes[0]);
|
|
43
|
+
setMagnitudes(event.magnitudes);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return () => {
|
|
48
|
+
if (mediaStreamTrack) {
|
|
49
|
+
removeListener(listener);
|
|
50
|
+
if (reactTag) {
|
|
51
|
+
LiveKitModule.deleteMultibandVolumeProcessor(reactTag, mediaStreamTrack._peerConnectionId ?? -1, mediaStreamTrack.id);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}, [mediaStreamTrack, opts]);
|
|
56
|
+
return magnitudes;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=useMultibandTrackVolume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Track","useEffect","useMemo","useState","addListener","removeListener","LiveKitModule","multibandDefaults","bands","minFrequency","maxFrequency","updateInterval","useMultibandTrackVolume","trackOrTrackReference","options","_trackOrTrackReferenc","track","publication","opts","mediaStreamTrack","magnitudes","setMagnitudes","listener","Object","reactTag","createMultibandVolumeProcessor","_peerConnectionId","id","event","console","log","deleteMultibandVolumeProcessor"],"sources":["useMultibandTrackVolume.ts"],"sourcesContent":["import { type TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport {\n Track,\n type LocalAudioTrack,\n type RemoteAudioTrack,\n} from 'livekit-client';\nimport { useEffect, useMemo, useState } from 'react';\nimport { addListener, removeListener } from '../events/EventEmitter';\nimport LiveKitModule from '../LKNativeModule';\n\n/**\n * Interface for configuring options for the useMultibandTrackVolume hook.\n * @alpha\n */\nexport interface MultiBandTrackVolumeOptions {\n /**\n * the number of bands to split the audio into\n */\n bands?: number;\n /**\n * cut off frequency on the lower end\n */\n minFrequency?: number;\n /**\n * cut off frequency on the higher end\n */\n maxFrequency?: number;\n /**\n * update should run every x ms\n */\n updateInterval?: number;\n}\n\nconst multibandDefaults = {\n bands: 5,\n minFrequency: 1000,\n maxFrequency: 8000,\n updateInterval: 40,\n} as const satisfies MultiBandTrackVolumeOptions;\n\n/**\n * A hook for tracking the volume of an audio track across multiple frequency bands.\n *\n * @param trackOrTrackReference\n * @returns A number array containing the volume for each frequency band.\n */\nexport function useMultibandTrackVolume(\n trackOrTrackReference?:\n | LocalAudioTrack\n | RemoteAudioTrack\n | TrackReferenceOrPlaceholder,\n options: MultiBandTrackVolumeOptions = {}\n) {\n const track =\n trackOrTrackReference instanceof Track\n ? trackOrTrackReference\n : <LocalAudioTrack | RemoteAudioTrack | undefined>(\n trackOrTrackReference?.publication?.track\n );\n const opts = useMemo(() => {\n return { ...multibandDefaults, ...options };\n }, [options]);\n const mediaStreamTrack = track?.mediaStreamTrack;\n\n let [magnitudes, setMagnitudes] = useState<number[]>([]);\n useEffect(() => {\n let listener = Object();\n let reactTag: string | null = null;\n if (mediaStreamTrack) {\n reactTag = LiveKitModule.createMultibandVolumeProcessor(\n opts,\n mediaStreamTrack._peerConnectionId ?? -1,\n mediaStreamTrack.id\n );\n addListener(listener, 'LK_MULTIBAND_PROCESSED', (event: any) => {\n if (event.magnitudes && reactTag && event.id === reactTag) {\n console.log('event received: ', event.magnitudes[0]);\n setMagnitudes(event.magnitudes);\n }\n });\n }\n return () => {\n if (mediaStreamTrack) {\n removeListener(listener);\n if (reactTag) {\n LiveKitModule.deleteMultibandVolumeProcessor(\n reactTag,\n mediaStreamTrack._peerConnectionId ?? -1,\n mediaStreamTrack.id\n );\n }\n }\n };\n }, [mediaStreamTrack, opts]);\n\n return magnitudes;\n}\n"],"mappings":"AACA,SACEA,KAAK,QAGA,gBAAgB;AACvB,SAASC,SAAS,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,OAAO;AACpD,SAASC,WAAW,EAAEC,cAAc,QAAQ,wBAAwB;AACpE,OAAOC,aAAa,MAAM,mBAAmB;;AAE7C;AACA;AACA;AACA;;AAoBA,MAAMC,iBAAiB,GAAG;EACxBC,KAAK,EAAE,CAAC;EACRC,YAAY,EAAE,IAAI;EAClBC,YAAY,EAAE,IAAI;EAClBC,cAAc,EAAE;AAClB,CAAgD;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,uBAAuBA,CACrCC,qBAG+B,EAC/BC,OAAoC,GAAG,CAAC,CAAC,EACzC;EAAA,IAAAC,qBAAA;EACA,MAAMC,KAAK,GACTH,qBAAqB,YAAYb,KAAK,GAClCa,qBAAqB,GAEnBA,qBAAqB,aAArBA,qBAAqB,gBAAAE,qBAAA,GAArBF,qBAAqB,CAAEI,WAAW,cAAAF,qBAAA,uBAAlCA,qBAAA,CAAoCC,KACrC;EACP,MAAME,IAAI,GAAGhB,OAAO,CAAC,MAAM;IACzB,OAAO;MAAE,GAAGK,iBAAiB;MAAE,GAAGO;IAAQ,CAAC;EAC7C,CAAC,EAAE,CAACA,OAAO,CAAC,CAAC;EACb,MAAMK,gBAAgB,GAAGH,KAAK,aAALA,KAAK,uBAALA,KAAK,CAAEG,gBAAgB;EAEhD,IAAI,CAACC,UAAU,EAAEC,aAAa,CAAC,GAAGlB,QAAQ,CAAW,EAAE,CAAC;EACxDF,SAAS,CAAC,MAAM;IACd,IAAIqB,QAAQ,GAAGC,MAAM,CAAC,CAAC;IACvB,IAAIC,QAAuB,GAAG,IAAI;IAClC,IAAIL,gBAAgB,EAAE;MACpBK,QAAQ,GAAGlB,aAAa,CAACmB,8BAA8B,CACrDP,IAAI,EACJC,gBAAgB,CAACO,iBAAiB,IAAI,CAAC,CAAC,EACxCP,gBAAgB,CAACQ,EACnB,CAAC;MACDvB,WAAW,CAACkB,QAAQ,EAAE,wBAAwB,EAAGM,KAAU,IAAK;QAC9D,IAAIA,KAAK,CAACR,UAAU,IAAII,QAAQ,IAAII,KAAK,CAACD,EAAE,KAAKH,QAAQ,EAAE;UACzDK,OAAO,CAACC,GAAG,CAAC,kBAAkB,EAAEF,KAAK,CAACR,UAAU,CAAC,CAAC,CAAC,CAAC;UACpDC,aAAa,CAACO,KAAK,CAACR,UAAU,CAAC;QACjC;MACF,CAAC,CAAC;IACJ;IACA,OAAO,MAAM;MACX,IAAID,gBAAgB,EAAE;QACpBd,cAAc,CAACiB,QAAQ,CAAC;QACxB,IAAIE,QAAQ,EAAE;UACZlB,aAAa,CAACyB,8BAA8B,CAC1CP,QAAQ,EACRL,gBAAgB,CAACO,iBAAiB,IAAI,CAAC,CAAC,EACxCP,gBAAgB,CAACQ,EACnB,CAAC;QACH;MACF;IACF,CAAC;EACH,CAAC,EAAE,CAACR,gBAAgB,EAAED,IAAI,CAAC,CAAC;EAE5B,OAAOE,UAAU;AACnB","ignoreList":[]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Track } from 'livekit-client';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { addListener, removeListener } from '../events/EventEmitter';
|
|
4
|
+
import LiveKitModule from '../LKNativeModule';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A hook for tracking the volume of an audio track.
|
|
8
|
+
*
|
|
9
|
+
* @param trackOrTrackReference
|
|
10
|
+
* @returns A number between 0-1 representing the volume.
|
|
11
|
+
*/
|
|
12
|
+
export function useTrackVolume(trackOrTrackReference) {
|
|
13
|
+
var _trackOrTrackReferenc;
|
|
14
|
+
const track = trackOrTrackReference instanceof Track ? trackOrTrackReference : trackOrTrackReference === null || trackOrTrackReference === void 0 || (_trackOrTrackReferenc = trackOrTrackReference.publication) === null || _trackOrTrackReferenc === void 0 ? void 0 : _trackOrTrackReferenc.track;
|
|
15
|
+
const mediaStreamTrack = track === null || track === void 0 ? void 0 : track.mediaStreamTrack;
|
|
16
|
+
let [volume, setVolume] = useState(0.0);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
let listener = Object();
|
|
19
|
+
let reactTag = null;
|
|
20
|
+
if (mediaStreamTrack) {
|
|
21
|
+
reactTag = LiveKitModule.createVolumeProcessor(mediaStreamTrack._peerConnectionId ?? -1, mediaStreamTrack.id);
|
|
22
|
+
addListener(listener, 'LK_VOLUME_PROCESSED', event => {
|
|
23
|
+
if (event.volume && reactTag && event.id === reactTag) {
|
|
24
|
+
setVolume(event.volume);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return () => {
|
|
29
|
+
if (mediaStreamTrack) {
|
|
30
|
+
removeListener(listener);
|
|
31
|
+
if (reactTag) {
|
|
32
|
+
LiveKitModule.deleteVolumeProcessor(reactTag, mediaStreamTrack._peerConnectionId ?? -1, mediaStreamTrack.id);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}, [mediaStreamTrack]);
|
|
37
|
+
return volume;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=useTrackVolume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Track","useEffect","useState","addListener","removeListener","LiveKitModule","useTrackVolume","trackOrTrackReference","_trackOrTrackReferenc","track","publication","mediaStreamTrack","volume","setVolume","listener","Object","reactTag","createVolumeProcessor","_peerConnectionId","id","event","deleteVolumeProcessor"],"sources":["useTrackVolume.ts"],"sourcesContent":["import { type TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport {\n Track,\n type LocalAudioTrack,\n type RemoteAudioTrack,\n} from 'livekit-client';\nimport { useEffect, useState } from 'react';\nimport { addListener, removeListener } from '../events/EventEmitter';\nimport LiveKitModule from '../LKNativeModule';\n\n/**\n * A hook for tracking the volume of an audio track.\n *\n * @param trackOrTrackReference\n * @returns A number between 0-1 representing the volume.\n */\nexport function useTrackVolume(\n trackOrTrackReference?:\n | LocalAudioTrack\n | RemoteAudioTrack\n | TrackReferenceOrPlaceholder\n) {\n const track =\n trackOrTrackReference instanceof Track\n ? trackOrTrackReference\n : <LocalAudioTrack | RemoteAudioTrack | undefined>(\n trackOrTrackReference?.publication?.track\n );\n\n const mediaStreamTrack = track?.mediaStreamTrack;\n\n let [volume, setVolume] = useState(0.0);\n useEffect(() => {\n let listener = Object();\n let reactTag: string | null = null;\n if (mediaStreamTrack) {\n reactTag = LiveKitModule.createVolumeProcessor(\n mediaStreamTrack._peerConnectionId ?? -1,\n mediaStreamTrack.id\n );\n addListener(listener, 'LK_VOLUME_PROCESSED', (event: any) => {\n if (event.volume && reactTag && event.id === reactTag) {\n setVolume(event.volume);\n }\n });\n }\n return () => {\n if (mediaStreamTrack) {\n removeListener(listener);\n if (reactTag) {\n LiveKitModule.deleteVolumeProcessor(\n reactTag,\n mediaStreamTrack._peerConnectionId ?? -1,\n mediaStreamTrack.id\n );\n }\n }\n };\n }, [mediaStreamTrack]);\n\n return volume;\n}\n"],"mappings":"AACA,SACEA,KAAK,QAGA,gBAAgB;AACvB,SAASC,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAC3C,SAASC,WAAW,EAAEC,cAAc,QAAQ,wBAAwB;AACpE,OAAOC,aAAa,MAAM,mBAAmB;;AAE7C;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAC5BC,qBAG+B,EAC/B;EAAA,IAAAC,qBAAA;EACA,MAAMC,KAAK,GACTF,qBAAqB,YAAYP,KAAK,GAClCO,qBAAqB,GAEnBA,qBAAqB,aAArBA,qBAAqB,gBAAAC,qBAAA,GAArBD,qBAAqB,CAAEG,WAAW,cAAAF,qBAAA,uBAAlCA,qBAAA,CAAoCC,KACrC;EAEP,MAAME,gBAAgB,GAAGF,KAAK,aAALA,KAAK,uBAALA,KAAK,CAAEE,gBAAgB;EAEhD,IAAI,CAACC,MAAM,EAAEC,SAAS,CAAC,GAAGX,QAAQ,CAAC,GAAG,CAAC;EACvCD,SAAS,CAAC,MAAM;IACd,IAAIa,QAAQ,GAAGC,MAAM,CAAC,CAAC;IACvB,IAAIC,QAAuB,GAAG,IAAI;IAClC,IAAIL,gBAAgB,EAAE;MACpBK,QAAQ,GAAGX,aAAa,CAACY,qBAAqB,CAC5CN,gBAAgB,CAACO,iBAAiB,IAAI,CAAC,CAAC,EACxCP,gBAAgB,CAACQ,EACnB,CAAC;MACDhB,WAAW,CAACW,QAAQ,EAAE,qBAAqB,EAAGM,KAAU,IAAK;QAC3D,IAAIA,KAAK,CAACR,MAAM,IAAII,QAAQ,IAAII,KAAK,CAACD,EAAE,KAAKH,QAAQ,EAAE;UACrDH,SAAS,CAACO,KAAK,CAACR,MAAM,CAAC;QACzB;MACF,CAAC,CAAC;IACJ;IACA,OAAO,MAAM;MACX,IAAID,gBAAgB,EAAE;QACpBP,cAAc,CAACU,QAAQ,CAAC;QACxB,IAAIE,QAAQ,EAAE;UACZX,aAAa,CAACgB,qBAAqB,CACjCL,QAAQ,EACRL,gBAAgB,CAACO,iBAAiB,IAAI,CAAC,CAAC,EACxCP,gBAAgB,CAACQ,EACnB,CAAC;QACH;MACF;IACF,CAAC;EACH,CAAC,EAAE,CAACR,gBAAgB,CAAC,CAAC;EAEtB,OAAOC,MAAM;AACf","ignoreList":[]}
|
package/lib/module/hooks.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { useConnectionState, useDataChannel, useIsSpeaking, useLocalParticipant, useLocalParticipantPermissions, useParticipantInfo, useParticipants, useRemoteParticipants, useRemoteParticipant, useSpeakingParticipants, useSortedParticipants, useChat, useIsEncrypted, useRoomInfo, useIsMuted, useParticipantTracks, useLiveKitRoom, RoomContext, useRoomContext, ParticipantContext, useParticipantContext, TrackRefContext, useTrackRefContext, useTracks, isTrackReference, useEnsureTrackRef, useTrackMutedIndicator, useVisualStableUpdate } from '@livekit/components-react';
|
|
2
2
|
export * from './hooks/useE2EEManager';
|
|
3
|
+
export * from './hooks/useTrackVolume';
|
|
4
|
+
export * from './hooks/useMultibandTrackVolume';
|
|
3
5
|
//# sourceMappingURL=hooks.js.map
|
package/lib/module/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useConnectionState","useDataChannel","useIsSpeaking","useLocalParticipant","useLocalParticipantPermissions","useParticipantInfo","useParticipants","useRemoteParticipants","useRemoteParticipant","useSpeakingParticipants","useSortedParticipants","useChat","useIsEncrypted","useRoomInfo","useIsMuted","useParticipantTracks","useLiveKitRoom","RoomContext","useRoomContext","ParticipantContext","useParticipantContext","TrackRefContext","useTrackRefContext","useTracks","isTrackReference","useEnsureTrackRef","useTrackMutedIndicator","useVisualStableUpdate"],"sources":["hooks.ts"],"sourcesContent":["export {\n useConnectionState,\n useDataChannel,\n useIsSpeaking,\n useLocalParticipant,\n useLocalParticipantPermissions,\n useParticipantInfo,\n useParticipants,\n useRemoteParticipants,\n useRemoteParticipant,\n useSpeakingParticipants,\n useSortedParticipants,\n useChat,\n useIsEncrypted,\n useRoomInfo,\n useIsMuted,\n useParticipantTracks,\n useLiveKitRoom,\n RoomContext,\n useRoomContext,\n ParticipantContext,\n useParticipantContext,\n TrackRefContext,\n useTrackRefContext,\n useTracks,\n isTrackReference,\n useEnsureTrackRef,\n useTrackMutedIndicator,\n useVisualStableUpdate,\n} from '@livekit/components-react';\nexport type {\n UseLocalParticipantOptions,\n UseParticipantInfoOptions,\n UseParticipantsOptions,\n UseRemoteParticipantOptions,\n UseRemoteParticipantsOptions,\n UseTracksOptions,\n TrackReference,\n TrackReferenceOrPlaceholder,\n UseVisualStableUpdateOptions,\n} from '@livekit/components-react';\n\nexport type { ReceivedDataMessage } from '@livekit/components-core';\nexport * from './hooks/useE2EEManager';\nexport type { UseRNE2EEManagerOptions } from './hooks/useE2EEManager';\n"],"mappings":"AAAA,SACEA,kBAAkB,EAClBC,cAAc,EACdC,aAAa,EACbC,mBAAmB,EACnBC,8BAA8B,EAC9BC,kBAAkB,EAClBC,eAAe,EACfC,qBAAqB,EACrBC,oBAAoB,EACpBC,uBAAuB,EACvBC,qBAAqB,EACrBC,OAAO,EACPC,cAAc,EACdC,WAAW,EACXC,UAAU,EACVC,oBAAoB,EACpBC,cAAc,EACdC,WAAW,EACXC,cAAc,EACdC,kBAAkB,EAClBC,qBAAqB,EACrBC,eAAe,EACfC,kBAAkB,EAClBC,SAAS,EACTC,gBAAgB,EAChBC,iBAAiB,EACjBC,sBAAsB,EACtBC,qBAAqB,QAChB,2BAA2B;AAclC,cAAc,wBAAwB","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["useConnectionState","useDataChannel","useIsSpeaking","useLocalParticipant","useLocalParticipantPermissions","useParticipantInfo","useParticipants","useRemoteParticipants","useRemoteParticipant","useSpeakingParticipants","useSortedParticipants","useChat","useIsEncrypted","useRoomInfo","useIsMuted","useParticipantTracks","useLiveKitRoom","RoomContext","useRoomContext","ParticipantContext","useParticipantContext","TrackRefContext","useTrackRefContext","useTracks","isTrackReference","useEnsureTrackRef","useTrackMutedIndicator","useVisualStableUpdate"],"sources":["hooks.ts"],"sourcesContent":["export {\n useConnectionState,\n useDataChannel,\n useIsSpeaking,\n useLocalParticipant,\n useLocalParticipantPermissions,\n useParticipantInfo,\n useParticipants,\n useRemoteParticipants,\n useRemoteParticipant,\n useSpeakingParticipants,\n useSortedParticipants,\n useChat,\n useIsEncrypted,\n useRoomInfo,\n useIsMuted,\n useParticipantTracks,\n useLiveKitRoom,\n RoomContext,\n useRoomContext,\n ParticipantContext,\n useParticipantContext,\n TrackRefContext,\n useTrackRefContext,\n useTracks,\n isTrackReference,\n useEnsureTrackRef,\n useTrackMutedIndicator,\n useVisualStableUpdate,\n} from '@livekit/components-react';\nexport type {\n UseLocalParticipantOptions,\n UseParticipantInfoOptions,\n UseParticipantsOptions,\n UseRemoteParticipantOptions,\n UseRemoteParticipantsOptions,\n UseTracksOptions,\n TrackReference,\n TrackReferenceOrPlaceholder,\n UseVisualStableUpdateOptions,\n} from '@livekit/components-react';\n\nexport type { ReceivedDataMessage } from '@livekit/components-core';\nexport * from './hooks/useE2EEManager';\nexport * from './hooks/useTrackVolume';\nexport * from './hooks/useMultibandTrackVolume';\nexport type { UseRNE2EEManagerOptions } from './hooks/useE2EEManager';\n"],"mappings":"AAAA,SACEA,kBAAkB,EAClBC,cAAc,EACdC,aAAa,EACbC,mBAAmB,EACnBC,8BAA8B,EAC9BC,kBAAkB,EAClBC,eAAe,EACfC,qBAAqB,EACrBC,oBAAoB,EACpBC,uBAAuB,EACvBC,qBAAqB,EACrBC,OAAO,EACPC,cAAc,EACdC,WAAW,EACXC,UAAU,EACVC,oBAAoB,EACpBC,cAAc,EACdC,WAAW,EACXC,cAAc,EACdC,kBAAkB,EAClBC,qBAAqB,EACrBC,eAAe,EACfC,kBAAkB,EAClBC,SAAS,EACTC,gBAAgB,EAChBC,iBAAiB,EACjBC,sBAAsB,EACtBC,qBAAqB,QAChB,2BAA2B;AAclC,cAAc,wBAAwB;AACtC,cAAc,wBAAwB;AACtC,cAAc,iCAAiC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import AudioSession, { AndroidAudioTypePresets, getDefaultAppleAudioConfiguratio
|
|
|
5
5
|
import { PixelRatio, Platform } from 'react-native';
|
|
6
6
|
import RNE2EEManager from './e2ee/RNE2EEManager';
|
|
7
7
|
import RNKeyProvider from './e2ee/RNKeyProvider';
|
|
8
|
+
import { setupNativeEvents } from './events/EventEmitter';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Registers the required globals needed for LiveKit to work.
|
|
@@ -21,6 +22,7 @@ export function registerGlobals() {
|
|
|
21
22
|
shimArrayAt();
|
|
22
23
|
shimAsyncIterator();
|
|
23
24
|
shimIterator();
|
|
25
|
+
setupNativeEvents();
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
/**
|
|
@@ -83,6 +85,7 @@ function shimIterator() {
|
|
|
83
85
|
shim();
|
|
84
86
|
}
|
|
85
87
|
export * from './hooks';
|
|
88
|
+
export * from './components/BarVisualizer';
|
|
86
89
|
export * from './components/LiveKitRoom';
|
|
87
90
|
export * from './components/VideoTrack';
|
|
88
91
|
export * from './components/VideoView'; // deprecated
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["registerGlobals","webrtcRegisterGlobals","setupURLPolyfill","AudioSession","AndroidAudioTypePresets","getDefaultAppleAudioConfigurationForMode","PixelRatio","Platform","RNE2EEManager","RNKeyProvider","iosCategoryEnforce","livekitRegisterGlobals","fixWebrtcAdapter","shimPromiseAllSettled","shimArrayAt","shimAsyncIterator","shimIterator","OS","getUserMediaFunc","global","navigator","mediaDevices","getUserMedia","constraints","audio","setAppleAudioConfiguration","audioCategory","lkGlobal","platform","devicePixelRatio","get","LiveKitReactNativeGlobal","_window","window","undefined","userAgent","product","allSettled","require","shim","Array","prototype","at"],"sources":["index.tsx"],"sourcesContent":["import { registerGlobals as webrtcRegisterGlobals } from '@livekit/react-native-webrtc';\nimport { setupURLPolyfill } from 'react-native-url-polyfill';\nimport './polyfills/EncoderDecoderTogether.min.js';\nimport AudioSession, {\n AndroidAudioTypePresets,\n type AndroidAudioTypeOptions,\n type AppleAudioCategory,\n type AppleAudioCategoryOption,\n type AppleAudioConfiguration,\n type AppleAudioMode,\n type AudioTrackState,\n getDefaultAppleAudioConfigurationForMode,\n} from './audio/AudioSession';\nimport type { AudioConfiguration } from './audio/AudioSession';\nimport { PixelRatio, Platform } from 'react-native';\nimport { type LiveKitReactNativeInfo } from 'livekit-client';\nimport type { LogLevel, SetLogLevelOptions } from './logger';\nimport RNE2EEManager from './e2ee/RNE2EEManager';\nimport RNKeyProvider, { type RNKeyProviderOptions } from './e2ee/RNKeyProvider';\n\n/**\n * Registers the required globals needed for LiveKit to work.\n *\n * Must be called before using LiveKit.\n */\nexport function registerGlobals() {\n webrtcRegisterGlobals();\n iosCategoryEnforce();\n livekitRegisterGlobals();\n setupURLPolyfill();\n fixWebrtcAdapter();\n shimPromiseAllSettled();\n shimArrayAt();\n shimAsyncIterator();\n shimIterator();\n}\n\n/**\n * Enforces changing to playAndRecord category prior to obtaining microphone.\n */\nfunction iosCategoryEnforce() {\n if (Platform.OS === 'ios') {\n // @ts-ignore\n let getUserMediaFunc = global.navigator.mediaDevices.getUserMedia;\n // @ts-ignore\n global.navigator.mediaDevices.getUserMedia = async (constraints: any) => {\n if (constraints.audio) {\n await AudioSession.setAppleAudioConfiguration({\n audioCategory: 'playAndRecord',\n });\n }\n\n return await getUserMediaFunc(constraints);\n };\n }\n}\n\nfunction livekitRegisterGlobals() {\n let lkGlobal: LiveKitReactNativeInfo = {\n platform: Platform.OS,\n devicePixelRatio: PixelRatio.get(),\n };\n\n // @ts-ignore\n global.LiveKitReactNativeGlobal = lkGlobal;\n}\n\nfunction fixWebrtcAdapter() {\n // @ts-ignore\n if (window?.navigator !== undefined) {\n // @ts-ignore\n const { navigator } = window;\n if (navigator.userAgent === undefined) {\n navigator.userAgent = navigator.product ?? 'Unknown';\n }\n }\n}\n\nfunction shimPromiseAllSettled() {\n var allSettled = require('promise.allsettled');\n allSettled.shim();\n}\n\nfunction shimArrayAt() {\n // Some versions of RN don't have Array.prototype.at, which is used by sdp-transform\n if (!Array.prototype.at) {\n var at = require('array.prototype.at');\n at.shim();\n }\n}\n\nfunction shimAsyncIterator() {\n var shim = require('well-known-symbols/Symbol.asyncIterator/shim');\n shim();\n}\n\nfunction shimIterator() {\n var shim = require('well-known-symbols/Symbol.iterator/shim');\n shim();\n}\nexport * from './hooks';\nexport * from './components/LiveKitRoom';\nexport * from './components/VideoTrack';\nexport * from './components/VideoView'; // deprecated\nexport * from './useParticipant'; // deprecated\nexport * from './useRoom'; // deprecated\nexport * from './logger';\nexport * from './audio/AudioManager';\n\nexport {\n AudioSession,\n RNE2EEManager,\n RNKeyProvider,\n AndroidAudioTypePresets,\n getDefaultAppleAudioConfigurationForMode,\n};\nexport type {\n AudioConfiguration,\n AndroidAudioTypeOptions,\n AppleAudioCategory,\n AppleAudioCategoryOption,\n AppleAudioConfiguration,\n AppleAudioMode,\n AudioTrackState,\n LogLevel,\n SetLogLevelOptions,\n RNKeyProviderOptions,\n};\n"],"mappings":"AAAA,SAASA,eAAe,IAAIC,qBAAqB,QAAQ,8BAA8B;AACvF,SAASC,gBAAgB,QAAQ,2BAA2B;AAC5D,OAAO,2CAA2C;AAClD,OAAOC,YAAY,IACjBC,uBAAuB,EAOvBC,wCAAwC,QACnC,sBAAsB;AAE7B,SAASC,UAAU,EAAEC,QAAQ,QAAQ,cAAc;AAGnD,OAAOC,aAAa,MAAM,sBAAsB;AAChD,OAAOC,aAAa,MAAqC,sBAAsB
|
|
1
|
+
{"version":3,"names":["registerGlobals","webrtcRegisterGlobals","setupURLPolyfill","AudioSession","AndroidAudioTypePresets","getDefaultAppleAudioConfigurationForMode","PixelRatio","Platform","RNE2EEManager","RNKeyProvider","setupNativeEvents","iosCategoryEnforce","livekitRegisterGlobals","fixWebrtcAdapter","shimPromiseAllSettled","shimArrayAt","shimAsyncIterator","shimIterator","OS","getUserMediaFunc","global","navigator","mediaDevices","getUserMedia","constraints","audio","setAppleAudioConfiguration","audioCategory","lkGlobal","platform","devicePixelRatio","get","LiveKitReactNativeGlobal","_window","window","undefined","userAgent","product","allSettled","require","shim","Array","prototype","at"],"sources":["index.tsx"],"sourcesContent":["import { registerGlobals as webrtcRegisterGlobals } from '@livekit/react-native-webrtc';\nimport { setupURLPolyfill } from 'react-native-url-polyfill';\nimport './polyfills/EncoderDecoderTogether.min.js';\nimport AudioSession, {\n AndroidAudioTypePresets,\n type AndroidAudioTypeOptions,\n type AppleAudioCategory,\n type AppleAudioCategoryOption,\n type AppleAudioConfiguration,\n type AppleAudioMode,\n type AudioTrackState,\n getDefaultAppleAudioConfigurationForMode,\n} from './audio/AudioSession';\nimport type { AudioConfiguration } from './audio/AudioSession';\nimport { PixelRatio, Platform } from 'react-native';\nimport { type LiveKitReactNativeInfo } from 'livekit-client';\nimport type { LogLevel, SetLogLevelOptions } from './logger';\nimport RNE2EEManager from './e2ee/RNE2EEManager';\nimport RNKeyProvider, { type RNKeyProviderOptions } from './e2ee/RNKeyProvider';\nimport { setupNativeEvents } from './events/EventEmitter';\n\n/**\n * Registers the required globals needed for LiveKit to work.\n *\n * Must be called before using LiveKit.\n */\nexport function registerGlobals() {\n webrtcRegisterGlobals();\n iosCategoryEnforce();\n livekitRegisterGlobals();\n setupURLPolyfill();\n fixWebrtcAdapter();\n shimPromiseAllSettled();\n shimArrayAt();\n shimAsyncIterator();\n shimIterator();\n setupNativeEvents();\n}\n\n/**\n * Enforces changing to playAndRecord category prior to obtaining microphone.\n */\nfunction iosCategoryEnforce() {\n if (Platform.OS === 'ios') {\n // @ts-ignore\n let getUserMediaFunc = global.navigator.mediaDevices.getUserMedia;\n // @ts-ignore\n global.navigator.mediaDevices.getUserMedia = async (constraints: any) => {\n if (constraints.audio) {\n await AudioSession.setAppleAudioConfiguration({\n audioCategory: 'playAndRecord',\n });\n }\n\n return await getUserMediaFunc(constraints);\n };\n }\n}\n\nfunction livekitRegisterGlobals() {\n let lkGlobal: LiveKitReactNativeInfo = {\n platform: Platform.OS,\n devicePixelRatio: PixelRatio.get(),\n };\n\n // @ts-ignore\n global.LiveKitReactNativeGlobal = lkGlobal;\n}\n\nfunction fixWebrtcAdapter() {\n // @ts-ignore\n if (window?.navigator !== undefined) {\n // @ts-ignore\n const { navigator } = window;\n if (navigator.userAgent === undefined) {\n navigator.userAgent = navigator.product ?? 'Unknown';\n }\n }\n}\n\nfunction shimPromiseAllSettled() {\n var allSettled = require('promise.allsettled');\n allSettled.shim();\n}\n\nfunction shimArrayAt() {\n // Some versions of RN don't have Array.prototype.at, which is used by sdp-transform\n if (!Array.prototype.at) {\n var at = require('array.prototype.at');\n at.shim();\n }\n}\n\nfunction shimAsyncIterator() {\n var shim = require('well-known-symbols/Symbol.asyncIterator/shim');\n shim();\n}\n\nfunction shimIterator() {\n var shim = require('well-known-symbols/Symbol.iterator/shim');\n shim();\n}\nexport * from './hooks';\nexport * from './components/BarVisualizer';\nexport * from './components/LiveKitRoom';\nexport * from './components/VideoTrack';\nexport * from './components/VideoView'; // deprecated\nexport * from './useParticipant'; // deprecated\nexport * from './useRoom'; // deprecated\nexport * from './logger';\nexport * from './audio/AudioManager';\n\nexport {\n AudioSession,\n RNE2EEManager,\n RNKeyProvider,\n AndroidAudioTypePresets,\n getDefaultAppleAudioConfigurationForMode,\n};\nexport type {\n AudioConfiguration,\n AndroidAudioTypeOptions,\n AppleAudioCategory,\n AppleAudioCategoryOption,\n AppleAudioConfiguration,\n AppleAudioMode,\n AudioTrackState,\n LogLevel,\n SetLogLevelOptions,\n RNKeyProviderOptions,\n};\n"],"mappings":"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","ignoreList":[]}
|