Home > Net >  How to get Expo Audio Recording Content as Base64?
How to get Expo Audio Recording Content as Base64?

Time:02-09

I am trying to use the recording mp4 content as base64 buffer and send to 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
  }
});

How to find the audio content instead of file path? For example, In the stopRecording() function, I want to send the recorded audio buffer to the URL. The getURI() returns a file path which is not the content. Is there any way to convert the content as byte array ? Thank you in advanced

CodePudding user response:

The common way to upload any file format from device file manager to server is through binary data mostly a binary large object (BLOB) then encode to any file final format (MP3, WAV, and more).


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



  •  Tags:  
  • Related