I'm building a voice recording application with Expo. This is my function to start voice recording, it works properly.
const [recording, setRecording] = React.useState();
async function startRecording() {
try {
console.log('Requesting permissions..');
await Audio.requestPermissionsAsync();
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
});
console.log('Starting recording..');
const recording = new Audio.Recording();
await recording.prepareToRecordAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY);
await recording.startAsync();
setRecording(recording);
console.log('Recording started');
} catch (err) {
console.error('Failed to start recording', err);
}
}
And this is my 'stop' function, Recording stopped and stored...
async function stopRecording() {
console.log('Stopping recording..');
setRecording(undefined);
await recording.stopAndUnloadAsync();
const uri = recording.getURI();
console.log('Recording stopped and stored at', uri);
}
Now I want to play this saved sound with a play button. How can I reach this saved sound?
return (
<View style={styles.container}>
<Button
title={recording ? 'Stop Recording' : 'Start Recording'}
onPress={recording ? stopRecording : startRecording}
/>
</View>
);
I want to pass this stored uri as a file location. Is it possible in this way?
async function playSound() {
console.log('Loading Sound');
const { sound } = await Audio.Sound.createAsync(
require(RecordedURI)
);
setSound(sound);
console.log('Playing Sound');
await sound.playAsync();
}
This is the snack link: https://snack.expo.io/ZN9MBtpLd
First of all, you are assigning your state to undefined
after you get the recording.
I would suggest you to do something like this
Create two refs for Recording
and Playing
audio.
const AudioRecorder = useRef(new Audio.Recording());
const AudioPlayer = useRef(new Audio.Sound());
And some states for recordingStatus
, permission
etc.
const [RecordedURI, SetRecordedURI] = useState<string>("");
const [AudioPermission, SetAudioPermission] = useState<boolean>(false);
const [IsRecording, SetIsRecording] = useState<boolean>(false);
const [IsPLaying, SetIsPLaying] = useState<boolean>(false);
Snack for the recording implementation is here
Here's a GitHub Repo which has the implementation.
Screenshot of Result
I've added below the Rest of the implementation
import React, { useState, useRef, useEffect } from "react";
import { View, StyleSheet, Button, Text } from "react-native";
import { Audio } from "expo-av";
export default function App() {
// Refs for the audio
const AudioRecorder = useRef(new Audio.Recording());
const AudioPlayer = useRef(new Audio.Sound());
// States for UI
const [RecordedURI, SetRecordedURI] = useState<string>("");
const [AudioPermission, SetAudioPermission] = useState<boolean>(false);
const [IsRecording, SetIsRecording] = useState<boolean>(false);
const [IsPLaying, SetIsPLaying] = useState<boolean>(false);
// Initial Load to get the audio permission
useEffect(() => {
GetPermission();
}, []);
// Function to get the audio permission
const GetPermission = async () => {
const getAudioPerm = await Audio.requestPermissionsAsync();
SetAudioPermission(getAudioPerm.granted);
};
// Function to start recording
const StartRecording = async () => {
try {
// Check if user has given the permission to record
if (AudioPermission === true) {
try {
// Prepare the Audio Recorder
await AudioRecorder.current.prepareToRecordAsync(
Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY
);
// Start recording
await AudioRecorder.current.startAsync();
SetIsRecording(true);
} catch (error) {
console.log(error);
}
} else {
// If user has not given the permission to record, then ask for permission
GetPermission();
}
} catch (error) {}
};
// Function to stop recording
const StopRecording = async () => {
try {
// Stop recording
await AudioRecorder.current.stopAndUnloadAsync();
// Get the recorded URI here
const result = AudioRecorder.current.getURI();
if (result) SetRecordedURI(result);
// Reset the Audio Recorder
AudioRecorder.current = new Audio.Recording();
SetIsRecording(false);
} catch (error) {}
};
// Function to play the recorded audio
const PlayRecordedAudio = async () => {
try {
// Load the Recorded URI
await AudioPlayer.current.loadAsync({ uri: RecordedURI }, {}, true);
// Get Player Status
const playerStatus = await AudioPlayer.current.getStatusAsync();
// Play if song is loaded successfully
if (playerStatus.isLoaded) {
if (playerStatus.isPlaying === false) {
AudioPlayer.current.playAsync();
SetIsPLaying(true);
}
}
} catch (error) {}
};
// Function to stop the playing audio
const StopPlaying = async () => {
try {
//Get Player Status
const playerStatus = await AudioPlayer.current.getStatusAsync();
// If song is playing then stop it
if (playerStatus.isLoaded === true)
await AudioPlayer.current.unloadAsync();
SetIsPLaying(false);
} catch (error) {}
};
return (
<View style={styles.container}>
<Button
title={IsRecording ? "Stop Recording" : "Start Recording"}
color={IsRecording ? "red" : "green"}
onPress={IsRecording ? StopRecording : StartRecording}
/>
<Button
title={IsPLaying ? "Stop Sound" : "Play Sound"}
color={IsPLaying ? "red" : "orange"}
onPress={IsPLaying ? StopPlaying : PlayRecordedAudio}
/>
<Text>{RecordedURI}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
backgroundColor: "#ecf0f1",
padding: 8,
},
});