Expo Audio获取音频时长偶发‘File not found’错误(Android/iOS均存在)
Expo Audio录音后获取时长偶尔报“File not found”的解决方案
问题背景
使用Expo Audio完成录音,执行stopAndUnloadAsync()后获取录音URI,但后续调用Audio.Sound.createAsync()读取时长时,偶尔会抛出文件不存在的错误,Android和iOS均有低概率出现。
核心原因
- 文件写入延迟:
stopAndUnloadAsync()虽然返回Promise,但底层可能仍在异步写入录音文件到磁盘,此时立即读取会找不到文件。 - 缓存目录不稳定性:录音默认存在缓存目录,系统可能在内存紧张时自动清理该目录下的临时文件,导致读取失败。
- 异步时序问题:跨线程的文件操作存在时序偏差,触发读取时文件尚未完成持久化。
可行解决方案
1. 增加短暂延迟等待文件写入
在停止卸载录音后,添加100-200ms的延迟,给系统足够时间完成文件写入:
const uri = recording.current.getURI(); await recording.current.stopAndUnloadAsync(); // 等待文件写入磁盘 await new Promise(resolve => setTimeout(resolve, 150)); try { const fileInfo = await Audio.Sound.createAsync({ uri }, { shouldPlay: false }); const duration = fileInfo.status.durationMillis; // 处理时长逻辑 } catch (error) { // 捕获错误,可提示用户重试 }
2. 复制文件到持久化目录
将录音文件从缓存目录复制到Expo的Document目录(该目录不会被系统自动清理),使用expo-file-system实现:
首先安装依赖:
npx expo install expo-file-system
然后修改代码:
import * as FileSystem from 'expo-file-system'; const uri = recording.current.getURI(); await recording.current.stopAndUnloadAsync(); // 创建目标目录(不存在则创建) const recordingsDir = `${FileSystem.documentDirectory}recordings/`; await FileSystem.makeDirectoryAsync(recordingsDir, { intermediates: true }); // 生成唯一文件名,避免重复 const targetUri = `${recordingsDir}${Date.now()}.m4a`; // 复制文件到持久化目录 await FileSystem.copyAsync({ from: uri, to: targetUri }); // 使用持久化的URI读取时长 try { const fileInfo = await Audio.Sound.createAsync({ uri: targetUri }, { shouldPlay: false }); const duration = fileInfo.status.durationMillis; // 处理时长逻辑 } catch (error) { // 错误处理 }
3. 添加重试机制
针对偶发的写入延迟,添加1-2次重试逻辑,每次重试增加延迟时间:
const uri = recording.current.getURI(); await recording.current.stopAndUnloadAsync(); let fileInfo = null; const maxRetries = 2; let retryCount = 0; while (retryCount < maxRetries) { try { fileInfo = await Audio.Sound.createAsync({ uri }, { shouldPlay: false }); break; } catch (error) { retryCount++; // 重试间隔逐渐增加 await new Promise(resolve => setTimeout(resolve, 100 * retryCount)); } } if (fileInfo) { const duration = fileInfo.status.durationMillis; // 处理时长逻辑 } else { // 多次重试失败,提示用户录音可能损坏 }
额外注意事项
- Android缓存目录下的文件可能被系统自动清理,若需长期保存录音,务必使用持久化目录。
- iOS错误码-11829本质是文件无法读取,复制到Document目录可从根源避免该问题。
- 完成操作后,可删除缓存目录中的原文件以节省空间:
await FileSystem.deleteAsync(uri);
内容的提问来源于stack exchange,提问作者Jogy Felix
相关产品推荐
相关产品推荐

