Expo-Video循环播放引发内存持续升高问题求助
Expo AV Video循环播放内存泄漏问题(SDK 48 / expo-av 13.2.1)
问题描述
在Expo托管的React Native项目中,使用expo-av的Video组件作为屏幕背景,10秒视频循环播放时,每次循环重启都会导致内存占用持续上升——即便视频仅2MB大小,内存仍会无限增长。相关代码如下:
const StyledVideo = styled(Video).attrs({ isMuted: true, usePoster: true, isLooping: true, source: VIDEO_SRC, // require(<LOCAL_ASSET>) posterSource: STATIC_SRC, // require(<LOCAL_ASSET>) resizeMode: ResizeMode.STRETCH, })` ${ratioCss}; `; export const Background: FunctionComponent = () => { const [isVideoReady, setIsVideoReady] = useState<boolean>(false); const screenFocused = useIsFocused(); const reduceMotion = useReducedMotionEnabled(); return ( <CenteringWrapper> <StyledVideo shouldPlay={screenFocused && !reduceMotion && isVideoReady} PosterComponent={({ source }) => <StaticBackground source={source} />} onReadyForDisplay={() => setIsVideoReady(true)} /> </CenteringWrapper> ); };
当前环境:Expo SDK 48,expo-av 13.2.1
解决方案
1. 手动管理视频实例生命周期
组件卸载或屏幕失焦时,主动调用unloadAsync()释放资源,避免循环时残留未释放的视频实例:
export const Background: FunctionComponent = () => { const [isVideoReady, setIsVideoReady] = useState<boolean>(false); const videoRef = useRef<Video>(null); const screenFocused = useIsFocused(); const reduceMotion = useReducedMotionEnabled(); useEffect(() => { // 屏幕失焦时卸载视频,聚焦时重新加载 if (!screenFocused) { videoRef.current?.unloadAsync(); setIsVideoReady(false); } else if (!isVideoReady) { videoRef.current?.loadAsync(VIDEO_SRC); } // 组件卸载时清理资源 return () => { videoRef.current?.unloadAsync(); }; }, [screenFocused, isVideoReady]); return ( <CenteringWrapper> <StyledVideo ref={videoRef} shouldPlay={screenFocused && !reduceMotion && isVideoReady} PosterComponent={({ source }) => <StaticBackground source={source} />} onReadyForDisplay={() => setIsVideoReady(true)} /> </CenteringWrapper> ); };
2. 替换自动循环为手动控制
关闭isLooping,通过播放结束事件手动重置播放位置,绕开组件内部可能的循环内存泄漏逻辑:
const StyledVideo = styled(Video).attrs({ isMuted: true, usePoster: true, isLooping: false, // 关闭自动循环 source: VIDEO_SRC, posterSource: STATIC_SRC, resizeMode: ResizeMode.STRETCH, })` ${ratioCss}; `; export const Background: FunctionComponent = () => { const [isVideoReady, setIsVideoReady] = useState<boolean>(false); const videoRef = useRef<Video>(null); const screenFocused = useIsFocused(); const reduceMotion = useReducedMotionEnabled(); const handlePlaybackStatus = async (status: PlaybackStatus) => { // 播放结束时重置到开头并继续播放 if (status.didJustFinish && !status.isLooping) { await videoRef.current?.seekAsync(0); videoRef.current?.playAsync(); } }; useEffect(() => { return () => { videoRef.current?.unloadAsync(); }; }, []); return ( <CenteringWrapper> <StyledVideo ref={videoRef} shouldPlay={screenFocused && !reduceMotion && isVideoReady} PosterComponent={({ source }) => <StaticBackground source={source} />} onReadyForDisplay={() => setIsVideoReady(true)} onPlaybackStatusUpdate={handlePlaybackStatus} /> </CenteringWrapper> ); };
3. 调整expo-av版本
SDK 48对应的expo-av 13.2.1可能存在循环播放的内存泄漏bug,尝试升级到同SDK兼容的更高版本(如13.3.0),或降级到13.1.0,验证问题是否消失。
4. 优化视频编码
将视频转码为H.264编码的MP4格式,确保分辨率、帧率与设备屏幕匹配,减少解码过程中的内存消耗。
内容的提问来源于stack exchange,提问作者Zając
相关产品推荐
相关产品推荐

