공식문서
설치
npx expo install expo-av
yarn add expo-module-scripts
음성 녹음 , 재생 예제
import { useEffect, useState } from 'react';
import { View, Button } from 'react-native';
import { Audio, InterruptionModeAndroid, InterruptionModeIOS } from 'expo-av';
import { AndroidOutputFormat, IOSOutputFormat } from 'expo-av/build/Audio';
import { AndroidAudioEncoder, IOSAudioQuality } from 'expo-av/build/Audio';
const RecordScreen = () => {
const [recording, setRecording] = useState<Audio.Recording | undefined>();
const [permissionResponse, requestPermission] = Audio.usePermissions();
const [uri, setUri] = useState<string | null>(null);
const [sound, setSound] = useState<Audio.Sound | undefined>();
const [isPaused, setIsPaused] = useState<boolean>(false);
const newAudioOptions = {
isMeteringEnabled: true,
android: {
extension: '.wav',
outputFormat: AndroidOutputFormat.MPEG_4,
audioEncoder: AndroidAudioEncoder.AAC,
sampleRate: 44100,
numberOfChannels: 2,
bitRate: 128000,
},
ios: {
extension: '.wav',
outputFormat: IOSOutputFormat.MPEG4AAC,
audioQuality: IOSAudioQuality.MAX,
sampleRate: 44100,
numberOfChannels: 2,
bitRate: 128000,
linearPCMBitDepth: 16,
linearPCMIsBigEndian: false,
linearPCMIsFloat: false,
},
web: {
mimeType: 'audio/webm',
bitsPerSecond: 128000,
},
};
const startRecording = async () => {
try {
if (recording)return;
if (!permissionResponse || permissionResponse.status !== 'granted') await requestPermission();
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
interruptionModeAndroid: InterruptionModeAndroid.DoNotMix,
interruptionModeIOS: InterruptionModeIOS.DoNotMix,
shouldDuckAndroid: false,
staysActiveInBackground: false,
});
console.log('Starting recording..');
const recordingObject = await Audio.Recording.createAsync(newAudioOptions);
setRecording(recordingObject.recording);
console.log('Recording started');
} catch (err) {
console.error('Failed to start recording', err);
}
}
const togglePauseRecording = async () => {
if (recording) {
if (isPaused) {
console.log('Resuming recording..');
await recording.startAsync();
setIsPaused(false);
} else {
console.log('Pausing recording..');
await recording.pauseAsync();
setIsPaused(true);
}
}
}
const stopRecording = async () => {
console.log('Stopping recording..');
setRecording(undefined);
await recording?.stopAndUnloadAsync();
await Audio.setAudioModeAsync({
allowsRecordingIOS: false,
});
const uri = recording?.getURI() ?? null;
setUri(uri);
console.log('Recording stopped and stored at', uri);
}
const playSound = async () => {
if (uri) {
const { sound } = await Audio.Sound.createAsync({ uri });
setSound(sound);
console.log('Playing sound');
await sound.playAsync();
}
}
const uploadRecording = async () => {
if (uri) {
const formData = new FormData();
formData.append("uri",uri);
formData.append('name','recording.wav');
formData.append('type','audio/wav');
console.log("formData",formData);
; try {
const response = await fetch('https://your-backend-server.com/upload', {
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
});
if (response.ok) {
console.log('File uploaded successfully');
} else {
console.error('File upload failed');
}
} catch (error) {
console.error('Error uploading file:', error);
}
} else {
console.error('No recording available to upload');
}
}
return (
<View className="flex-1 justify-center bg-gray-200 p-2.5">
<Button
title={recording ? (isPaused ? 'Resume Recording' : 'Pause Recording') : 'Start Recording'}
onPress={recording ? togglePauseRecording : startRecording}
/>
{recording && (
<Button
title="Stop Recording"
onPress={stopRecording}
/>
)}
{uri && (
<>
<Button
title="Play Recording"
onPress={playSound}
/>
<Button
title="Submit"
onPress={uploadRecording}
/>
</>
)}
</View>
);
}
export default RecordScreen;