如何获取Base64格式的世博录音内容?

问题描述 投票:0回答:3

我正在尝试使用录制的mp4内容作为base64缓冲区并发送到rest api。

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import { Audio } from 'expo-av';
import axios     from 'axios';
import base64 from 'react-native-base64'

export default function App() {
  const [recording, setRecording] = React.useState();
  const [recordings, setRecordings] = React.useState([]);
  const [message, setMessage] = React.useState("");

  async function startRecording() {
    try {
      const permission = await Audio.requestPermissionsAsync();

      if (permission.status === "granted") {
        await Audio.setAudioModeAsync({
          allowsRecordingIOS: true,
          playsInSilentModeIOS: true
        });
        
        const RECORDING_OPTIONS_PRESET_HIGH_QUALITY: RecordingOptions = {
                android: {
                    extension: '.mp4',
                    outputFormat: Audio.RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_MPEG_4,
                    audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AMR_NB,
                    sampleRate: 44100,
                    numberOfChannels: 2,
                    bitRate: 128000,
                },
                ios: {
                    extension: '.wav',
                    audioQuality: Audio.RECORDING_OPTION_IOS_AUDIO_QUALITY_MIN,
                    sampleRate: 44100,
                    numberOfChannels: 2,
                    bitRate: 128000,
                    linearPCMBitDepth: 16,
                    linearPCMIsBigEndian: false,
                    linearPCMIsFloat: false,
                },
            };

        const { recording } = await Audio.Recording.createAsync(
          RECORDING_OPTIONS_PRESET_HIGH_QUALITY
        );

        setRecording(recording);
      } else {
        setMessage("Please grant permission to app to access microphone");
      }
    } catch (err) {
      console.error('Failed to start recording', err);
    }
  }

  async function stopRecording() {
    setRecording(undefined);
    await recording.stopAndUnloadAsync();

    let updatedRecordings = [...recordings];
    const { sound, status } = await recording.createNewLoadedSoundAsync();
    updatedRecordings.push({
      sound: sound,
      duration: getDurationFormatted(status.durationMillis),
      file: recording.getURI()
    });
    setRecordings(updatedRecordings);
    //const response = await axios.post('http://192.18.0.4:8000/audio', base64.encode(sound));
    console.log(sound);
  }

  function getDurationFormatted(millis) {
    const minutes = millis / 1000 / 60;
    const minutesDisplay = Math.floor(minutes);
    const seconds = Math.round((minutes - minutesDisplay) * 60);
    const secondsDisplay = seconds < 10 ? `0${seconds}` : seconds;
    return `${minutesDisplay}:${secondsDisplay}`;
  }


  function getRecordingLines() {
    console.log(recordings);
    return recordings.map((recordingLine, index) => {
      return (
        <View key={index} style={styles.row}>
          <Text style={styles.fill}>Recording {index + 1} - {recordingLine.duration}</Text>
          <Button style={styles.button} onPress={() => {recordingLine.sound.replayAsync(); 
                                                        console.log(recordingLine);}} title="Play"></Button>
        </View>
      );
    });
  }

  return (
    <View style={styles.container}>
      <Text>{message}</Text>
      <Button
        title={recording ? 'Stop Recording' : 'Start Recording'}
        onPress={recording ? stopRecording : startRecording} />
      {getRecordingLines()}
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  row: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  fill: {
    flex: 1,
    margin: 16
  },
  button: {
    margin: 16
  }
});

如何找到音频内容而不是文件路径?例如,在 stopRecording() 函数中,我想将录制的音频缓冲区发送到 URL。 getURI() 返回一个文件路径,它不是内容。有没有办法将内容转换为字节数组?提前谢谢您

react-native expo
3个回答
5
投票

将任何文件格式从设备文件管理器上传到服务器的常见方法是通过二进制数据(主要是二进制大对象 (BLOB)),然后编码为任何文件最终格式(MP3、WAV 等)。


  async function stopRecording() {
  setRecording(undefined);
  await recording.stopAndUnloadAsync();

  let updatedRecordings = [...recordings];
  const { sound, status } = await recording.createNewLoadedSoundAsync();
  updatedRecordings.push({
    sound: sound,
    duration: getDurationFormatted(status.durationMillis),
    file: recording.getURI(),
  });
  setRecordings(updatedRecordings);

  // utitlity function to convert BLOB to BASE64
  const blobToBase64 = (blob) => {
    const reader = new FileReader();
    reader.readAsDataURL(blob);
    return new Promise((resolve) => {
      reader.onloadend = () => {
        resolve(reader.result);
      };
    });
  };

  // Fetch audio binary blob data

  const audioURI = recording.getURI();
  const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function (e) {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", audioURI, true);
    xhr.send(null);
  });

  const audioBase64 = await blobToBase64(blob);

  const response = await axios.post(
    "http://192.18.0.4:8000/audio",
    base64.encode(audioBase64)
  );
  

// We're done with the blob and file uploading, close and release it
  blob.close()
}




0
投票

您可以使用react native fs,并且使用它可能类似于:

...
import { Audio } from "expo-av";
import RFNS from 'react-native-fs';

...
// after recording the audio

let audio = recording.getURI();

RFNS.readFile(audio, 'base64').then(async base64data => {
  //use base64data here in your code
  console.log(base64data);
});

0
投票

您还可以使用

expo-file-system
lib 执行以下操作:

const base64String = await FileSystem.readAsStringAsync(uri, {
    encoding: FileSystem?.EncodingType?.Base64,
})
© www.soinside.com 2019 - 2024. All rights reserved.