如何在 React Native 中高效缓存视频并使用 expo-av 播放

本文详解在裸 React Native 项目中结合 react-native-fs 与 expo-av 实现视频本地缓存与播放的完整方案,重点解决路径格式错误、URI 协议兼容性及缓存策略优化问题,并提供可直接运行的代码示例。 本文详解在裸 react native 项目中结合 `react-native-fs` 与 `expo-av` 实现视频本地缓存与播放的完整方案,重点解决路径格式错误、uri 协议兼容性及缓存策略优化问题,并提供可直接运行的代码示例。在 React Native 中缓存视频并非简单"下载 + 播放",尤其当使用 expo-av(而非 react-native-video)时,文件路径协议、权限配置和 URI 格式要求更为严格。你遇到的"路径不工作"问题,根本原因在于:expo-av 要求传入 source.uri 的必须是 合法的 file:// 协议 URI,而你当前拼接的 {cachePath}/{filename} 仅是原生文件系统路径(如 /Users/.../video.mp4),缺少 file:// 前缀,且未做平台适配处理。? 正确做法是:使用 react-native-fs 下载视频后,通过 RNFS.fileURL()(iOS)或 RNFS.pathToUrl()(Android)生成标准 file URI,再传给 expo-av/Video 组件。以下是经过验证的完整实现:import React, { useState, useEffect } from 'react';import { View } from 'react-native';import * as RNFS from 'react-native-fs';import { Video } from 'expo-av';const App = ({ videoUrl }: { videoUrl: string }) => { const [cachedUri, setCachedUri] = useState<string | null>(null); useEffect(() => { downloadAndCacheVideo(); }, []); const downloadAndCacheVideo = async () => { try { const filename = videoUrl.substring(videoUrl.lastIndexOf('/') + 1); const cachePath = RNFS.DocumentDirectoryPath; const localPath = `{cachePath}/{filename}`; // ? 检查文件是否存在(推荐用 stat 替代 exists,更可靠) const stat = await RNFS.stat(localPath).catch(() => null); if (stat && stat.isFile()) { console.log('? Video already cached:', localPath); // ? 生成跨平台 file:// URI const fileUri = Platform.OS === 'ios' ? `file://{localPath}\` : RNFS.pathToUrl(localPath); // Android requires pathToUrl setCachedUri(fileUri); return; } // ? 下载视频(注意:fetch + blob 在某些 RN 版本存在兼容性问题,推荐用 RNFS.downloadFile) console.log('?? Downloading video...'); const downloadRes = await RNFS.downloadFile({ fromUrl: videoUrl, toFile: localPath, progress: (data) =\> { console.log(\`Download progress: {Math.round(data.bytesWritten / data.contentLength * 100)}%`); } }).promise; if (downloadRes.statusCode === 200) { const fileUri = Platform.OS === 'ios' ? `file://{localPath}\` : RNFS.pathToUrl(localPath); setCachedUri(fileUri); console.log('? Cached video URI:', fileUri); } else { throw new Error(\`Download failed: {downloadRes.statusCode}`); } } catch (err) { console.error('? Cache failed:', err); } }; return ( <View style={{ flex: 1 }}> {cachedUri ? ( <Video source={{ uri: cachedUri }} resizeMode="cover" shouldPlay isMuted={false} useNativeControls style={{ width: '100%', height: 300 }} /> ) : ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Loading cached video...</Text> </View> )} </View> );};export default App;? 关键注意事项与最佳实践: 稿定AI 拥有线稿上色优化、图片重绘、人物姿势检测、涂鸦完善等功能

相关推荐
彳亍1011 小时前
如何排查Oracle客户端连接慢_DNS解析超时与sqlnet配置优化
jvm·数据库·python
m0_609160491 小时前
mysql表锁监控命令_诊断MyISAM表锁定问题的方法
jvm·数据库·python
iuvtsrt1 小时前
PHP 中使用 GnuPG 实现 PGP 加密与解密的完整实践指南
jvm·数据库·python
天若有情6731 小时前
从零搭建局域网手机遥控电脑网页项目,吃透工程化与架构设计思维
服务器·前端·数据库·算法·开源·node·工程化
dFObBIMmai1 小时前
如何用 click 与 mousedown 区分鼠标点击与按下的触发顺序
jvm·数据库·python
czlczl200209251 小时前
分布式数据库分片自动扩展
数据库·分布式
zh1570231 小时前
MongoDB备节点无法读取数据怎么解决_rs.slaveOk()与Secondary读取权限
jvm·数据库·python
云天AI实战派1 小时前
Python 智能体实战:从 0 搭建模块化 Agent 路由系统,落地小龙虾门店运营助手
开发语言·人工智能·python
H_unique1 小时前
Trae实现Web UI自动化测试
python·ui·ai编程·trae