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

使用expo-audio录制音频时实例未释放导致重复获取旧音频的问题

expo-audio录制音频时实例未释放导致重复获取旧音频的问题

兄弟,我前阵子迁移expo音频库的时候也踩过这个坑!你的问题核心在于useAudioRecorder创建的实例默认会复用同一个临时文件路径,而且单纯调用stop()并不会自动清理或重置这个路径,导致每次新录制的音频都覆盖(或者直接复用)了旧文件,自然拿到的都是第一次的内容。

给你两个实用的解决方案,亲测有效:

方案一:手动指定唯一的输出文件路径(推荐)

我们可以借助expo-file-system生成每次录制的唯一临时路径,强制让录制器写入新文件,彻底避免复用旧资源。

先修改你的hook代码:

import { RecordingPresets, useAudioRecorder } from 'expo-audio';
import { useState } from "react";
import * as FileSystem from 'expo-file-system';

export default function useRecorder() {
  const audioRecorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
  const [isRecording, setIsRecording] = useState(false);
  const [recordedUri, setRecordedUri] = useState(null); // 用来存每次的录制结果

  const startRecording = async () => {
    // 用时间戳生成唯一的文件名,保证路径不重复
    const newRecordingUri = `${FileSystem.cacheDirectory}voice_recording_${Date.now()}.m4a`;
    
    // 传入新的输出路径重新准备录制
    await audioRecorder.prepareToRecordAsync({
      ...RecordingPresets.HIGH_QUALITY,
      outputUri: newRecordingUri
    });
    
    audioRecorder.record();
    setIsRecording(true);
  };

  const stopRecording = async () => {
    await audioRecorder.stop();
    // 保存本次录制的URI
    setRecordedUri(audioRecorder.uri);
    console.log("本次录制完成,文件URI:", audioRecorder.uri);
    setIsRecording(false);
    
    // 可选:重置录制器状态,释放内部资源
    await audioRecorder.reset();
  };

  return { startRecording, stopRecording, recordedUri, isRecording };
}

这个方法的好处是完全可控,每次录制都用全新的文件,而且reset()方法能帮你清理录制器的内部状态,避免残留旧数据。

方案二:强制重新创建录制器实例

如果上面的方法还没解决问题,我们可以通过改变useAudioRecorder的key参数,让它每次停止录制后都销毁旧实例、创建新实例,从根源上避免旧资源的复用:

import { RecordingPresets, useAudioRecorder } from 'expo-audio';
import { useState } from "react";

export default function useRecorder() {
  // 用一个key来控制录制器实例的重建
  const [recorderKey, setRecorderKey] = useState(0);
  const audioRecorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY, { key: recorderKey });
  
  const [isRecording, setIsRecording] = useState(false);
  const [recordedUri, setRecordedUri] = useState(null);

  const startRecording = async () => {
    await audioRecorder.prepareToRecordAsync();
    audioRecorder.record();
    setIsRecording(true);
  };

  const stopRecording = async () => {
    await audioRecorder.stop();
    setRecordedUri(audioRecorder.uri);
    console.log("本次录制完成,文件URI:", audioRecorder.uri);
    setIsRecording(false);
    
    // 更新key,触发录制器实例重建
    setRecorderKey(prevKey => prevKey + 1);
  };

  return { startRecording, stopRecording, recordedUri, isRecording };
}

额外提醒

  • 记得确保已经获取了RECORD_AUDIO和WRITE_EXTERNAL_STORAGE(如果需要持久化保存)的权限,你提到省略了这部分,一定要确认权限没问题
  • 缓存目录的文件可能会被系统自动清理,如果需要长期保存录制的音频,记得用FileSystem.moveAsync()把文件移到持久化存储目录

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:13:09