React Native录音功能实现及音频上传服务器需求咨询
React Native 录音功能实现方案
1. 安装依赖
使用react-native-audio-recorder-player处理录音逻辑,react-native-permissions处理权限申请,执行以下命令:
npm install react-native-audio-recorder-player react-native-permissions react-native-fs # 或用 yarn yarn add react-native-audio-recorder-player react-native-permissions react-native-fs
2. 配置权限
iOS
在Info.plist中添加麦克风权限申请描述:
<key>NSMicrophoneUsageDescription</key> <string>需要访问麦克风进行录音</string>
Android
在AndroidManifest.xml中添加录音和存储权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
3. 完整Train组件代码
替换原有代码,实现点击录音、自动静音停止、手动停止及文件上传功能:
import { StyleSheet, Text, View, Image, Pressable, Alert } from 'react-native' import React, { useState, useRef } from 'react' import { useAuth } from '../AuthContext' import { COLORS } from '../assets/colors/colors'; import Train_word from '../assets/images/Train_word.svg' import Train_word_2 from '../assets/images/Train_word_2.svg' import AudioRecorderPlayer from 'react-native-audio-recorder-player'; import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions'; import RNFS from 'react-native-fs'; const audioRecorderPlayer = new AudioRecorderPlayer(); const Train = () => { const [user] = useAuth() const [isRecording, setIsRecording] = useState(false) const [audioPath, setAudioPath] = useState('') const silenceTimerRef = useRef(null) // 检查并申请麦克风权限 const checkMicrophonePermission = async () => { const permission = Platform.OS === 'ios' ? PERMISSIONS.IOS.MICROPHONE : PERMISSIONS.ANDROID.RECORD_AUDIO; const result = await check(permission); if (result === RESULTS.DENIED) { const requestResult = await request(permission); return requestResult === RESULTS.GRANTED; } return result === RESULTS.GRANTED; } // 启动静音检测:5秒内音量低于阈值则自动停止录音 const startSilenceDetection = () => { silenceTimerRef.current = setInterval(async () => { const volume = await audioRecorderPlayer.getVolume(); // 音量阈值可按需调整,当前设为0.01 if (parseFloat(volume) < 0.01) { stopRecording(); Alert.alert('提示', '未检测到声音,已自动停止录音'); } }, 5000); } // 开始录音 const startRecording = async () => { const hasPermission = await checkMicrophonePermission(); if (!hasPermission) { Alert.alert('权限不足', '请允许访问麦克风'); return; } const path = `${RNFS.DocumentDirectoryPath}/recording_${Date.now()}.mp4`; const audioSet = { AudioEncoderAndroid: 'aac', AudioSourceAndroid: 'mic', OutputFormatAndroid: 'mpeg_4', AudioQualityIOS: 'low', AudioEncodingBitRateIOS: 32000, NumberOfChannelsIOS: 1, }; await audioRecorderPlayer.startRecorder(path, audioSet); setIsRecording(true); setAudioPath(path); startSilenceDetection(); audioRecorderPlayer.addRecordBackListener((e) => { console.log('录音进度:', e.current_position, '/', e.duration); }); } // 停止录音 const stopRecording = async () => { if (silenceTimerRef.current) { clearInterval(silenceTimerRef.current); silenceTimerRef.current = null; } await audioRecorderPlayer.stopRecorder(); setIsRecording(false); audioRecorderPlayer.removeRecordBackListener(); console.log('录音文件路径:', audioPath); } // 上传录音文件到服务器 const uploadAudio = async () => { if (!audioPath) { Alert.alert('提示', '暂无录音文件可上传'); return; } const formData = new FormData(); formData.append('audio', { uri: Platform.OS === 'ios' ? audioPath.replace('file://', '') : audioPath, name: `recording_${Date.now()}.mp4`, type: 'audio/mp4', }); try { const response = await fetch('你的服务器上传接口地址', { method: 'POST', headers: { 'Content-Type': 'multipart/form-data', // 若需身份验证,添加token // 'Authorization': `Bearer ${user.token}` }, body: formData, }); const result = await response.json(); response.ok ? Alert.alert('成功', '录音文件上传完成') : Alert.alert('失败', `上传错误:${result.message}`); } catch (error) { Alert.alert('错误', `上传失败:${error.message}`); } } return ( <View style={styles.container}> <View style={styles.header}> <Image source={require('../assets/images/Logo_small.png')} style={styles.logo_s} resizeMode='contain'/> </View> <View style={styles.main_cont}> <Train_word marginBottom={34}/> <Train_word_2 marginBottom={55}/> <Pressable marginBottom={180} onPress={() => isRecording ? stopRecording() : startRecording()} > <Image source={isRecording ? require('../assets/images/Stop_img.png') : require('../assets/images/Start_img.png')} style={styles.start_img}> </Image> </Pressable> <Pressable style={styles.result} onPress={uploadAudio}> <Text style={styles.text_result}>Получить результат</Text> </Pressable> </View> <Image source={require('../assets/images/bottom_menu.png')} style={styles.img_bg}/> </View> ) } export default Train const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "rgba(243, 239, 239, 1)", alignItems: 'center' }, img_bg: { width: 412, height: 80, }, logo_s: { width: 100, height: 100, left: 150, top: -130, }, header: { backgroundColor: 'transparent', flexDirection: 'row', alignItems:'center', height: 100, paddingTop: 180, paddingRight: 35 }, main_cont: { alignItems: 'center', top: -90, flex: 1, }, start_img: { width: 286, height: 286, }, result: { backgroundColor: 'transparent', width: 178, height: 25, alignItems: "center", left: -63, }, text_result: { fontFamily: 'OpenSans-Italic', color: COLORS.text, fontSize: 16, textDecorationLine: 'underline' } })
功能说明
- 录音切换:点击按钮切换状态,未录音时启动录音,录音中则手动停止。
- 自动静音停止:录音启动后每5秒检测音量,低于阈值时自动停止并提示用户。
- 文件上传:点击"Получить результат"按钮将录音文件以FormData格式上传到服务器,需替换为实际接口地址。
- 权限处理:启动录音前自动检查并申请麦克风权限,避免无权限导致功能异常。
内容的提问来源于stack exchange,提问作者Proger228
相关产品推荐
相关产品推荐

