如何在React Native中实现点击按钮录音频,静音20秒后停止并保存为WAV文件?
Absolutely! This is totally achievable in React Native. We'll use a reliable audio library combined with volume level monitoring to detect silence, then auto-stop recording and save the file as WAV. Here's how to make it happen:
Step 1: Install Dependencies
We'll use react-native-audio-recorder-player for recording/playing audio and accessing volume levels, plus react-native-permissions to handle necessary device permissions (microphone, storage).
Install them via npm/yarn:
# Using npm npm install react-native-audio-recorder-player react-native-permissions # Using yarn yarn add react-native-audio-recorder-player react-native-permissions
For iOS, don't forget to run pod install after installing dependencies:
cd ios && pod install && cd ..
Step 2: Configure Permissions
iOS
Add these lines to your Info.plist (inside the <dict> tag) to request microphone and storage access:
<key>NSMicrophoneUsageDescription</key> <string>Need microphone access to record audio</string> <key>NSDocumentsFolderUsageDescription</key> <string>Need access to documents folder to save recorded audio</string>
Android
Add these permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
Step 3: Core Implementation Code
Here's a complete functional component example with all the logic you need:
import React, { useState, useEffect, useRef } from 'react'; import { View, Button, Text, Alert } from 'react-native'; import AudioRecorderPlayer from 'react-native-audio-recorder-player'; import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions'; const AudioRecorderComponent = () => { const [isRecording, setIsRecording] = useState(false); const [silenceDuration, setSilenceDuration] = useState(0); const silenceThreshold = -40; // Adjust based on your environment (lower = quieter) const maxSilenceTime = 20; // Target 20 seconds of silence const audioRecorderPlayer = useRef(new AudioRecorderPlayer()).current; const silenceTimerRef = useRef(null); const volumeCheckIntervalRef = useRef(null); // Check permissions when component mounts useEffect(() => { const checkPermissions = async () => { const micPermission = await check(PERMISSIONS.IOS.MICROPHONE ?? PERMISSIONS.ANDROID.RECORD_AUDIO); const storagePermission = await check(PERMISSIONS.IOS.DOCUMENTS_FOLDER ?? PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE); if (micPermission !== RESULTS.GRANTED || storagePermission !== RESULTS.GRANTED) { const micRequest = await request(PERMISSIONS.IOS.MICROPHONE ?? PERMISSIONS.ANDROID.RECORD_AUDIO); const storageRequest = await request(PERMISSIONS.IOS.DOCUMENTS_FOLDER ?? PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE); if (micRequest !== RESULTS.GRANTED || storageRequest !== RESULTS.GRANTED) { Alert.alert("Permissions Required", "Please grant microphone and storage permissions to use this feature."); } } }; checkPermissions(); // Cleanup timers and recording on component unmount return () => { if (silenceTimerRef.current) clearTimeout(silenceTimerRef.current); if (volumeCheckIntervalRef.current) clearInterval(volumeCheckIntervalRef.current); audioRecorderPlayer.stopRecorder(); }; }, []); const startRecording = async () => { try { // Configure recording to save as WAV format const audioPath = `${AudioRecorderPlayer.WORKING_DIR}/test.wav`; const recordingOptions = { audioQuality: "high", sampleRate: 44100, numberOfChannels: 1, audioEncoding: "wav", format: "wav", }; await audioRecorderPlayer.startRecorder(audioPath, recordingOptions); setIsRecording(true); setSilenceDuration(0); // Monitor volume levels every 1 second volumeCheckIntervalRef.current = setInterval(async () => { const volume = await audioRecorderPlayer.getVolume(); const decibel = parseInt(volume); if (decibel <= silenceThreshold) { // Increment silence counter if below threshold setSilenceDuration(prev => prev + 1); } else { // Reset counter if sound is detected setSilenceDuration(0); if (silenceTimerRef.current) clearTimeout(silenceTimerRef.current); } }, 1000); // Check if silence duration hits the 20-second mark const checkSilenceTimeout = () => { if (silenceDuration >= maxSilenceTime && isRecording) { stopRecording(); Alert.alert("Recording Stopped", "Silence detected for 20 seconds."); } else { silenceTimerRef.current = setTimeout(checkSilenceTimeout, 1000); } }; silenceTimerRef.current = setTimeout(checkSilenceTimeout, 1000); } catch (error) { console.error("Error starting recording:", error); Alert.alert("Error", "Failed to start recording."); } }; const stopRecording = async () => { try { await audioRecorderPlayer.stopRecorder(); setIsRecording(false); // Clean up timers if (silenceTimerRef.current) clearTimeout(silenceTimerRef.current); if (volumeCheckIntervalRef.current) clearInterval(volumeCheckIntervalRef.current); Alert.alert("Recording Saved", "Your audio has been saved as test.wav"); } catch (error) { console.error("Error stopping recording:", error); Alert.alert("Error", "Failed to stop recording."); } }; return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 }}> <Button title={isRecording ? "Stop Recording" : "Start Recording"} onPress={isRecording ? stopRecording : startRecording} color={isRecording ? "#ff3b30" : "#34c759"} /> {isRecording && ( <Text style={{ marginTop: 20, fontSize: 16 }}> Silence detected for: {silenceDuration}s / {maxSilenceTime}s </Text> )} </View> ); }; export default AudioRecorderComponent;
Key Adjustments & Tips
- Silence Threshold: The
-40 dBthreshold might need tweaking based on your environment. Test with different values to find what works best for your use case. - File Location: The audio saves to the app's working directory by default. You can adjust the
audioPathto save to external storage on Android if needed. - Performance: Checking volume every 1 second balances accuracy and performance—you can adjust the interval, but 1s is usually sufficient.
- Error Handling: The example includes basic error handling, but you might want to expand it for edge cases like low storage or recording interruptions.
内容的提问来源于stack exchange,提问作者Ravikiran kallepally

