You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo Audio获取音频时长偶发‘File not found’错误(Android/iOS均存在)

Expo Audio录音后获取时长偶尔报“File not found”的解决方案

问题背景

使用Expo Audio完成录音,执行stopAndUnloadAsync()后获取录音URI,但后续调用Audio.Sound.createAsync()读取时长时,偶尔会抛出文件不存在的错误,Android和iOS均有低概率出现。

核心原因

  1. 文件写入延迟:stopAndUnloadAsync()虽然返回Promise,但底层可能仍在异步写入录音文件到磁盘,此时立即读取会找不到文件。
  2. 缓存目录不稳定性:录音默认存在缓存目录,系统可能在内存紧张时自动清理该目录下的临时文件,导致读取失败。
  3. 异步时序问题:跨线程的文件操作存在时序偏差,触发读取时文件尚未完成持久化。

可行解决方案

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:53:14