我正在尝试使用录制的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() 返回一个文件路径,它不是内容。有没有办法将内容转换为字节数组?提前谢谢您
将任何文件格式从设备文件管理器上传到服务器的常见方法是通过二进制数据(主要是二进制大对象 (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()
}
您可以使用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);
});
您还可以使用
expo-file-system
lib 执行以下操作:
const base64String = await FileSystem.readAsStringAsync(uri, {
encoding: FileSystem?.EncodingType?.Base64,
})