如何在 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 拥有线稿上色优化、图片重绘、人物姿势检测、涂鸦完善等功能

相关推荐
专业程序开发源6 分钟前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
FPGA小迷弟9 分钟前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
c++·python·ai·plotly·django·ai编程·claude
卷无止境19 分钟前
面向arm64桌面客户端开发全景:语言、框架与生态
后端·python
九零HTTP29 分钟前
10月21号-CSDN配菜-IP池的5个坑
服务器·数据库·tcp/ip
fanruitian31 分钟前
python else用法
开发语言·python
Data-Miner42 分钟前
需要做财务数据分析,有什么好用的工具?从准备到出报告的实操指南
大数据·数据库·数据分析
Thinker QAQ1 小时前
并发编程(十一):Shared Memory 与 Message Passing——关系与组合使用
java·python·go·并发编程·shared memory·message passing
用户8356290780511 小时前
如何使用 Python 对 Excel 数据进行分组和分级显示
后端·python
vx_Biye_Design1 小时前
django房屋租赁推荐系统78455-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·课程设计·express
袋鼠云数栈1 小时前
让 SQL 解析不再重复造轮子:SqlParserX 正式开源
数据库·人工智能·sql·开源·数据治理