在 React Native Expo 中录制后如何播放声音?
How can I play a sound after recording in React Native Expo?
我正在使用 Expo 构建一个录音应用程序。
这是我开始录音的功能,可以正常使用。
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);
}
}
这是我的 'stop' 功能,录制已停止并存储...
async function stopRecording() {
console.log('Stopping recording..');
setRecording(undefined);
await recording.stopAndUnloadAsync();
const uri = recording.getURI();
console.log('Recording stopped and stored at', uri);
}
现在我想用播放按钮播放这个保存的声音。我怎样才能找到这个保存的声音?
return (
<View style={styles.container}>
<Button
title={recording ? 'Stop Recording' : 'Start Recording'}
onPress={recording ? stopRecording : startRecording}
/>
</View>
);
我想将这个存储的 uri 作为文件位置传递。这样可以吗?
async function playSound() {
console.log('Loading Sound');
const { sound } = await Audio.Sound.createAsync(
require(RecordedURI)
);
setSound(sound);
console.log('Playing Sound');
await sound.playAsync();
}
这是点心link:https://snack.expo.io/ZN9MBtpLd
首先,您在获得录音后将您的状态分配给undefined
。
我建议你这样做
为 Recording
和 Playing
音频创建两个引用。
const AudioRecorder = useRef(new Audio.Recording());
const AudioPlayer = useRef(new Audio.Sound());
以及 recordingStatus
、permission
等的一些状态
const [RecordedURI, SetRecordedURI] = useState<string>("");
const [AudioPermission, SetAudioPermission] = useState<boolean>(false);
const [IsRecording, SetIsRecording] = useState<boolean>(false);
const [IsPLaying, SetIsPLaying] = useState<boolean>(false);
录音实施的小吃是here
这里有一个 GitHub Repo 实现。
Screenshot 结果
我在下面添加了其余的实现
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,
},
});
这是一个有趣的问题,我也遇到了同样的问题。我无法从记录的 URI 播放。
此外,我已经从官方文档中了解了,但是他们只提供了有限的示例。
但我想出了一个有趣的解决方案,它对我来说很有效。 Audio.Sound.createAsync()
也支持URI支持。
您只需通过 {uri: recording. getURI() || URIFROMFileSystem}
即可完美运行。
以我为例
const { sound } = await Audio.Sound.createAsync({
uri: "file:///Users/xyz/Library/Developer/CoreSimulator/Devices/1BBRFGFCBC414-6685-4818-B625-01038771B105/data/Containers/Data/Application/18E8D28E-EA03-4733-A0CF-F3E21A23427D/Library/Caches/ExponentExperienceData/%2540anonymous%252Fchat-app-c88a6b2e-ad36-45b8-9e5e-1fb6001826eb/AV/recording-87738E73-A38E-49E8-89D1-9689DC5F316B.caf",
});
setSound(sound);
console.log("Playing Sound");
await sound.playAsync();
我正在使用 Expo 构建一个录音应用程序。 这是我开始录音的功能,可以正常使用。
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);
}
}
这是我的 'stop' 功能,录制已停止并存储...
async function stopRecording() {
console.log('Stopping recording..');
setRecording(undefined);
await recording.stopAndUnloadAsync();
const uri = recording.getURI();
console.log('Recording stopped and stored at', uri);
}
现在我想用播放按钮播放这个保存的声音。我怎样才能找到这个保存的声音?
return (
<View style={styles.container}>
<Button
title={recording ? 'Stop Recording' : 'Start Recording'}
onPress={recording ? stopRecording : startRecording}
/>
</View>
);
我想将这个存储的 uri 作为文件位置传递。这样可以吗?
async function playSound() {
console.log('Loading Sound');
const { sound } = await Audio.Sound.createAsync(
require(RecordedURI)
);
setSound(sound);
console.log('Playing Sound');
await sound.playAsync();
}
这是点心link:https://snack.expo.io/ZN9MBtpLd
首先,您在获得录音后将您的状态分配给undefined
。
我建议你这样做
为 Recording
和 Playing
音频创建两个引用。
const AudioRecorder = useRef(new Audio.Recording());
const AudioPlayer = useRef(new Audio.Sound());
以及 recordingStatus
、permission
等的一些状态
const [RecordedURI, SetRecordedURI] = useState<string>("");
const [AudioPermission, SetAudioPermission] = useState<boolean>(false);
const [IsRecording, SetIsRecording] = useState<boolean>(false);
const [IsPLaying, SetIsPLaying] = useState<boolean>(false);
录音实施的小吃是here
这里有一个 GitHub Repo 实现。
Screenshot 结果
我在下面添加了其余的实现
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,
},
});
这是一个有趣的问题,我也遇到了同样的问题。我无法从记录的 URI 播放。
此外,我已经从官方文档中了解了,但是他们只提供了有限的示例。
但我想出了一个有趣的解决方案,它对我来说很有效。 Audio.Sound.createAsync()
也支持URI支持。
您只需通过 {uri: recording. getURI() || URIFROMFileSystem}
即可完美运行。
以我为例
const { sound } = await Audio.Sound.createAsync({
uri: "file:///Users/xyz/Library/Developer/CoreSimulator/Devices/1BBRFGFCBC414-6685-4818-B625-01038771B105/data/Containers/Data/Application/18E8D28E-EA03-4733-A0CF-F3E21A23427D/Library/Caches/ExponentExperienceData/%2540anonymous%252Fchat-app-c88a6b2e-ad36-45b8-9e5e-1fb6001826eb/AV/recording-87738E73-A38E-49E8-89D1-9689DC5F316B.caf",
});
setSound(sound);
console.log("Playing Sound");
await sound.playAsync();