@livekit/react-native 2.4.1 → 2.4.3
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/android/build.gradle +1 -1
- package/lib/commonjs/audio/AudioManager.js +20 -12
- package/lib/commonjs/audio/AudioManager.js.map +1 -1
- package/lib/commonjs/components/VideoTrack.js +13 -0
- package/lib/commonjs/components/VideoTrack.js.map +1 -1
- package/lib/module/audio/AudioManager.js +20 -12
- package/lib/module/audio/AudioManager.js.map +1 -1
- package/lib/module/components/VideoTrack.js +14 -0
- package/lib/module/components/VideoTrack.js.map +1 -1
- package/lib/typescript/lib/commonjs/components/VideoTrack.d.ts +12 -0
- package/lib/typescript/src/components/VideoTrack.d.ts +46 -0
- package/package.json +3 -3
- package/src/audio/AudioManager.ts +30 -18
- package/src/components/VideoTrack.tsx +48 -0
package/android/build.gradle
CHANGED
|
@@ -30,7 +30,7 @@ android {
|
|
|
30
30
|
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
|
|
31
31
|
namespace "com.livekit.reactnative"
|
|
32
32
|
defaultConfig {
|
|
33
|
-
minSdkVersion
|
|
33
|
+
minSdkVersion 24
|
|
34
34
|
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
|
|
35
35
|
versionCode 1
|
|
36
36
|
versionName "1.0"
|
|
@@ -38,23 +38,31 @@ function useIOSAudioManagement(room, preferSpeakerOutput = true, onConfigureNati
|
|
|
38
38
|
if (_reactNative.Platform.OS !== 'ios') {
|
|
39
39
|
return () => {};
|
|
40
40
|
}
|
|
41
|
-
let onLocalPublished =
|
|
42
|
-
|
|
41
|
+
let onLocalPublished = publication => {
|
|
42
|
+
if (publication.kind === 'audio') {
|
|
43
|
+
setLocalTrackCount(localTrackCount + 1);
|
|
44
|
+
}
|
|
43
45
|
};
|
|
44
|
-
let onLocalUnpublished =
|
|
45
|
-
if (
|
|
46
|
-
|
|
46
|
+
let onLocalUnpublished = publication => {
|
|
47
|
+
if (publication.kind === 'audio') {
|
|
48
|
+
if (localTrackCount - 1 < 0) {
|
|
49
|
+
_.log.warn('mismatched local audio track count! attempted to reduce track count below zero.');
|
|
50
|
+
}
|
|
51
|
+
setLocalTrackCount(Math.max(localTrackCount - 1, 0));
|
|
47
52
|
}
|
|
48
|
-
setLocalTrackCount(Math.max(localTrackCount - 1, 0));
|
|
49
53
|
};
|
|
50
|
-
let onRemotePublished =
|
|
51
|
-
|
|
54
|
+
let onRemotePublished = publication => {
|
|
55
|
+
if (publication.kind === 'audio') {
|
|
56
|
+
setRemoteTrackCount(remoteTrackCount + 1);
|
|
57
|
+
}
|
|
52
58
|
};
|
|
53
|
-
let onRemoteUnpublished =
|
|
54
|
-
if (
|
|
55
|
-
|
|
59
|
+
let onRemoteUnpublished = publication => {
|
|
60
|
+
if (publication.kind === 'audio') {
|
|
61
|
+
if (remoteTrackCount - 1 < 0) {
|
|
62
|
+
_.log.warn('mismatched remote audio track count! attempted to reduce track count below zero.');
|
|
63
|
+
}
|
|
64
|
+
setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));
|
|
56
65
|
}
|
|
57
|
-
setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));
|
|
58
66
|
};
|
|
59
67
|
room.on(_livekitClient.RoomEvent.LocalTrackPublished, onLocalPublished).on(_livekitClient.RoomEvent.LocalTrackUnpublished, onLocalUnpublished).on(_livekitClient.RoomEvent.TrackPublished, onRemotePublished).on(_livekitClient.RoomEvent.TrackUnpublished, onRemoteUnpublished);
|
|
60
68
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_reactNative","_livekitClient","_AudioSession","_interopRequireWildcard","_","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","useIOSAudioManagement","room","preferSpeakerOutput","onConfigureNativeAudio","localTrackCount","setLocalTrackCount","useState","remoteTrackCount","setRemoteTrackCount","trackState","useMemo","computeAudioTrackState","useEffect","recalculateTrackCounts","getLocalAudioTrackCount","getRemoteAudioTrackCount","on","RoomEvent","Connected","off","Platform","OS","onLocalPublished","onLocalUnpublished","log","warn","Math","max","onRemotePublished","onRemoteUnpublished","LocalTrackPublished","LocalTrackUnpublished","TrackPublished","TrackUnpublished","configFunc","getDefaultAppleAudioConfigurationForMode","audioConfig","AudioSession","setAppleAudioConfiguration","localTracks","remoteTracks","localParticipant","audioTrackPublications","size","audioTracks","remoteParticipants","forEach","participant"],"sources":["AudioManager.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { Platform } from 'react-native';\nimport {
|
|
1
|
+
{"version":3,"names":["_react","require","_reactNative","_livekitClient","_AudioSession","_interopRequireWildcard","_","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","useIOSAudioManagement","room","preferSpeakerOutput","onConfigureNativeAudio","localTrackCount","setLocalTrackCount","useState","remoteTrackCount","setRemoteTrackCount","trackState","useMemo","computeAudioTrackState","useEffect","recalculateTrackCounts","getLocalAudioTrackCount","getRemoteAudioTrackCount","on","RoomEvent","Connected","off","Platform","OS","onLocalPublished","publication","kind","onLocalUnpublished","log","warn","Math","max","onRemotePublished","onRemoteUnpublished","LocalTrackPublished","LocalTrackUnpublished","TrackPublished","TrackUnpublished","configFunc","getDefaultAppleAudioConfigurationForMode","audioConfig","AudioSession","setAppleAudioConfiguration","localTracks","remoteTracks","localParticipant","audioTrackPublications","size","audioTracks","remoteParticipants","forEach","participant"],"sources":["AudioManager.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { Platform } from 'react-native';\nimport {\n RoomEvent,\n Room,\n type LocalTrackPublication,\n type RemoteTrackPublication,\n} from 'livekit-client';\nimport AudioSession, {\n getDefaultAppleAudioConfigurationForMode,\n type AppleAudioConfiguration,\n type AudioTrackState,\n} from './AudioSession';\nimport { log } from '..';\n\n/**\n * Handles setting the appropriate AVAudioSession options automatically\n * depending on the audio track states of the Room.\n *\n * @param room\n * @param preferSpeakerOutput\n * @param onConfigureNativeAudio A custom method for determining options used.\n */\nexport function useIOSAudioManagement(\n room: Room,\n preferSpeakerOutput: boolean = true,\n onConfigureNativeAudio?: (\n trackState: AudioTrackState,\n preferSpeakerOutput: boolean\n ) => AppleAudioConfiguration\n) {\n const [localTrackCount, setLocalTrackCount] = useState(0);\n const [remoteTrackCount, setRemoteTrackCount] = useState(0);\n const trackState = useMemo(\n () => computeAudioTrackState(localTrackCount, remoteTrackCount),\n [localTrackCount, remoteTrackCount]\n );\n\n useEffect(() => {\n let recalculateTrackCounts = () => {\n setLocalTrackCount(getLocalAudioTrackCount(room));\n setRemoteTrackCount(getRemoteAudioTrackCount(room));\n };\n\n recalculateTrackCounts();\n\n room.on(RoomEvent.Connected, recalculateTrackCounts);\n\n return () => {\n room.off(RoomEvent.Connected, recalculateTrackCounts);\n };\n }, [room]);\n useEffect(() => {\n if (Platform.OS !== 'ios') {\n return () => {};\n }\n\n let onLocalPublished = (publication: LocalTrackPublication) => {\n if (publication.kind === 'audio') {\n setLocalTrackCount(localTrackCount + 1);\n }\n };\n let onLocalUnpublished = (publication: LocalTrackPublication) => {\n if (publication.kind === 'audio') {\n if (localTrackCount - 1 < 0) {\n log.warn(\n 'mismatched local audio track count! attempted to reduce track count below zero.'\n );\n }\n setLocalTrackCount(Math.max(localTrackCount - 1, 0));\n }\n };\n let onRemotePublished = (publication: RemoteTrackPublication) => {\n if (publication.kind === 'audio') {\n setRemoteTrackCount(remoteTrackCount + 1);\n }\n };\n let onRemoteUnpublished = (publication: RemoteTrackPublication) => {\n if (publication.kind === 'audio') {\n if (remoteTrackCount - 1 < 0) {\n log.warn(\n 'mismatched remote audio track count! attempted to reduce track count below zero.'\n );\n }\n setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));\n }\n };\n\n room\n .on(RoomEvent.LocalTrackPublished, onLocalPublished)\n .on(RoomEvent.LocalTrackUnpublished, onLocalUnpublished)\n .on(RoomEvent.TrackPublished, onRemotePublished)\n .on(RoomEvent.TrackUnpublished, onRemoteUnpublished);\n\n return () => {\n room\n .off(RoomEvent.LocalTrackPublished, onLocalPublished)\n .off(RoomEvent.LocalTrackUnpublished, onLocalUnpublished)\n .off(RoomEvent.TrackPublished, onRemotePublished)\n .off(RoomEvent.TrackUnpublished, onRemoteUnpublished);\n };\n }, [room, localTrackCount, remoteTrackCount]);\n\n useEffect(() => {\n if (Platform.OS !== 'ios') {\n return;\n }\n\n let configFunc =\n onConfigureNativeAudio ?? getDefaultAppleAudioConfigurationForMode;\n let audioConfig = configFunc(trackState, preferSpeakerOutput);\n AudioSession.setAppleAudioConfiguration(audioConfig);\n }, [trackState, onConfigureNativeAudio, preferSpeakerOutput]);\n}\n\nfunction computeAudioTrackState(\n localTracks: number,\n remoteTracks: number\n): AudioTrackState {\n if (localTracks > 0 && remoteTracks > 0) {\n return 'localAndRemote';\n } else if (localTracks > 0 && remoteTracks === 0) {\n return 'localOnly';\n } else if (localTracks === 0 && remoteTracks > 0) {\n return 'remoteOnly';\n } else {\n return 'none';\n }\n}\n\nfunction getLocalAudioTrackCount(room: Room): number {\n return room.localParticipant.audioTrackPublications.size;\n}\n\nfunction getRemoteAudioTrackCount(room: Room): number {\n var audioTracks = 0;\n room.remoteParticipants.forEach((participant) => {\n audioTracks += participant.audioTrackPublications.size;\n });\n return audioTracks;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -16,6 +16,19 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
16
16
|
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; }
|
|
17
17
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
18
18
|
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); }
|
|
19
|
+
/**
|
|
20
|
+
* Props for the VideoTrack component.
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* VideoTrack component for displaying video tracks in a React Native application.
|
|
26
|
+
* It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.
|
|
27
|
+
*
|
|
28
|
+
* @param props - See VideoTrackProps for details.
|
|
29
|
+
* @returns A React component that renders the given video track.
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
19
32
|
const VideoTrack = ({
|
|
20
33
|
style = {},
|
|
21
34
|
trackRef,
|
|
@@ -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","style","trackRef","objectFit","zOrder","mirror","elementInfo","useState","_trackRef$publication","info","VideoTrackElementInfo","id","publication","trackSid","layoutOnChange","useCallback","event","onLayout","visibilityOnChange","isVisible","onVisibility","videoTrack","track","shouldObserveVisibility","useMemo","RemoteVideoTrack","isAdaptiveStream","mediaStream","setMediaStream","useEffect","LocalVideoTrack","onRestarted","on","TrackEvent","Restarted","off","observeElementInfo","stopObservingElementInfo","createElement","View","styles","container","onChange","disabled","propKey","RTCView","streamURL","toURL","exports","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 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 { RTCView } from '@livekit/react-native-webrtc';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { RemoteVideoTrack } from 'livekit-client';\nimport ViewPortDetector from './ViewPortDetector';\nimport type { TrackReference } from '@livekit/components-react';\n\nexport type VideoTrackProps = {\n trackRef: TrackReference | undefined;\n style?: ViewStyle;\n objectFit?: 'cover' | 'contain' | undefined;\n mirror?: boolean;\n zOrder?: number;\n};\n\nexport const VideoTrack = ({\n style = {},\n trackRef,\n objectFit = 'cover',\n zOrder,\n mirror,\n}: VideoTrackProps) => {\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 const visibilityOnChange = useCallback(\n (isVisible: boolean) => elementInfo.onVisibility(isVisible),\n [elementInfo]\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 (videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\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 <RTCView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n />\n </ViewPortDetector>\n </View>\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 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 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","style","trackRef","objectFit","zOrder","mirror","elementInfo","useState","_trackRef$publication","info","VideoTrackElementInfo","id","publication","trackSid","layoutOnChange","useCallback","event","onLayout","visibilityOnChange","isVisible","onVisibility","videoTrack","track","shouldObserveVisibility","useMemo","RemoteVideoTrack","isAdaptiveStream","mediaStream","setMediaStream","useEffect","LocalVideoTrack","onRestarted","on","TrackEvent","Restarted","off","observeElementInfo","stopObservingElementInfo","createElement","View","styles","container","onChange","disabled","propKey","RTCView","streamURL","toURL","exports","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 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 { RTCView } from '@livekit/react-native-webrtc';\nimport { useCallback, useEffect, useMemo, useState } 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/**\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 = ({\n style = {},\n trackRef,\n objectFit = 'cover',\n zOrder,\n mirror,\n}: VideoTrackProps) => {\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 const visibilityOnChange = useCallback(\n (isVisible: boolean) => elementInfo.onVisibility(isVisible),\n [elementInfo]\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 (videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\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 <RTCView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n />\n </ViewPortDetector>\n </View>\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":[]}
|
|
@@ -31,23 +31,31 @@ export function useIOSAudioManagement(room, preferSpeakerOutput = true, onConfig
|
|
|
31
31
|
if (Platform.OS !== 'ios') {
|
|
32
32
|
return () => {};
|
|
33
33
|
}
|
|
34
|
-
let onLocalPublished =
|
|
35
|
-
|
|
34
|
+
let onLocalPublished = publication => {
|
|
35
|
+
if (publication.kind === 'audio') {
|
|
36
|
+
setLocalTrackCount(localTrackCount + 1);
|
|
37
|
+
}
|
|
36
38
|
};
|
|
37
|
-
let onLocalUnpublished =
|
|
38
|
-
if (
|
|
39
|
-
|
|
39
|
+
let onLocalUnpublished = publication => {
|
|
40
|
+
if (publication.kind === 'audio') {
|
|
41
|
+
if (localTrackCount - 1 < 0) {
|
|
42
|
+
log.warn('mismatched local audio track count! attempted to reduce track count below zero.');
|
|
43
|
+
}
|
|
44
|
+
setLocalTrackCount(Math.max(localTrackCount - 1, 0));
|
|
40
45
|
}
|
|
41
|
-
setLocalTrackCount(Math.max(localTrackCount - 1, 0));
|
|
42
46
|
};
|
|
43
|
-
let onRemotePublished =
|
|
44
|
-
|
|
47
|
+
let onRemotePublished = publication => {
|
|
48
|
+
if (publication.kind === 'audio') {
|
|
49
|
+
setRemoteTrackCount(remoteTrackCount + 1);
|
|
50
|
+
}
|
|
45
51
|
};
|
|
46
|
-
let onRemoteUnpublished =
|
|
47
|
-
if (
|
|
48
|
-
|
|
52
|
+
let onRemoteUnpublished = publication => {
|
|
53
|
+
if (publication.kind === 'audio') {
|
|
54
|
+
if (remoteTrackCount - 1 < 0) {
|
|
55
|
+
log.warn('mismatched remote audio track count! attempted to reduce track count below zero.');
|
|
56
|
+
}
|
|
57
|
+
setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));
|
|
49
58
|
}
|
|
50
|
-
setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));
|
|
51
59
|
};
|
|
52
60
|
room.on(RoomEvent.LocalTrackPublished, onLocalPublished).on(RoomEvent.LocalTrackUnpublished, onLocalUnpublished).on(RoomEvent.TrackPublished, onRemotePublished).on(RoomEvent.TrackUnpublished, onRemoteUnpublished);
|
|
53
61
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useState","useEffect","useMemo","Platform","RoomEvent","AudioSession","getDefaultAppleAudioConfigurationForMode","log","useIOSAudioManagement","room","preferSpeakerOutput","onConfigureNativeAudio","localTrackCount","setLocalTrackCount","remoteTrackCount","setRemoteTrackCount","trackState","computeAudioTrackState","recalculateTrackCounts","getLocalAudioTrackCount","getRemoteAudioTrackCount","on","Connected","off","OS","onLocalPublished","onLocalUnpublished","warn","Math","max","onRemotePublished","onRemoteUnpublished","LocalTrackPublished","LocalTrackUnpublished","TrackPublished","TrackUnpublished","configFunc","audioConfig","setAppleAudioConfiguration","localTracks","remoteTracks","localParticipant","audioTrackPublications","size","audioTracks","remoteParticipants","forEach","participant"],"sources":["AudioManager.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { Platform } from 'react-native';\nimport {
|
|
1
|
+
{"version":3,"names":["useState","useEffect","useMemo","Platform","RoomEvent","AudioSession","getDefaultAppleAudioConfigurationForMode","log","useIOSAudioManagement","room","preferSpeakerOutput","onConfigureNativeAudio","localTrackCount","setLocalTrackCount","remoteTrackCount","setRemoteTrackCount","trackState","computeAudioTrackState","recalculateTrackCounts","getLocalAudioTrackCount","getRemoteAudioTrackCount","on","Connected","off","OS","onLocalPublished","publication","kind","onLocalUnpublished","warn","Math","max","onRemotePublished","onRemoteUnpublished","LocalTrackPublished","LocalTrackUnpublished","TrackPublished","TrackUnpublished","configFunc","audioConfig","setAppleAudioConfiguration","localTracks","remoteTracks","localParticipant","audioTrackPublications","size","audioTracks","remoteParticipants","forEach","participant"],"sources":["AudioManager.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { Platform } from 'react-native';\nimport {\n RoomEvent,\n Room,\n type LocalTrackPublication,\n type RemoteTrackPublication,\n} from 'livekit-client';\nimport AudioSession, {\n getDefaultAppleAudioConfigurationForMode,\n type AppleAudioConfiguration,\n type AudioTrackState,\n} from './AudioSession';\nimport { log } from '..';\n\n/**\n * Handles setting the appropriate AVAudioSession options automatically\n * depending on the audio track states of the Room.\n *\n * @param room\n * @param preferSpeakerOutput\n * @param onConfigureNativeAudio A custom method for determining options used.\n */\nexport function useIOSAudioManagement(\n room: Room,\n preferSpeakerOutput: boolean = true,\n onConfigureNativeAudio?: (\n trackState: AudioTrackState,\n preferSpeakerOutput: boolean\n ) => AppleAudioConfiguration\n) {\n const [localTrackCount, setLocalTrackCount] = useState(0);\n const [remoteTrackCount, setRemoteTrackCount] = useState(0);\n const trackState = useMemo(\n () => computeAudioTrackState(localTrackCount, remoteTrackCount),\n [localTrackCount, remoteTrackCount]\n );\n\n useEffect(() => {\n let recalculateTrackCounts = () => {\n setLocalTrackCount(getLocalAudioTrackCount(room));\n setRemoteTrackCount(getRemoteAudioTrackCount(room));\n };\n\n recalculateTrackCounts();\n\n room.on(RoomEvent.Connected, recalculateTrackCounts);\n\n return () => {\n room.off(RoomEvent.Connected, recalculateTrackCounts);\n };\n }, [room]);\n useEffect(() => {\n if (Platform.OS !== 'ios') {\n return () => {};\n }\n\n let onLocalPublished = (publication: LocalTrackPublication) => {\n if (publication.kind === 'audio') {\n setLocalTrackCount(localTrackCount + 1);\n }\n };\n let onLocalUnpublished = (publication: LocalTrackPublication) => {\n if (publication.kind === 'audio') {\n if (localTrackCount - 1 < 0) {\n log.warn(\n 'mismatched local audio track count! attempted to reduce track count below zero.'\n );\n }\n setLocalTrackCount(Math.max(localTrackCount - 1, 0));\n }\n };\n let onRemotePublished = (publication: RemoteTrackPublication) => {\n if (publication.kind === 'audio') {\n setRemoteTrackCount(remoteTrackCount + 1);\n }\n };\n let onRemoteUnpublished = (publication: RemoteTrackPublication) => {\n if (publication.kind === 'audio') {\n if (remoteTrackCount - 1 < 0) {\n log.warn(\n 'mismatched remote audio track count! attempted to reduce track count below zero.'\n );\n }\n setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));\n }\n };\n\n room\n .on(RoomEvent.LocalTrackPublished, onLocalPublished)\n .on(RoomEvent.LocalTrackUnpublished, onLocalUnpublished)\n .on(RoomEvent.TrackPublished, onRemotePublished)\n .on(RoomEvent.TrackUnpublished, onRemoteUnpublished);\n\n return () => {\n room\n .off(RoomEvent.LocalTrackPublished, onLocalPublished)\n .off(RoomEvent.LocalTrackUnpublished, onLocalUnpublished)\n .off(RoomEvent.TrackPublished, onRemotePublished)\n .off(RoomEvent.TrackUnpublished, onRemoteUnpublished);\n };\n }, [room, localTrackCount, remoteTrackCount]);\n\n useEffect(() => {\n if (Platform.OS !== 'ios') {\n return;\n }\n\n let configFunc =\n onConfigureNativeAudio ?? getDefaultAppleAudioConfigurationForMode;\n let audioConfig = configFunc(trackState, preferSpeakerOutput);\n AudioSession.setAppleAudioConfiguration(audioConfig);\n }, [trackState, onConfigureNativeAudio, preferSpeakerOutput]);\n}\n\nfunction computeAudioTrackState(\n localTracks: number,\n remoteTracks: number\n): AudioTrackState {\n if (localTracks > 0 && remoteTracks > 0) {\n return 'localAndRemote';\n } else if (localTracks > 0 && remoteTracks === 0) {\n return 'localOnly';\n } else if (localTracks === 0 && remoteTracks > 0) {\n return 'remoteOnly';\n } else {\n return 'none';\n }\n}\n\nfunction getLocalAudioTrackCount(room: Room): number {\n return room.localParticipant.audioTrackPublications.size;\n}\n\nfunction getRemoteAudioTrackCount(room: Room): number {\n var audioTracks = 0;\n room.remoteParticipants.forEach((participant) => {\n audioTracks += participant.audioTrackPublications.size;\n });\n return audioTracks;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -8,6 +8,20 @@ import { RTCView } from '@livekit/react-native-webrtc';
|
|
|
8
8
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
9
9
|
import { RemoteVideoTrack } from 'livekit-client';
|
|
10
10
|
import ViewPortDetector from './ViewPortDetector';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Props for the VideoTrack component.
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* VideoTrack component for displaying video tracks in a React Native application.
|
|
19
|
+
* It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.
|
|
20
|
+
*
|
|
21
|
+
* @param props - See VideoTrackProps for details.
|
|
22
|
+
* @returns A React component that renders the given video track.
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
11
25
|
export const VideoTrack = ({
|
|
12
26
|
style = {},
|
|
13
27
|
trackRef,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","StyleSheet","View","LocalVideoTrack","TrackEvent","RTCView","useCallback","useEffect","useMemo","useState","RemoteVideoTrack","ViewPortDetector","VideoTrack","style","trackRef","objectFit","zOrder","mirror","elementInfo","_trackRef$publication","info","VideoTrackElementInfo","id","publication","trackSid","layoutOnChange","event","onLayout","visibilityOnChange","isVisible","onVisibility","videoTrack","track","shouldObserveVisibility","isAdaptiveStream","mediaStream","setMediaStream","onRestarted","on","Restarted","off","observeElementInfo","stopObservingElementInfo","createElement","styles","container","onChange","disabled","propKey","streamURL","toURL","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 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 { RTCView } from '@livekit/react-native-webrtc';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { RemoteVideoTrack } from 'livekit-client';\nimport ViewPortDetector from './ViewPortDetector';\nimport type { TrackReference } from '@livekit/components-react';\n\nexport type VideoTrackProps = {\n trackRef: TrackReference | undefined;\n style?: ViewStyle;\n objectFit?: 'cover' | 'contain' | undefined;\n mirror?: boolean;\n zOrder?: number;\n};\n\nexport const VideoTrack = ({\n style = {},\n trackRef,\n objectFit = 'cover',\n zOrder,\n mirror,\n}: VideoTrackProps) => {\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 const visibilityOnChange = useCallback(\n (isVisible: boolean) => elementInfo.onVisibility(isVisible),\n [elementInfo]\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 (videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\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 <RTCView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n />\n </ViewPortDetector>\n </View>\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 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 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","StyleSheet","View","LocalVideoTrack","TrackEvent","RTCView","useCallback","useEffect","useMemo","useState","RemoteVideoTrack","ViewPortDetector","VideoTrack","style","trackRef","objectFit","zOrder","mirror","elementInfo","_trackRef$publication","info","VideoTrackElementInfo","id","publication","trackSid","layoutOnChange","event","onLayout","visibilityOnChange","isVisible","onVisibility","videoTrack","track","shouldObserveVisibility","isAdaptiveStream","mediaStream","setMediaStream","onRestarted","on","Restarted","off","observeElementInfo","stopObservingElementInfo","createElement","styles","container","onChange","disabled","propKey","streamURL","toURL","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 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 { RTCView } from '@livekit/react-native-webrtc';\nimport { useCallback, useEffect, useMemo, useState } 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/**\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 = ({\n style = {},\n trackRef,\n objectFit = 'cover',\n zOrder,\n mirror,\n}: VideoTrackProps) => {\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 const visibilityOnChange = useCallback(\n (isVisible: boolean) => elementInfo.onVisibility(isVisible),\n [elementInfo]\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 (videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\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 <RTCView\n style={styles.videoTrack}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n />\n </ViewPortDetector>\n </View>\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,4 +1,16 @@
|
|
|
1
1
|
export const __esModule: boolean;
|
|
2
|
+
/**
|
|
3
|
+
* Props for the VideoTrack component.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* VideoTrack component for displaying video tracks in a React Native application.
|
|
8
|
+
* It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.
|
|
9
|
+
*
|
|
10
|
+
* @param props - See VideoTrackProps for details.
|
|
11
|
+
* @returns A React component that renders the given video track.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
2
14
|
export function VideoTrack({ style, trackRef, objectFit, zOrder, mirror }: {
|
|
3
15
|
style?: {} | undefined;
|
|
4
16
|
trackRef: any;
|
|
@@ -1,11 +1,57 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { type ViewStyle } from 'react-native';
|
|
3
3
|
import type { TrackReference } from '@livekit/components-react';
|
|
4
|
+
/**
|
|
5
|
+
* Props for the VideoTrack component.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
4
8
|
export type VideoTrackProps = {
|
|
9
|
+
/**
|
|
10
|
+
* The track reference to display. This should be a TrackReference object
|
|
11
|
+
* or undefined if no track is available.
|
|
12
|
+
*/
|
|
5
13
|
trackRef: TrackReference | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Custom React Native styles for the video container.
|
|
16
|
+
*/
|
|
6
17
|
style?: ViewStyle;
|
|
18
|
+
/**
|
|
19
|
+
* Specifies how the video content should be resized to fit its container.
|
|
20
|
+
* 'cover' (default): The video will fill the entire container, potentially cropping the video.
|
|
21
|
+
* 'contain': The entire video will be visible within the container, potentially leaving empty space.
|
|
22
|
+
*/
|
|
7
23
|
objectFit?: 'cover' | 'contain' | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Indicates whether the video should be mirrored during rendering.
|
|
26
|
+
* This is commonly used for front-facing cameras.
|
|
27
|
+
*/
|
|
8
28
|
mirror?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Specifies the depth-stacking order of this video view in the stacking space of all video views.
|
|
31
|
+
* A larger zOrder value generally causes the view to cover those with lower values.
|
|
32
|
+
*
|
|
33
|
+
* The support for zOrder is platform-dependent and/or
|
|
34
|
+
* implementation-specific. Thus, specifying a value for zOrder is to be
|
|
35
|
+
* thought of as giving a hint rather than as imposing a requirement. For
|
|
36
|
+
* example, video renderers such as RTCView are commonly implemented using
|
|
37
|
+
* OpenGL and OpenGL views may have different numbers of layers in their
|
|
38
|
+
* stacking space. Android has three: a layer bellow the window (aka
|
|
39
|
+
* default), a layer bellow the window again but above the previous layer
|
|
40
|
+
* (aka media overlay), and above the window. Consequently, it is advisable
|
|
41
|
+
* to limit the number of utilized layers in the stacking space to the
|
|
42
|
+
* minimum sufficient for the desired display. For example, a video call
|
|
43
|
+
* application usually needs a maximum of two zOrder values: 0 for the
|
|
44
|
+
* remote video(s) which appear in the background, and 1 for the local
|
|
45
|
+
* video(s) which appear above the remote video(s).
|
|
46
|
+
*/
|
|
9
47
|
zOrder?: number;
|
|
10
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* VideoTrack component for displaying video tracks in a React Native application.
|
|
51
|
+
* It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.
|
|
52
|
+
*
|
|
53
|
+
* @param props - See VideoTrackProps for details.
|
|
54
|
+
* @returns A React component that renders the given video track.
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
11
57
|
export declare const VideoTrack: ({ style, trackRef, objectFit, zOrder, mirror, }: VideoTrackProps) => React.JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livekit/react-native",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.3",
|
|
4
4
|
"description": "LiveKit for React Native",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@babel/preset-env": "^7.20.0",
|
|
56
56
|
"@babel/runtime": "^7.20.0",
|
|
57
57
|
"@commitlint/config-conventional": "^16.2.1",
|
|
58
|
-
"@livekit/react-native-webrtc": "^125.0.
|
|
58
|
+
"@livekit/react-native-webrtc": "^125.0.5",
|
|
59
59
|
"@react-native/babel-preset": "0.74.84",
|
|
60
60
|
"@react-native/eslint-config": "0.74.84",
|
|
61
61
|
"@react-native/metro-config": "0.74.84",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"typescript": "5.0.4"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
|
-
"@livekit/react-native-webrtc": "^125.0.
|
|
84
|
+
"@livekit/react-native-webrtc": "^125.0.5",
|
|
85
85
|
"react": "*",
|
|
86
86
|
"react-native": "*"
|
|
87
87
|
},
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { useState, useEffect, useMemo } from 'react';
|
|
2
2
|
import { Platform } from 'react-native';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
RoomEvent,
|
|
5
|
+
Room,
|
|
6
|
+
type LocalTrackPublication,
|
|
7
|
+
type RemoteTrackPublication,
|
|
8
|
+
} from 'livekit-client';
|
|
4
9
|
import AudioSession, {
|
|
5
10
|
getDefaultAppleAudioConfigurationForMode,
|
|
6
11
|
type AppleAudioConfiguration,
|
|
@@ -50,27 +55,35 @@ export function useIOSAudioManagement(
|
|
|
50
55
|
return () => {};
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
let onLocalPublished = () => {
|
|
54
|
-
|
|
58
|
+
let onLocalPublished = (publication: LocalTrackPublication) => {
|
|
59
|
+
if (publication.kind === 'audio') {
|
|
60
|
+
setLocalTrackCount(localTrackCount + 1);
|
|
61
|
+
}
|
|
55
62
|
};
|
|
56
|
-
let onLocalUnpublished = () => {
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
let onLocalUnpublished = (publication: LocalTrackPublication) => {
|
|
64
|
+
if (publication.kind === 'audio') {
|
|
65
|
+
if (localTrackCount - 1 < 0) {
|
|
66
|
+
log.warn(
|
|
67
|
+
'mismatched local audio track count! attempted to reduce track count below zero.'
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
setLocalTrackCount(Math.max(localTrackCount - 1, 0));
|
|
61
71
|
}
|
|
62
|
-
setLocalTrackCount(Math.max(localTrackCount - 1, 0));
|
|
63
72
|
};
|
|
64
|
-
let onRemotePublished = () => {
|
|
65
|
-
|
|
73
|
+
let onRemotePublished = (publication: RemoteTrackPublication) => {
|
|
74
|
+
if (publication.kind === 'audio') {
|
|
75
|
+
setRemoteTrackCount(remoteTrackCount + 1);
|
|
76
|
+
}
|
|
66
77
|
};
|
|
67
|
-
let onRemoteUnpublished = () => {
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
let onRemoteUnpublished = (publication: RemoteTrackPublication) => {
|
|
79
|
+
if (publication.kind === 'audio') {
|
|
80
|
+
if (remoteTrackCount - 1 < 0) {
|
|
81
|
+
log.warn(
|
|
82
|
+
'mismatched remote audio track count! attempted to reduce track count below zero.'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));
|
|
72
86
|
}
|
|
73
|
-
setRemoteTrackCount(Math.max(remoteTrackCount - 1, 0));
|
|
74
87
|
};
|
|
75
88
|
|
|
76
89
|
room
|
|
@@ -124,6 +137,5 @@ function getRemoteAudioTrackCount(room: Room): number {
|
|
|
124
137
|
room.remoteParticipants.forEach((participant) => {
|
|
125
138
|
audioTracks += participant.audioTrackPublications.size;
|
|
126
139
|
});
|
|
127
|
-
|
|
128
140
|
return audioTracks;
|
|
129
141
|
}
|
|
@@ -18,14 +18,60 @@ import { RemoteVideoTrack } from 'livekit-client';
|
|
|
18
18
|
import ViewPortDetector from './ViewPortDetector';
|
|
19
19
|
import type { TrackReference } from '@livekit/components-react';
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Props for the VideoTrack component.
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
21
25
|
export type VideoTrackProps = {
|
|
26
|
+
/**
|
|
27
|
+
* The track reference to display. This should be a TrackReference object
|
|
28
|
+
* or undefined if no track is available.
|
|
29
|
+
*/
|
|
22
30
|
trackRef: TrackReference | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Custom React Native styles for the video container.
|
|
33
|
+
*/
|
|
23
34
|
style?: ViewStyle;
|
|
35
|
+
/**
|
|
36
|
+
* Specifies how the video content should be resized to fit its container.
|
|
37
|
+
* 'cover' (default): The video will fill the entire container, potentially cropping the video.
|
|
38
|
+
* 'contain': The entire video will be visible within the container, potentially leaving empty space.
|
|
39
|
+
*/
|
|
24
40
|
objectFit?: 'cover' | 'contain' | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Indicates whether the video should be mirrored during rendering.
|
|
43
|
+
* This is commonly used for front-facing cameras.
|
|
44
|
+
*/
|
|
25
45
|
mirror?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Specifies the depth-stacking order of this video view in the stacking space of all video views.
|
|
48
|
+
* A larger zOrder value generally causes the view to cover those with lower values.
|
|
49
|
+
*
|
|
50
|
+
* The support for zOrder is platform-dependent and/or
|
|
51
|
+
* implementation-specific. Thus, specifying a value for zOrder is to be
|
|
52
|
+
* thought of as giving a hint rather than as imposing a requirement. For
|
|
53
|
+
* example, video renderers such as RTCView are commonly implemented using
|
|
54
|
+
* OpenGL and OpenGL views may have different numbers of layers in their
|
|
55
|
+
* stacking space. Android has three: a layer bellow the window (aka
|
|
56
|
+
* default), a layer bellow the window again but above the previous layer
|
|
57
|
+
* (aka media overlay), and above the window. Consequently, it is advisable
|
|
58
|
+
* to limit the number of utilized layers in the stacking space to the
|
|
59
|
+
* minimum sufficient for the desired display. For example, a video call
|
|
60
|
+
* application usually needs a maximum of two zOrder values: 0 for the
|
|
61
|
+
* remote video(s) which appear in the background, and 1 for the local
|
|
62
|
+
* video(s) which appear above the remote video(s).
|
|
63
|
+
*/
|
|
26
64
|
zOrder?: number;
|
|
27
65
|
};
|
|
28
66
|
|
|
67
|
+
/**
|
|
68
|
+
* VideoTrack component for displaying video tracks in a React Native application.
|
|
69
|
+
* It supports both local and remote video tracks from LiveKit, and handles adaptive streaming for remote tracks.
|
|
70
|
+
*
|
|
71
|
+
* @param props - See VideoTrackProps for details.
|
|
72
|
+
* @returns A React component that renders the given video track.
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
29
75
|
export const VideoTrack = ({
|
|
30
76
|
style = {},
|
|
31
77
|
trackRef,
|
|
@@ -130,6 +176,7 @@ class VideoTrackElementInfo implements ElementInfo {
|
|
|
130
176
|
observe(): void {
|
|
131
177
|
this._observing = true;
|
|
132
178
|
}
|
|
179
|
+
|
|
133
180
|
stopObserving(): void {
|
|
134
181
|
this._observing = false;
|
|
135
182
|
}
|
|
@@ -143,6 +190,7 @@ class VideoTrackElementInfo implements ElementInfo {
|
|
|
143
190
|
this.handleResize?.();
|
|
144
191
|
}
|
|
145
192
|
}
|
|
193
|
+
|
|
146
194
|
onVisibility(isVisible: boolean) {
|
|
147
195
|
if (this.visible !== isVisible) {
|
|
148
196
|
this.visible = isVisible;
|