【问题标题】:How to get Expo Audio Recording Content as Base64?如何将 Expo 录音内容获取为 Base64?
【发布时间】:2022-02-07 20:23:15
【问题描述】:

我正在尝试将录制的 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


    【解决方案1】:

    将任何文件格式从设备文件管理器上传到服务器的常用方法是通过二进制数据,主要是二进制大对象 (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()
    }
    
    
    
    

    【讨论】:

    • 嗨。您是否建议在 stopRecording() 函数中包含代码 sn-p?
    • 是的。您的后端是否可以支持BLOB 代替base64
    • 你能给我一个样本 BLOB 和 base64 的任何 mp4 音频文件吗?我想检查我的后端是否可以处理这两个
    • 我尝试更新解决方案并将文件转换为base64
    • 代码现在可以输出base64数据了。但是,当我尝试将其转换回 mp4 时:“此文件无法播放。这可能是因为文件类型不受支持、文件扩展名不正确或文件已损坏。”我的后端收到两个字符串:b'AAAAAZZ......' b'ZHSKAIOQ.......' 但无法按预期处理。你能帮我解决这个问题吗?
    猜你喜欢
    • 2019-04-21
    • 2011-01-28
    • 2020-08-09
    • 2014-06-08
    • 2022-08-04
    • 1970-01-01
    • 2019-06-02
    • 2021-09-06
    • 2015-03-09
    相关资源
    最近更新 更多