我有一个react应用程序,它使用MediaRecorder API录制音频,然后将录制的音频数据转换为base64。代码如下所示:
import React, { useState } from "react";
const App: React.FC = () => {
const [recording, setRecording] = useState(false);
const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder>();
const [audioChunks, setAudioChunks] = useState<Blob[]>([]);
const handleStartRecording = async () => {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
});
const mediaRecorder = new MediaRecorder(stream);
setMediaRecorder(mediaRecorder);
mediaRecorder.start();
mediaRecorder.addEventListener("dataavailable", handleDataAvailable);
setRecording(true);
};
const handleStopRecording = () => {
if (mediaRecorder) {
mediaRecorder.stop();
setRecording(false);
}
};
const handleDataAvailable = (e: BlobEvent) => {
if (e.data.size > 0) {
setAudioChunks((prev) => [...prev, e.data]);
}
};
const handleDownload = async () => {
if (audioChunks) {
const audioBlob = new Blob(audioChunks);
convertToBase64AndSend(audioBlob);
setMediaRecorder(undefined);
setAudioChunks([]);
}
};
const convertToBase64AndSend = (audioBlob: Blob) => {
const reader = new FileReader();
reader.readAsDataURL(audioBlob);
reader.onloadend = () => {
const base64data = reader.result as string;
console.log(base64data);
}
}
return (
<div>
<button onClick={recording ? handleStopRecording : handleStartRecording}>
{recording ? "Stop Recording" : "Start Recording"}
</button>
{audioChunks.length > 0 && (
<button onClick={handleDownload}>Send Audio</button>
)}
</div>
);
};
export default App;
`
现在代码在这种状态下完全按照预期工作,你点击开始录制,然后音频开始录制,你点击停止录制,然后音频停止录制,当你点击下载,它成功地将音频数据转换为base64并记录下来:
我想修改这段代码,让它在我点击Stop Recording时自动启动下载功能,所以我删除了Download按钮,让handleStopRecording()函数调用handleDownload()函数,如下所示:
const handleStopRecording = () => {
if (mediaRecorder) {
mediaRecorder.stop();
setRecording(false);
}
handleDownload();
};
return (
<div>
<button onClick={recording ? handleStopRecording : handleStartRecording}>
{recording ? "Stop Recording" : "Start Recording"}
</button>
</div>
);
然而,现在这导致了一个问题,我记录的base64AudioData是空的。大概是因为audioChunks钩子没有正确设置。似乎audioChunks钩子只有在有一个额外的按钮按下时才能正确设置,但我不太理解react,不知道为什么。我该如何纠正这个问题?
1条答案
按热度按时间yhived7q1#
您需要等待
audioChunks
状态被设置,并且由于设置状态是异步的,并且在本例中它只在调用dataavailable
事件之后发生,所以当您在mediaRecorder.stop()
之后调用handleDownload()
时,块还没有准备好。一个简单的解决方案是将下载代码移到
useEffect
块中,这样它就可以在设置块之后执行:但是,由于现在下载时只需要块,之后会重置它们,因此不需要
audioChunks
状态,可以直接从dataavailable
事件处理程序调用下载,并将当前块传递给它: