如何复用Expo的Audio.Recording对象实现多次录音?
复用Audio.Recording实例优化语音录制体验
完全可以复用单个Audio.Recording实例,这正是解决你当前频繁录音场景下性能问题的最优方案。
当前方案的核心问题
每次长按都创建新实例并执行prepareToRecordAsync异步操作,这个过程涉及硬件资源初始化、编码配置加载,频繁触发会产生明显延迟,直接影响用户操作流畅感;而结束时调用stopAndUnloadAsync会彻底卸载录制资源,导致下次录音必须重复初始化流程。
复用实例的实现方案
只在组件初始化阶段创建一次Recording实例并完成准备工作,后续每次录音仅重置状态、启动/停止录制,无需重复初始化。
1. 一次性初始化实例
const recording = React.useRef<Audio.Recording | null>(null); // 组件挂载时完成实例创建与准备 React.useEffect(() => { const initRecording = async () => { try { recording.current = new Audio.Recording(); recording.current.setOnRecordingStatusUpdate((...args) => { // 你的状态更新逻辑(比如音量监测、时长统计) }); recording.current.setProgressUpdateInterval(50); // 仅执行一次准备操作 await recording.current.prepareToRecordAsync({ isMeteringEnabled: true, android: { extension: '.mp3', outputFormat: AndroidOutputFormat.MPEG_4, audioEncoder: AndroidAudioEncoder.AAC, sampleRate: 44100, numberOfChannels: 2, bitRate: 128000, }, ios: { extension: '.mp3', outputFormat: IOSOutputFormat.MPEG4AAC, audioQuality: IOSAudioQuality.MAX, sampleRate: 44100, numberOfChannels: 2, bitRate: 128000, linearPCMBitDepth: 16, linearPCMIsBigEndian: false, linearPCMIsFloat: false, }, web: { mimeType: 'audio/webm', bitsPerSecond: 128000, }, }); } catch (err) { console.log('初始化录音实例失败', err); recording.current = null; } }; initRecording(); // 组件卸载时彻底清理资源 return () => { if (recording.current) { recording.current.stopAndUnloadAsync().catch(err => console.log('清理录音实例失败', err)); recording.current = null; } }; }, []);
2. 修改开始录音逻辑
const startRecording = React.useCallback(async () => { if (!recording.current) return; try { // 重置之前的录制数据,让实例回到可录制状态 await recording.current.resetAsync(); await recording.current.startAsync(); } catch (err) { console.log('开始录音失败', err); } }, []);
3. 修改停止录音逻辑
const stopRecording = React.useCallback(async () => { if (!recording.current) return; try { // 用stopAsync替代stopAndUnloadAsync,保留实例资源 await recording.current.stopAsync(); const uri = recording.current.getURI(); console.log('录音文件URI', uri); // 若无需立即处理文件,可提前resetAsync为下次录音做准备 // await recording.current.resetAsync(); } catch (err) { console.log('停止录音失败', err); } }, []);
关键注意事项
- 核心差异:
stopAsync仅停止录制,不会卸载底层资源;而stopAndUnloadAsync会彻底释放资源,导致实例无法复用 - 重置状态:每次录音前调用
resetAsync清除上次录制的缓存数据,避免数据污染 - 内存管理:组件卸载时必须调用
stopAndUnloadAsync并销毁实例,防止内存泄漏 - 异常处理:所有异步操作都要加try-catch,并在调用方法前检查实例是否存在,避免空指针错误
内容的提问来源于stack exchange,提问作者Mike K
相关产品推荐
相关产品推荐

