在 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

我建议你这样做

RecordingPlaying 音频创建两个引用。

const AudioRecorder = useRef(new Audio.Recording());
const AudioPlayer = useRef(new Audio.Sound());

以及 recordingStatuspermission 等的一些状态

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();