@livekit/react-native 2.7.5 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/android/src/main/java/com/livekit/reactnative/LivekitReactNativeModule.kt +15 -2
- package/ios/LiveKitReactNativeModule.swift +8 -0
- package/ios/LivekitReactNativeModule.m +2 -0
- package/lib/commonjs/audio/AudioSession.js +10 -0
- package/lib/commonjs/audio/AudioSession.js.map +1 -1
- package/lib/commonjs/components/VideoTrack.js.map +1 -1
- package/lib/module/audio/AudioSession.js +10 -0
- package/lib/module/audio/AudioSession.js.map +1 -1
- package/lib/module/components/VideoTrack.js.map +1 -1
- package/lib/typescript/src/audio/AudioSession.d.ts +8 -0
- package/lib/typescript/src/components/VideoTrack.d.ts +1 -1
- package/package.json +3 -3
- package/src/audio/AudioSession.ts +11 -0
- package/src/components/VideoTrack.tsx +3 -2
package/README.md
CHANGED
|
@@ -423,9 +423,9 @@ Apache License 2.0
|
|
|
423
423
|
<br/><table>
|
|
424
424
|
<thead><tr><th colspan="2">LiveKit Ecosystem</th></tr></thead>
|
|
425
425
|
<tbody>
|
|
426
|
-
<tr><td>LiveKit SDKs</td><td><a href="https://github.com/livekit/client-sdk-js">Browser</a> · <a href="https://github.com/livekit/client-sdk-swift">iOS/macOS/visionOS</a> · <a href="https://github.com/livekit/client-sdk-android">Android</a> · <a href="https://github.com/livekit/client-sdk-flutter">Flutter</a> · <b>React Native</b> · <a href="https://github.com/livekit/rust-sdks">Rust</a> · <a href="https://github.com/livekit/node-sdks">Node.js</a> · <a href="https://github.com/livekit/python-sdks">Python</a> · <a href="https://github.com/livekit/client-sdk-unity">Unity</a> · <a href="https://github.com/livekit/client-sdk-unity-web">Unity (WebGL)</a></td></tr><tr></tr>
|
|
426
|
+
<tr><td>LiveKit SDKs</td><td><a href="https://github.com/livekit/client-sdk-js">Browser</a> · <a href="https://github.com/livekit/client-sdk-swift">iOS/macOS/visionOS</a> · <a href="https://github.com/livekit/client-sdk-android">Android</a> · <a href="https://github.com/livekit/client-sdk-flutter">Flutter</a> · <b>React Native</b> · <a href="https://github.com/livekit/rust-sdks">Rust</a> · <a href="https://github.com/livekit/node-sdks">Node.js</a> · <a href="https://github.com/livekit/python-sdks">Python</a> · <a href="https://github.com/livekit/client-sdk-unity">Unity</a> · <a href="https://github.com/livekit/client-sdk-unity-web">Unity (WebGL)</a> · <a href="https://github.com/livekit/client-sdk-esp32">ESP32</a></td></tr><tr></tr>
|
|
427
427
|
<tr><td>Server APIs</td><td><a href="https://github.com/livekit/node-sdks">Node.js</a> · <a href="https://github.com/livekit/server-sdk-go">Golang</a> · <a href="https://github.com/livekit/server-sdk-ruby">Ruby</a> · <a href="https://github.com/livekit/server-sdk-kotlin">Java/Kotlin</a> · <a href="https://github.com/livekit/python-sdks">Python</a> · <a href="https://github.com/livekit/rust-sdks">Rust</a> · <a href="https://github.com/agence104/livekit-server-sdk-php">PHP (community)</a> · <a href="https://github.com/pabloFuente/livekit-server-sdk-dotnet">.NET (community)</a></td></tr><tr></tr>
|
|
428
|
-
<tr><td>UI Components</td><td><a href="https://github.com/livekit/components-js">React</a> · <a href="https://github.com/livekit/components-android">Android Compose</a> · <a href="https://github.com/livekit/components-swift">SwiftUI</a></td></tr><tr></tr>
|
|
428
|
+
<tr><td>UI Components</td><td><a href="https://github.com/livekit/components-js">React</a> · <a href="https://github.com/livekit/components-android">Android Compose</a> · <a href="https://github.com/livekit/components-swift">SwiftUI</a> · <a href="https://github.com/livekit/components-flutter">Flutter</a></td></tr><tr></tr>
|
|
429
429
|
<tr><td>Agents Frameworks</td><td><a href="https://github.com/livekit/agents">Python</a> · <a href="https://github.com/livekit/agents-js">Node.js</a> · <a href="https://github.com/livekit/agent-playground">Playground</a></td></tr><tr></tr>
|
|
430
430
|
<tr><td>Services</td><td><a href="https://github.com/livekit/livekit">LiveKit server</a> · <a href="https://github.com/livekit/egress">Egress</a> · <a href="https://github.com/livekit/ingress">Ingress</a> · <a href="https://github.com/livekit/sip">SIP</a></td></tr><tr></tr>
|
|
431
431
|
<tr><td>Resources</td><td><a href="https://docs.livekit.io">Docs</a> · <a href="https://github.com/livekit-examples">Example apps</a> · <a href="https://livekit.io/cloud">Cloud</a> · <a href="https://docs.livekit.io/home/self-hosting/deployment">Self-hosting</a> · <a href="https://github.com/livekit/livekit-cli">CLI</a></td></tr>
|
|
@@ -14,9 +14,13 @@ import com.livekit.reactnative.audio.AudioSwitchManager
|
|
|
14
14
|
import com.livekit.reactnative.audio.processing.AudioSinkManager
|
|
15
15
|
import com.livekit.reactnative.audio.processing.MultibandVolumeProcessor
|
|
16
16
|
import com.livekit.reactnative.audio.processing.VolumeProcessor
|
|
17
|
+
import com.oney.WebRTCModule.WebRTCModuleOptions
|
|
17
18
|
import org.webrtc.audio.WebRtcAudioTrackHelper
|
|
18
19
|
import kotlin.time.Duration.Companion.milliseconds
|
|
19
20
|
|
|
21
|
+
// NOTE: As of 0.80 react-native new architecture requires all
|
|
22
|
+
// @ReactMethod(isBlockingSynchronousMethod = true)
|
|
23
|
+
// annotated methods to be non-void.
|
|
20
24
|
|
|
21
25
|
class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
|
22
26
|
|
|
@@ -141,9 +145,10 @@ class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactCon
|
|
|
141
145
|
}
|
|
142
146
|
|
|
143
147
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
144
|
-
fun deleteVolumeProcessor(reactTag: String, pcId: Int, trackId: String) {
|
|
148
|
+
fun deleteVolumeProcessor(reactTag: String, pcId: Int, trackId: String): Boolean {
|
|
145
149
|
audioSinkManager.detachSinkFromTrack(reactTag, pcId, trackId)
|
|
146
150
|
audioSinkManager.unregisterSink(reactTag)
|
|
151
|
+
return true
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
@@ -170,7 +175,7 @@ class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactCon
|
|
|
170
175
|
}
|
|
171
176
|
|
|
172
177
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
173
|
-
fun deleteMultibandVolumeProcessor(reactTag: String, pcId: Int, trackId: String) {
|
|
178
|
+
fun deleteMultibandVolumeProcessor(reactTag: String, pcId: Int, trackId: String): Boolean {
|
|
174
179
|
val volumeProcessor =
|
|
175
180
|
audioSinkManager.getSink(reactTag) ?: throw IllegalArgumentException("Can't find volume processor for $reactTag")
|
|
176
181
|
audioSinkManager.detachSinkFromTrack(volumeProcessor, pcId, trackId)
|
|
@@ -181,7 +186,10 @@ class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactCon
|
|
|
181
186
|
multibandVolumeProcessor.release()
|
|
182
187
|
} else {
|
|
183
188
|
Log.w(name, "deleteMultibandVolumeProcessor called, but non-MultibandVolumeProcessor found?!")
|
|
189
|
+
return false
|
|
184
190
|
}
|
|
191
|
+
|
|
192
|
+
return true
|
|
185
193
|
}
|
|
186
194
|
|
|
187
195
|
@ReactMethod
|
|
@@ -194,6 +202,11 @@ class LivekitReactNativeModule(reactContext: ReactApplicationContext) : ReactCon
|
|
|
194
202
|
// Keep: Required for RN built in Event Emitter Calls.
|
|
195
203
|
}
|
|
196
204
|
|
|
205
|
+
@ReactMethod
|
|
206
|
+
fun setDefaultAudioTrackVolume(volume: Double) {
|
|
207
|
+
WebRTCModuleOptions.getInstance().defaultTrackVolume = volume
|
|
208
|
+
}
|
|
209
|
+
|
|
197
210
|
override fun invalidate() {
|
|
198
211
|
LiveKitReactNative.invalidate(reactApplicationContext)
|
|
199
212
|
}
|
|
@@ -225,6 +225,14 @@ public class LivekitReactNativeModule: RCTEventEmitter {
|
|
|
225
225
|
return nil
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
@objc(setDefaultAudioTrackVolume:)
|
|
229
|
+
public func setDefaultAudioTrackVolume(_ volume: NSNumber) -> Any? {
|
|
230
|
+
let options = WebRTCModuleOptions.sharedInstance()
|
|
231
|
+
options.defaultTrackVolume = volume.doubleValue
|
|
232
|
+
|
|
233
|
+
return nil
|
|
234
|
+
}
|
|
235
|
+
|
|
228
236
|
override public func supportedEvents() -> [String]! {
|
|
229
237
|
return [
|
|
230
238
|
LKEvents.kEventVolumeProcessed,
|
|
@@ -8,6 +8,8 @@ RCT_EXTERN_METHOD(configureAudio:(NSDictionary *) config)
|
|
|
8
8
|
RCT_EXTERN_METHOD(startAudioSession)
|
|
9
9
|
RCT_EXTERN_METHOD(stopAudioSession)
|
|
10
10
|
|
|
11
|
+
RCT_EXTERN_METHOD(setDefaultAudioTrackVolume:(nonnull NSNumber *) volume)
|
|
12
|
+
|
|
11
13
|
RCT_EXTERN_METHOD(showAudioRoutePicker)
|
|
12
14
|
RCT_EXTERN_METHOD(getAudioOutputsWithResolver:(RCTPromiseResolveBlock)resolve
|
|
13
15
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
@@ -101,6 +101,16 @@ _defineProperty(AudioSession, "startAudioSession", async () => {
|
|
|
101
101
|
_defineProperty(AudioSession, "stopAudioSession", async () => {
|
|
102
102
|
await _LKNativeModule.default.stopAudioSession();
|
|
103
103
|
});
|
|
104
|
+
/**
|
|
105
|
+
* Set default audio track volume when new tracks are subscribed.
|
|
106
|
+
* Does **not** affect any existing tracks.
|
|
107
|
+
*
|
|
108
|
+
* @param volume A number between 0.0 and 1.0, where 0.0 represents 0% volume and
|
|
109
|
+
* 1.0 represents full volume.
|
|
110
|
+
*/
|
|
111
|
+
_defineProperty(AudioSession, "setDefaultRemoteAudioTrackVolume", async volume => {
|
|
112
|
+
await _LKNativeModule.default.setDefaultAudioTrackVolume(volume);
|
|
113
|
+
});
|
|
104
114
|
/**
|
|
105
115
|
* Gets the available audio outputs for use with {@link selectAudioOutput}.
|
|
106
116
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_LKNativeModule","_interopRequireDefault","e","__esModule","default","_defineProperty","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","AndroidAudioTypePresets","exports","communication","manageAudioFocus","audioMode","audioFocusMode","audioStreamType","audioAttributesUsageType","audioAttributesContentType","media","getDefaultAppleAudioConfigurationForMode","mode","preferSpeakerOutput","audioCategory","audioCategoryOptions","AudioSession","config","LiveKitModule","configureAudio","startAudioSession","stopAudioSession","Platform","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":[]}
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_LKNativeModule","_interopRequireDefault","e","__esModule","default","_defineProperty","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","AndroidAudioTypePresets","exports","communication","manageAudioFocus","audioMode","audioFocusMode","audioStreamType","audioAttributesUsageType","audioAttributesContentType","media","getDefaultAppleAudioConfigurationForMode","mode","preferSpeakerOutput","audioCategory","audioCategoryOptions","AudioSession","config","LiveKitModule","configureAudio","startAudioSession","stopAudioSession","volume","setDefaultAudioTrackVolume","Platform","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 * Set default audio track volume when new tracks are subscribed.\n * Does **not** affect any existing tracks.\n *\n * @param volume A number between 0.0 and 1.0, where 0.0 represents 0% volume and\n * 1.0 represents full volume.\n */\n static setDefaultRemoteAudioTrackVolume = async (volume: number) => {\n await LiveKitModule.setDefaultAudioTrackVolume(volume);\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":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","React","_reactNative","_livekitClient","_reactNativeWebrtc","_ViewPortDetector","_interopRequireDefault","e","__esModule","default","_getRequireWildcardCache","WeakMap","r","t","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","_defineProperty","_toPropertyKey","value","enumerable","configurable","writable","_toPrimitive","Symbol","toPrimitive","TypeError","String","Number","VideoTrack","exports","forwardRef","style","trackRef","objectFit","zOrder","mirror","iosPIP","ref","elementInfo","useState","_trackRef$publication","info","VideoTrackElementInfo","id","publication","trackSid","layoutOnChange","useCallback","event","onLayout","iosPIPEnabled","enabled","visibilityOnChange","isVisible","onVisibility","videoTrack","track","shouldObserveVisibility","useMemo","RemoteVideoTrack","isAdaptiveStream","mediaStream","setMediaStream","useEffect","LocalVideoTrack","onRestarted","on","TrackEvent","Restarted","off","observeElementInfo","stopObservingElementInfo","videoView","Platform","OS","createElement","RTCView","styles","streamURL","toURL","RTCPIPView","View","container","onChange","disabled","propKey","StyleSheet","create","flex","width","constructor","_width","_height","observe","_observing","stopObserving","height","nativeEvent","layout","_this$handleResize","handleResize","visible","visibilityChangedAt","Date","now","_this$handleVisibilit","handleVisibilityChanged"],"sources":["VideoTrack.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n type LayoutChangeEvent,\n Platform,\n StyleSheet,\n View,\n type ViewStyle,\n} from 'react-native';\nimport {\n type ElementInfo,\n LocalVideoTrack,\n Track,\n TrackEvent,\n} from 'livekit-client';\nimport {\n RTCView,\n RTCPIPView,\n type RTCIOSPIPOptions,\n} from '@livekit/react-native-webrtc';\nimport {\n Component,\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport { RemoteVideoTrack } from 'livekit-client';\nimport ViewPortDetector from './ViewPortDetector';\nimport type { TrackReference } from '@livekit/components-react';\n\n/**\n * Props for the VideoTrack component.\n * @public\n */\nexport type VideoTrackProps = {\n /**\n * The track reference to display. This should be a TrackReference object\n * or undefined if no track is available.\n */\n trackRef: TrackReference | undefined;\n /**\n * Custom React Native styles for the video container.\n */\n style?: ViewStyle;\n /**\n * Specifies how the video content should be resized to fit its container.\n * 'cover' (default): The video will fill the entire container, potentially cropping the video.\n * 'contain': The entire video will be visible within the container, potentially leaving empty space.\n */\n objectFit?: 'cover' | 'contain' | undefined;\n /**\n * Indicates whether the video should be mirrored during rendering.\n * This is commonly used for front-facing cameras.\n */\n mirror?: boolean;\n /**\n * Specifies the depth-stacking order of this video view in the stacking space of all video views.\n * A larger zOrder value generally causes the view to cover those with lower values.\n *\n * The support for zOrder is platform-dependent and/or\n * implementation-specific. Thus, specifying a value for zOrder is to be\n * thought of as giving a hint rather than as imposing a requirement. For\n * example, video renderers such as RTCView are commonly implemented using\n * OpenGL and OpenGL views may have different numbers of layers in their\n * stacking space. Android has three: a layer bellow the window (aka\n * default), a layer bellow the window again but above the previous layer\n * (aka media overlay), and above the window. Consequently, it is advisable\n * to limit the number of utilized layers in the stacking space to the\n * minimum sufficient for the desired display. For example, a video call\n * application usually needs a maximum of two zOrder values: 0 for the\n * remote video(s) which appear in the background, and 1 for the local\n * video(s) which appear above the remote video(s).\n */\n zOrder?: number;\n\n /**\n * Picture in picture options for this view. Disabled if not supplied.\n *\n * iOS only. Requires iOS 15.0 or above, and the PIP background mode capability.\n *\n * If `iosPIP.enabled` is true, the methods `startIOSPIP` and `stopIOSPIP`\n * can be used to manually trigger the PIP mode.\n *\n * `iosPIP.startAutomatically` can be used to automatically\n * enter PIP when backgrounding the app.\n *\n * `iosPIP.preferredSize` is used to provide a suggested aspect ratio.\n *\n * @example\n * ```tsx\n * import { startIOSPIP, stopIOSPIP } from '@livekit/react-native-webrtc';\n *\n * // Obtain a ref to the view\n * const videoRef = useRef<Component>(null);\n * const videoView = (\n * <VideoTrack\n * ref={videoRef}\n * iosPIP={{\n * enabled: true,\n * startAutomatically: true,\n * preferredSize: {\n * width: 9,\n * height: 16,\n * },\n * }}\n * ...\n * />\n * );\n *\n * // Start/stop manually\n * startIOSPIP(videoRef);\n * stopIOSPIP(videoRef);\n * ```\n *\n */\n iosPIP?: RTCIOSPIPOptions & {\n preferredSize: {\n width: number;\n height: number;\n };\n fallbackView?: ReactNode;\n };\n};\n\n/**\n * VideoTrack component for displaying video tracks in a React Native application.\n * It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.\n *\n * @param props - See VideoTrackProps for details.\n * @returns A React component that renders the given video track.\n * @public\n */\nexport const VideoTrack = forwardRef<Component, VideoTrackProps>(\n (\n {\n style = {},\n trackRef,\n objectFit = 'cover',\n zOrder,\n mirror,\n iosPIP,\n }: VideoTrackProps,\n ref\n ) => {\n const [elementInfo] = useState(() => {\n let info = new VideoTrackElementInfo();\n info.id = trackRef?.publication?.trackSid;\n return info;\n });\n\n const layoutOnChange = useCallback(\n (event: LayoutChangeEvent) => elementInfo.onLayout(event),\n [elementInfo]\n );\n\n const iosPIPEnabled = iosPIP?.enabled ?? false;\n const visibilityOnChange = useCallback(\n (isVisible: boolean) =>\n elementInfo.onVisibility(isVisible || iosPIPEnabled),\n [elementInfo, iosPIPEnabled]\n );\n\n const videoTrack = trackRef?.publication.track;\n\n const shouldObserveVisibility = useMemo(() => {\n return (\n videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream\n );\n }, [videoTrack]);\n\n const [mediaStream, setMediaStream] = useState(videoTrack?.mediaStream);\n useEffect(() => {\n setMediaStream(videoTrack?.mediaStream);\n if (videoTrack instanceof LocalVideoTrack) {\n const onRestarted = (track: Track | null) => {\n setMediaStream(track?.mediaStream);\n };\n videoTrack.on(TrackEvent.Restarted, onRestarted);\n\n return () => {\n videoTrack.off(TrackEvent.Restarted, onRestarted);\n };\n } else {\n return () => {};\n }\n }, [videoTrack]);\n\n useEffect(() => {\n if (\n videoTrack instanceof RemoteVideoTrack &&\n videoTrack.isAdaptiveStream\n ) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\n\n let videoView;\n if (!iosPIP || Platform.OS !== 'ios') {\n videoView = (\n <RTCView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n // @ts-ignore\n ref={ref}\n />\n );\n } else {\n videoView = (\n <RTCPIPView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n // TODO: fix this up in react-native-webrtc side.\n // @ts-expect-error\n iosPIP={iosPIP}\n ref={ref}\n />\n );\n }\n return (\n <View style={{ ...style, ...styles.container }} onLayout={layoutOnChange}>\n <ViewPortDetector\n onChange={visibilityOnChange}\n style={styles.videoTrack}\n disabled={!shouldObserveVisibility}\n propKey={videoTrack}\n >\n {videoView}\n </ViewPortDetector>\n </View>\n );\n }\n);\n\nconst styles = StyleSheet.create({\n container: {},\n videoTrack: {\n flex: 1,\n width: '100%',\n },\n});\n\nclass VideoTrackElementInfo implements ElementInfo {\n element: object = {};\n something?: any;\n id?: string;\n _width = 0;\n _height = 0;\n _observing = false;\n visible: boolean = true;\n visibilityChangedAt: number | undefined;\n pictureInPicture = false;\n handleResize?: (() => void) | undefined;\n handleVisibilityChanged?: (() => void) | undefined;\n width = () => this._width;\n height = () => this._height;\n\n observe(): void {\n this._observing = true;\n }\n\n stopObserving(): void {\n this._observing = false;\n }\n\n onLayout(event: LayoutChangeEvent) {\n let { width, height } = event.nativeEvent.layout;\n this._width = width;\n this._height = height;\n\n if (this._observing) {\n this.handleResize?.();\n }\n }\n\n onVisibility(isVisible: boolean) {\n if (this.visible !== isVisible) {\n this.visible = isVisible;\n this.visibilityChangedAt = Date.now();\n if (this._observing) {\n this.handleVisibilityChanged?.();\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","React","_reactNative","_livekitClient","_reactNativeWebrtc","_ViewPortDetector","_interopRequireDefault","e","__esModule","default","_getRequireWildcardCache","WeakMap","r","t","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","_defineProperty","_toPropertyKey","value","enumerable","configurable","writable","_toPrimitive","Symbol","toPrimitive","TypeError","String","Number","VideoTrack","exports","forwardRef","style","trackRef","objectFit","zOrder","mirror","iosPIP","ref","elementInfo","useState","_trackRef$publication","info","VideoTrackElementInfo","id","publication","trackSid","layoutOnChange","useCallback","event","onLayout","iosPIPEnabled","enabled","visibilityOnChange","isVisible","onVisibility","videoTrack","track","shouldObserveVisibility","useMemo","RemoteVideoTrack","isAdaptiveStream","mediaStream","setMediaStream","useEffect","LocalVideoTrack","onRestarted","on","TrackEvent","Restarted","off","observeElementInfo","stopObservingElementInfo","videoView","Platform","OS","createElement","RTCView","styles","streamURL","toURL","RTCPIPView","View","container","onChange","disabled","propKey","StyleSheet","create","flex","width","constructor","_width","_height","observe","_observing","stopObserving","height","nativeEvent","layout","_this$handleResize","handleResize","visible","visibilityChangedAt","Date","now","_this$handleVisibilit","handleVisibilityChanged"],"sources":["VideoTrack.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n type LayoutChangeEvent,\n Platform,\n StyleSheet,\n View,\n type ViewStyle,\n} from 'react-native';\nimport {\n type ElementInfo,\n LocalVideoTrack,\n Track,\n TrackEvent,\n} from 'livekit-client';\nimport {\n RTCView,\n RTCPIPView,\n type RTCIOSPIPOptions,\n} from '@livekit/react-native-webrtc';\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport { RemoteVideoTrack } from 'livekit-client';\nimport ViewPortDetector from './ViewPortDetector';\nimport type { TrackReference } from '@livekit/components-react';\n\n/**\n * Props for the VideoTrack component.\n * @public\n */\nexport type VideoTrackProps = {\n /**\n * The track reference to display. This should be a TrackReference object\n * or undefined if no track is available.\n */\n trackRef: TrackReference | undefined;\n /**\n * Custom React Native styles for the video container.\n */\n style?: ViewStyle;\n /**\n * Specifies how the video content should be resized to fit its container.\n * 'cover' (default): The video will fill the entire container, potentially cropping the video.\n * 'contain': The entire video will be visible within the container, potentially leaving empty space.\n */\n objectFit?: 'cover' | 'contain' | undefined;\n /**\n * Indicates whether the video should be mirrored during rendering.\n * This is commonly used for front-facing cameras.\n */\n mirror?: boolean;\n /**\n * Specifies the depth-stacking order of this video view in the stacking space of all video views.\n * A larger zOrder value generally causes the view to cover those with lower values.\n *\n * The support for zOrder is platform-dependent and/or\n * implementation-specific. Thus, specifying a value for zOrder is to be\n * thought of as giving a hint rather than as imposing a requirement. For\n * example, video renderers such as RTCView are commonly implemented using\n * OpenGL and OpenGL views may have different numbers of layers in their\n * stacking space. Android has three: a layer bellow the window (aka\n * default), a layer bellow the window again but above the previous layer\n * (aka media overlay), and above the window. Consequently, it is advisable\n * to limit the number of utilized layers in the stacking space to the\n * minimum sufficient for the desired display. For example, a video call\n * application usually needs a maximum of two zOrder values: 0 for the\n * remote video(s) which appear in the background, and 1 for the local\n * video(s) which appear above the remote video(s).\n */\n zOrder?: number;\n\n /**\n * Picture in picture options for this view. Disabled if not supplied.\n *\n * iOS only. Requires iOS 15.0 or above, and the PIP background mode capability.\n *\n * If `iosPIP.enabled` is true, the methods `startIOSPIP` and `stopIOSPIP`\n * can be used to manually trigger the PIP mode.\n *\n * `iosPIP.startAutomatically` can be used to automatically\n * enter PIP when backgrounding the app.\n *\n * `iosPIP.preferredSize` is used to provide a suggested aspect ratio.\n *\n * @example\n * ```tsx\n * import { startIOSPIP, stopIOSPIP } from '@livekit/react-native-webrtc';\n *\n * // Obtain a ref to the view\n * const videoRef = useRef<Component>(null);\n * const videoView = (\n * <VideoTrack\n * ref={videoRef}\n * iosPIP={{\n * enabled: true,\n * startAutomatically: true,\n * preferredSize: {\n * width: 9,\n * height: 16,\n * },\n * }}\n * ...\n * />\n * );\n *\n * // Start/stop manually\n * startIOSPIP(videoRef);\n * stopIOSPIP(videoRef);\n * ```\n *\n */\n iosPIP?: RTCIOSPIPOptions & {\n preferredSize: {\n width: number;\n height: number;\n };\n fallbackView?: ReactNode;\n };\n};\n\ntype RTCViewInstance = InstanceType<typeof RTCView>;\n\n/**\n * VideoTrack component for displaying video tracks in a React Native application.\n * It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.\n *\n * @param props - See VideoTrackProps for details.\n * @returns A React component that renders the given video track.\n * @public\n */\nexport const VideoTrack = forwardRef<RTCViewInstance, VideoTrackProps>(\n (\n {\n style = {},\n trackRef,\n objectFit = 'cover',\n zOrder,\n mirror,\n iosPIP,\n }: VideoTrackProps,\n ref\n ) => {\n const [elementInfo] = useState(() => {\n let info = new VideoTrackElementInfo();\n info.id = trackRef?.publication?.trackSid;\n return info;\n });\n\n const layoutOnChange = useCallback(\n (event: LayoutChangeEvent) => elementInfo.onLayout(event),\n [elementInfo]\n );\n\n const iosPIPEnabled = iosPIP?.enabled ?? false;\n const visibilityOnChange = useCallback(\n (isVisible: boolean) =>\n elementInfo.onVisibility(isVisible || iosPIPEnabled),\n [elementInfo, iosPIPEnabled]\n );\n\n const videoTrack = trackRef?.publication.track;\n\n const shouldObserveVisibility = useMemo(() => {\n return (\n videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream\n );\n }, [videoTrack]);\n\n const [mediaStream, setMediaStream] = useState(videoTrack?.mediaStream);\n useEffect(() => {\n setMediaStream(videoTrack?.mediaStream);\n if (videoTrack instanceof LocalVideoTrack) {\n const onRestarted = (track: Track | null) => {\n setMediaStream(track?.mediaStream);\n };\n videoTrack.on(TrackEvent.Restarted, onRestarted);\n\n return () => {\n videoTrack.off(TrackEvent.Restarted, onRestarted);\n };\n } else {\n return () => {};\n }\n }, [videoTrack]);\n\n useEffect(() => {\n if (\n videoTrack instanceof RemoteVideoTrack &&\n videoTrack.isAdaptiveStream\n ) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\n\n let videoView;\n if (!iosPIP || Platform.OS !== 'ios') {\n videoView = (\n <RTCView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n // @ts-ignore\n ref={ref}\n />\n );\n } else {\n videoView = (\n <RTCPIPView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n // TODO: fix this up in react-native-webrtc side.\n // @ts-expect-error\n iosPIP={iosPIP}\n ref={ref}\n />\n );\n }\n return (\n <View style={{ ...style, ...styles.container }} onLayout={layoutOnChange}>\n <ViewPortDetector\n onChange={visibilityOnChange}\n style={styles.videoTrack}\n disabled={!shouldObserveVisibility}\n propKey={videoTrack}\n >\n {videoView}\n </ViewPortDetector>\n </View>\n );\n }\n);\n\nconst styles = StyleSheet.create({\n container: {},\n videoTrack: {\n flex: 1,\n width: '100%',\n },\n});\n\nclass VideoTrackElementInfo implements ElementInfo {\n element: object = {};\n something?: any;\n id?: string;\n _width = 0;\n _height = 0;\n _observing = false;\n visible: boolean = true;\n visibilityChangedAt: number | undefined;\n pictureInPicture = false;\n handleResize?: (() => void) | undefined;\n handleVisibilityChanged?: (() => void) | undefined;\n width = () => this._width;\n height = () => this._height;\n\n observe(): void {\n this._observing = true;\n }\n\n stopObserving(): void {\n this._observing = false;\n }\n\n onLayout(event: LayoutChangeEvent) {\n let { width, height } = event.nativeEvent.layout;\n this._width = width;\n this._height = height;\n\n if (this._observing) {\n this.handleResize?.();\n }\n }\n\n onVisibility(isVisible: boolean) {\n if (this.visible !== isVisible) {\n this.visible = isVisible;\n this.visibilityChangedAt = Date.now();\n if (this._observing) {\n this.handleVisibilityChanged?.();\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -93,6 +93,16 @@ _defineProperty(AudioSession, "startAudioSession", async () => {
|
|
|
93
93
|
_defineProperty(AudioSession, "stopAudioSession", async () => {
|
|
94
94
|
await LiveKitModule.stopAudioSession();
|
|
95
95
|
});
|
|
96
|
+
/**
|
|
97
|
+
* Set default audio track volume when new tracks are subscribed.
|
|
98
|
+
* Does **not** affect any existing tracks.
|
|
99
|
+
*
|
|
100
|
+
* @param volume A number between 0.0 and 1.0, where 0.0 represents 0% volume and
|
|
101
|
+
* 1.0 represents full volume.
|
|
102
|
+
*/
|
|
103
|
+
_defineProperty(AudioSession, "setDefaultRemoteAudioTrackVolume", async volume => {
|
|
104
|
+
await LiveKitModule.setDefaultAudioTrackVolume(volume);
|
|
105
|
+
});
|
|
96
106
|
/**
|
|
97
107
|
* Gets the available audio outputs for use with {@link selectAudioOutput}.
|
|
98
108
|
*
|
|
@@ -1 +1 @@
|
|
|
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":[]}
|
|
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","volume","setDefaultAudioTrackVolume","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 * Set default audio track volume when new tracks are subscribed.\n * Does **not** affect any existing tracks.\n *\n * @param volume A number between 0.0 and 1.0, where 0.0 represents 0% volume and\n * 1.0 represents full volume.\n */\n static setDefaultRemoteAudioTrackVolume = async (volume: number) => {\n await LiveKitModule.setDefaultAudioTrackVolume(volume);\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":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","Platform","StyleSheet","View","LocalVideoTrack","TrackEvent","RTCView","RTCPIPView","forwardRef","useCallback","useEffect","useMemo","useState","RemoteVideoTrack","ViewPortDetector","VideoTrack","style","trackRef","objectFit","zOrder","mirror","iosPIP","ref","elementInfo","_trackRef$publication","info","VideoTrackElementInfo","id","publication","trackSid","layoutOnChange","event","onLayout","iosPIPEnabled","enabled","visibilityOnChange","isVisible","onVisibility","videoTrack","track","shouldObserveVisibility","isAdaptiveStream","mediaStream","setMediaStream","onRestarted","on","Restarted","off","observeElementInfo","stopObservingElementInfo","videoView","OS","createElement","styles","streamURL","toURL","container","onChange","disabled","propKey","create","flex","width","constructor","_defineProperty","_width","_height","observe","_observing","stopObserving","height","nativeEvent","layout","_this$handleResize","handleResize","call","visible","visibilityChangedAt","Date","now","_this$handleVisibilit","handleVisibilityChanged"],"sources":["VideoTrack.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n type LayoutChangeEvent,\n Platform,\n StyleSheet,\n View,\n type ViewStyle,\n} from 'react-native';\nimport {\n type ElementInfo,\n LocalVideoTrack,\n Track,\n TrackEvent,\n} from 'livekit-client';\nimport {\n RTCView,\n RTCPIPView,\n type RTCIOSPIPOptions,\n} from '@livekit/react-native-webrtc';\nimport {\n Component,\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport { RemoteVideoTrack } from 'livekit-client';\nimport ViewPortDetector from './ViewPortDetector';\nimport type { TrackReference } from '@livekit/components-react';\n\n/**\n * Props for the VideoTrack component.\n * @public\n */\nexport type VideoTrackProps = {\n /**\n * The track reference to display. This should be a TrackReference object\n * or undefined if no track is available.\n */\n trackRef: TrackReference | undefined;\n /**\n * Custom React Native styles for the video container.\n */\n style?: ViewStyle;\n /**\n * Specifies how the video content should be resized to fit its container.\n * 'cover' (default): The video will fill the entire container, potentially cropping the video.\n * 'contain': The entire video will be visible within the container, potentially leaving empty space.\n */\n objectFit?: 'cover' | 'contain' | undefined;\n /**\n * Indicates whether the video should be mirrored during rendering.\n * This is commonly used for front-facing cameras.\n */\n mirror?: boolean;\n /**\n * Specifies the depth-stacking order of this video view in the stacking space of all video views.\n * A larger zOrder value generally causes the view to cover those with lower values.\n *\n * The support for zOrder is platform-dependent and/or\n * implementation-specific. Thus, specifying a value for zOrder is to be\n * thought of as giving a hint rather than as imposing a requirement. For\n * example, video renderers such as RTCView are commonly implemented using\n * OpenGL and OpenGL views may have different numbers of layers in their\n * stacking space. Android has three: a layer bellow the window (aka\n * default), a layer bellow the window again but above the previous layer\n * (aka media overlay), and above the window. Consequently, it is advisable\n * to limit the number of utilized layers in the stacking space to the\n * minimum sufficient for the desired display. For example, a video call\n * application usually needs a maximum of two zOrder values: 0 for the\n * remote video(s) which appear in the background, and 1 for the local\n * video(s) which appear above the remote video(s).\n */\n zOrder?: number;\n\n /**\n * Picture in picture options for this view. Disabled if not supplied.\n *\n * iOS only. Requires iOS 15.0 or above, and the PIP background mode capability.\n *\n * If `iosPIP.enabled` is true, the methods `startIOSPIP` and `stopIOSPIP`\n * can be used to manually trigger the PIP mode.\n *\n * `iosPIP.startAutomatically` can be used to automatically\n * enter PIP when backgrounding the app.\n *\n * `iosPIP.preferredSize` is used to provide a suggested aspect ratio.\n *\n * @example\n * ```tsx\n * import { startIOSPIP, stopIOSPIP } from '@livekit/react-native-webrtc';\n *\n * // Obtain a ref to the view\n * const videoRef = useRef<Component>(null);\n * const videoView = (\n * <VideoTrack\n * ref={videoRef}\n * iosPIP={{\n * enabled: true,\n * startAutomatically: true,\n * preferredSize: {\n * width: 9,\n * height: 16,\n * },\n * }}\n * ...\n * />\n * );\n *\n * // Start/stop manually\n * startIOSPIP(videoRef);\n * stopIOSPIP(videoRef);\n * ```\n *\n */\n iosPIP?: RTCIOSPIPOptions & {\n preferredSize: {\n width: number;\n height: number;\n };\n fallbackView?: ReactNode;\n };\n};\n\n/**\n * VideoTrack component for displaying video tracks in a React Native application.\n * It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.\n *\n * @param props - See VideoTrackProps for details.\n * @returns A React component that renders the given video track.\n * @public\n */\nexport const VideoTrack = forwardRef<Component, VideoTrackProps>(\n (\n {\n style = {},\n trackRef,\n objectFit = 'cover',\n zOrder,\n mirror,\n iosPIP,\n }: VideoTrackProps,\n ref\n ) => {\n const [elementInfo] = useState(() => {\n let info = new VideoTrackElementInfo();\n info.id = trackRef?.publication?.trackSid;\n return info;\n });\n\n const layoutOnChange = useCallback(\n (event: LayoutChangeEvent) => elementInfo.onLayout(event),\n [elementInfo]\n );\n\n const iosPIPEnabled = iosPIP?.enabled ?? false;\n const visibilityOnChange = useCallback(\n (isVisible: boolean) =>\n elementInfo.onVisibility(isVisible || iosPIPEnabled),\n [elementInfo, iosPIPEnabled]\n );\n\n const videoTrack = trackRef?.publication.track;\n\n const shouldObserveVisibility = useMemo(() => {\n return (\n videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream\n );\n }, [videoTrack]);\n\n const [mediaStream, setMediaStream] = useState(videoTrack?.mediaStream);\n useEffect(() => {\n setMediaStream(videoTrack?.mediaStream);\n if (videoTrack instanceof LocalVideoTrack) {\n const onRestarted = (track: Track | null) => {\n setMediaStream(track?.mediaStream);\n };\n videoTrack.on(TrackEvent.Restarted, onRestarted);\n\n return () => {\n videoTrack.off(TrackEvent.Restarted, onRestarted);\n };\n } else {\n return () => {};\n }\n }, [videoTrack]);\n\n useEffect(() => {\n if (\n videoTrack instanceof RemoteVideoTrack &&\n videoTrack.isAdaptiveStream\n ) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\n\n let videoView;\n if (!iosPIP || Platform.OS !== 'ios') {\n videoView = (\n <RTCView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n // @ts-ignore\n ref={ref}\n />\n );\n } else {\n videoView = (\n <RTCPIPView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n // TODO: fix this up in react-native-webrtc side.\n // @ts-expect-error\n iosPIP={iosPIP}\n ref={ref}\n />\n );\n }\n return (\n <View style={{ ...style, ...styles.container }} onLayout={layoutOnChange}>\n <ViewPortDetector\n onChange={visibilityOnChange}\n style={styles.videoTrack}\n disabled={!shouldObserveVisibility}\n propKey={videoTrack}\n >\n {videoView}\n </ViewPortDetector>\n </View>\n );\n }\n);\n\nconst styles = StyleSheet.create({\n container: {},\n videoTrack: {\n flex: 1,\n width: '100%',\n },\n});\n\nclass VideoTrackElementInfo implements ElementInfo {\n element: object = {};\n something?: any;\n id?: string;\n _width = 0;\n _height = 0;\n _observing = false;\n visible: boolean = true;\n visibilityChangedAt: number | undefined;\n pictureInPicture = false;\n handleResize?: (() => void) | undefined;\n handleVisibilityChanged?: (() => void) | undefined;\n width = () => this._width;\n height = () => this._height;\n\n observe(): void {\n this._observing = true;\n }\n\n stopObserving(): void {\n this._observing = false;\n }\n\n onLayout(event: LayoutChangeEvent) {\n let { width, height } = event.nativeEvent.layout;\n this._width = width;\n this._height = height;\n\n if (this._observing) {\n this.handleResize?.();\n }\n }\n\n onVisibility(isVisible: boolean) {\n if (this.visible !== isVisible) {\n this.visible = isVisible;\n this.visibilityChangedAt = Date.now();\n if (this._observing) {\n this.handleVisibilityChanged?.();\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["React","Platform","StyleSheet","View","LocalVideoTrack","TrackEvent","RTCView","RTCPIPView","forwardRef","useCallback","useEffect","useMemo","useState","RemoteVideoTrack","ViewPortDetector","VideoTrack","style","trackRef","objectFit","zOrder","mirror","iosPIP","ref","elementInfo","_trackRef$publication","info","VideoTrackElementInfo","id","publication","trackSid","layoutOnChange","event","onLayout","iosPIPEnabled","enabled","visibilityOnChange","isVisible","onVisibility","videoTrack","track","shouldObserveVisibility","isAdaptiveStream","mediaStream","setMediaStream","onRestarted","on","Restarted","off","observeElementInfo","stopObservingElementInfo","videoView","OS","createElement","styles","streamURL","toURL","container","onChange","disabled","propKey","create","flex","width","constructor","_defineProperty","_width","_height","observe","_observing","stopObserving","height","nativeEvent","layout","_this$handleResize","handleResize","call","visible","visibilityChangedAt","Date","now","_this$handleVisibilit","handleVisibilityChanged"],"sources":["VideoTrack.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n type LayoutChangeEvent,\n Platform,\n StyleSheet,\n View,\n type ViewStyle,\n} from 'react-native';\nimport {\n type ElementInfo,\n LocalVideoTrack,\n Track,\n TrackEvent,\n} from 'livekit-client';\nimport {\n RTCView,\n RTCPIPView,\n type RTCIOSPIPOptions,\n} from '@livekit/react-native-webrtc';\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport { RemoteVideoTrack } from 'livekit-client';\nimport ViewPortDetector from './ViewPortDetector';\nimport type { TrackReference } from '@livekit/components-react';\n\n/**\n * Props for the VideoTrack component.\n * @public\n */\nexport type VideoTrackProps = {\n /**\n * The track reference to display. This should be a TrackReference object\n * or undefined if no track is available.\n */\n trackRef: TrackReference | undefined;\n /**\n * Custom React Native styles for the video container.\n */\n style?: ViewStyle;\n /**\n * Specifies how the video content should be resized to fit its container.\n * 'cover' (default): The video will fill the entire container, potentially cropping the video.\n * 'contain': The entire video will be visible within the container, potentially leaving empty space.\n */\n objectFit?: 'cover' | 'contain' | undefined;\n /**\n * Indicates whether the video should be mirrored during rendering.\n * This is commonly used for front-facing cameras.\n */\n mirror?: boolean;\n /**\n * Specifies the depth-stacking order of this video view in the stacking space of all video views.\n * A larger zOrder value generally causes the view to cover those with lower values.\n *\n * The support for zOrder is platform-dependent and/or\n * implementation-specific. Thus, specifying a value for zOrder is to be\n * thought of as giving a hint rather than as imposing a requirement. For\n * example, video renderers such as RTCView are commonly implemented using\n * OpenGL and OpenGL views may have different numbers of layers in their\n * stacking space. Android has three: a layer bellow the window (aka\n * default), a layer bellow the window again but above the previous layer\n * (aka media overlay), and above the window. Consequently, it is advisable\n * to limit the number of utilized layers in the stacking space to the\n * minimum sufficient for the desired display. For example, a video call\n * application usually needs a maximum of two zOrder values: 0 for the\n * remote video(s) which appear in the background, and 1 for the local\n * video(s) which appear above the remote video(s).\n */\n zOrder?: number;\n\n /**\n * Picture in picture options for this view. Disabled if not supplied.\n *\n * iOS only. Requires iOS 15.0 or above, and the PIP background mode capability.\n *\n * If `iosPIP.enabled` is true, the methods `startIOSPIP` and `stopIOSPIP`\n * can be used to manually trigger the PIP mode.\n *\n * `iosPIP.startAutomatically` can be used to automatically\n * enter PIP when backgrounding the app.\n *\n * `iosPIP.preferredSize` is used to provide a suggested aspect ratio.\n *\n * @example\n * ```tsx\n * import { startIOSPIP, stopIOSPIP } from '@livekit/react-native-webrtc';\n *\n * // Obtain a ref to the view\n * const videoRef = useRef<Component>(null);\n * const videoView = (\n * <VideoTrack\n * ref={videoRef}\n * iosPIP={{\n * enabled: true,\n * startAutomatically: true,\n * preferredSize: {\n * width: 9,\n * height: 16,\n * },\n * }}\n * ...\n * />\n * );\n *\n * // Start/stop manually\n * startIOSPIP(videoRef);\n * stopIOSPIP(videoRef);\n * ```\n *\n */\n iosPIP?: RTCIOSPIPOptions & {\n preferredSize: {\n width: number;\n height: number;\n };\n fallbackView?: ReactNode;\n };\n};\n\ntype RTCViewInstance = InstanceType<typeof RTCView>;\n\n/**\n * VideoTrack component for displaying video tracks in a React Native application.\n * It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.\n *\n * @param props - See VideoTrackProps for details.\n * @returns A React component that renders the given video track.\n * @public\n */\nexport const VideoTrack = forwardRef<RTCViewInstance, VideoTrackProps>(\n (\n {\n style = {},\n trackRef,\n objectFit = 'cover',\n zOrder,\n mirror,\n iosPIP,\n }: VideoTrackProps,\n ref\n ) => {\n const [elementInfo] = useState(() => {\n let info = new VideoTrackElementInfo();\n info.id = trackRef?.publication?.trackSid;\n return info;\n });\n\n const layoutOnChange = useCallback(\n (event: LayoutChangeEvent) => elementInfo.onLayout(event),\n [elementInfo]\n );\n\n const iosPIPEnabled = iosPIP?.enabled ?? false;\n const visibilityOnChange = useCallback(\n (isVisible: boolean) =>\n elementInfo.onVisibility(isVisible || iosPIPEnabled),\n [elementInfo, iosPIPEnabled]\n );\n\n const videoTrack = trackRef?.publication.track;\n\n const shouldObserveVisibility = useMemo(() => {\n return (\n videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream\n );\n }, [videoTrack]);\n\n const [mediaStream, setMediaStream] = useState(videoTrack?.mediaStream);\n useEffect(() => {\n setMediaStream(videoTrack?.mediaStream);\n if (videoTrack instanceof LocalVideoTrack) {\n const onRestarted = (track: Track | null) => {\n setMediaStream(track?.mediaStream);\n };\n videoTrack.on(TrackEvent.Restarted, onRestarted);\n\n return () => {\n videoTrack.off(TrackEvent.Restarted, onRestarted);\n };\n } else {\n return () => {};\n }\n }, [videoTrack]);\n\n useEffect(() => {\n if (\n videoTrack instanceof RemoteVideoTrack &&\n videoTrack.isAdaptiveStream\n ) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\n\n let videoView;\n if (!iosPIP || Platform.OS !== 'ios') {\n videoView = (\n <RTCView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n // @ts-ignore\n ref={ref}\n />\n );\n } else {\n videoView = (\n <RTCPIPView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n // TODO: fix this up in react-native-webrtc side.\n // @ts-expect-error\n iosPIP={iosPIP}\n ref={ref}\n />\n );\n }\n return (\n <View style={{ ...style, ...styles.container }} onLayout={layoutOnChange}>\n <ViewPortDetector\n onChange={visibilityOnChange}\n style={styles.videoTrack}\n disabled={!shouldObserveVisibility}\n propKey={videoTrack}\n >\n {videoView}\n </ViewPortDetector>\n </View>\n );\n }\n);\n\nconst styles = StyleSheet.create({\n container: {},\n videoTrack: {\n flex: 1,\n width: '100%',\n },\n});\n\nclass VideoTrackElementInfo implements ElementInfo {\n element: object = {};\n something?: any;\n id?: string;\n _width = 0;\n _height = 0;\n _observing = false;\n visible: boolean = true;\n visibilityChangedAt: number | undefined;\n pictureInPicture = false;\n handleResize?: (() => void) | undefined;\n handleVisibilityChanged?: (() => void) | undefined;\n width = () => this._width;\n height = () => this._height;\n\n observe(): void {\n this._observing = true;\n }\n\n stopObserving(): void {\n this._observing = false;\n }\n\n onLayout(event: LayoutChangeEvent) {\n let { width, height } = event.nativeEvent.layout;\n this._width = width;\n this._height = height;\n\n if (this._observing) {\n this.handleResize?.();\n }\n }\n\n onVisibility(isVisible: boolean) {\n if (this.visible !== isVisible) {\n this.visible = isVisible;\n this.visibilityChangedAt = Date.now();\n if (this._observing) {\n this.handleVisibilityChanged?.();\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -127,6 +127,14 @@ export default class AudioSession {
|
|
|
127
127
|
* Stops the existing AudioSession.
|
|
128
128
|
*/
|
|
129
129
|
static stopAudioSession: () => Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Set default audio track volume when new tracks are subscribed.
|
|
132
|
+
* Does **not** affect any existing tracks.
|
|
133
|
+
*
|
|
134
|
+
* @param volume A number between 0.0 and 1.0, where 0.0 represents 0% volume and
|
|
135
|
+
* 1.0 represents full volume.
|
|
136
|
+
*/
|
|
137
|
+
static setDefaultRemoteAudioTrackVolume: (volume: number) => Promise<void>;
|
|
130
138
|
/**
|
|
131
139
|
* Gets the available audio outputs for use with {@link selectAudioOutput}.
|
|
132
140
|
*
|
|
@@ -103,4 +103,4 @@ export type VideoTrackProps = {
|
|
|
103
103
|
* @returns A React component that renders the given video track.
|
|
104
104
|
* @public
|
|
105
105
|
*/
|
|
106
|
-
export declare const VideoTrack: React.ForwardRefExoticComponent<VideoTrackProps & React.RefAttributes<React.Component<
|
|
106
|
+
export declare const VideoTrack: React.ForwardRefExoticComponent<VideoTrackProps & React.RefAttributes<React.Component<import("@livekit/react-native-webrtc").RTCVideoViewProps, {}, any> & Readonly<import("react-native").NativeMethods>>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livekit/react-native",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "LiveKit for React Native",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@babel/preset-env": "^7.20.0",
|
|
58
58
|
"@babel/runtime": "^7.20.0",
|
|
59
59
|
"@commitlint/config-conventional": "^16.2.1",
|
|
60
|
-
"@livekit/react-native-webrtc": "^125.0.
|
|
60
|
+
"@livekit/react-native-webrtc": "^125.0.12",
|
|
61
61
|
"@react-native/babel-preset": "0.74.84",
|
|
62
62
|
"@react-native/eslint-config": "0.74.84",
|
|
63
63
|
"@react-native/metro-config": "0.74.84",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"typescript": "5.0.4"
|
|
85
85
|
},
|
|
86
86
|
"peerDependencies": {
|
|
87
|
-
"@livekit/react-native-webrtc": "^125.0.
|
|
87
|
+
"@livekit/react-native-webrtc": "^125.0.12",
|
|
88
88
|
"livekit-client": "^2.9.0",
|
|
89
89
|
"react": "*",
|
|
90
90
|
"react-native": "*"
|
|
@@ -254,6 +254,17 @@ export default class AudioSession {
|
|
|
254
254
|
await LiveKitModule.stopAudioSession();
|
|
255
255
|
};
|
|
256
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Set default audio track volume when new tracks are subscribed.
|
|
259
|
+
* Does **not** affect any existing tracks.
|
|
260
|
+
*
|
|
261
|
+
* @param volume A number between 0.0 and 1.0, where 0.0 represents 0% volume and
|
|
262
|
+
* 1.0 represents full volume.
|
|
263
|
+
*/
|
|
264
|
+
static setDefaultRemoteAudioTrackVolume = async (volume: number) => {
|
|
265
|
+
await LiveKitModule.setDefaultAudioTrackVolume(volume);
|
|
266
|
+
};
|
|
267
|
+
|
|
257
268
|
/**
|
|
258
269
|
* Gets the available audio outputs for use with {@link selectAudioOutput}.
|
|
259
270
|
*
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
type RTCIOSPIPOptions,
|
|
20
20
|
} from '@livekit/react-native-webrtc';
|
|
21
21
|
import {
|
|
22
|
-
Component,
|
|
23
22
|
forwardRef,
|
|
24
23
|
useCallback,
|
|
25
24
|
useEffect,
|
|
@@ -125,6 +124,8 @@ export type VideoTrackProps = {
|
|
|
125
124
|
};
|
|
126
125
|
};
|
|
127
126
|
|
|
127
|
+
type RTCViewInstance = InstanceType<typeof RTCView>;
|
|
128
|
+
|
|
128
129
|
/**
|
|
129
130
|
* VideoTrack component for displaying video tracks in a React Native application.
|
|
130
131
|
* It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.
|
|
@@ -133,7 +134,7 @@ export type VideoTrackProps = {
|
|
|
133
134
|
* @returns A React component that renders the given video track.
|
|
134
135
|
* @public
|
|
135
136
|
*/
|
|
136
|
-
export const VideoTrack = forwardRef<
|
|
137
|
+
export const VideoTrack = forwardRef<RTCViewInstance, VideoTrackProps>(
|
|
137
138
|
(
|
|
138
139
|
{
|
|
139
140
|
style = {},
|