需要调用后端接口将录音文件传给后端,由后端将录音内容转换成文字返回给前端,当然也有一些插件可以实现语音转文字功能,可以自行查找使用插件实现方法
有注释版本,下面还有 一个无注释版本。
import React, { useState, useEffect, useRef } from "react";
import { getTextByAudio } from "./api/audio";
const AudioRecorder = () => {
const [recording, setRecording] = useState(false); // 是否正在录音
const audioData = useRef<MediaStream | null>(null); // 创建一个ref,存储媒体流数据
const mediaRecorderRef = useRef<MediaRecorder | null>(null); // 创建一个ref,用于存储媒体记录器实例
const chunksRef = useRef<Blob[]>([]); // 创建一个ref,用于存储音频数据块
useEffect(() => {
const init = async () => {
try {
// 获取用户媒体设备(麦克风)的媒体流
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
});
// 将获取到的媒体流存储到audioData ref中
audioData.current = stream;
} catch (error) {
console.error("Error accessing microphone:", error);
// 如果获取媒体流失败,打印错误信息
// 这里可以设置一个错误状态,用于显示给用户
}
};
init();
// 组件卸载时清理资源
return () => {
if (audioData.current) {
audioData.current.getTracks().forEach((track) => track.stop());
}
};
}, []);
const startRecording = () => {
if (audioData.current) {
chunksRef.current = [];// 重置chunks数组,用于新的录音
mediaRecorderRef.current = new MediaRecorder(audioData.current);// 创建一个新的MediaRecorder实例
// 当有数据可用时触发的事件
mediaRecorderRef.current.ondataavailable = (event) => {
if (event.data && event.data.size > 0) {
chunksRef.current.push(event.data);// 将数据块添加到chunks数组中
}
};
mediaRecorderRef.current.start();// 开始录音
setRecording(true);// 更新录音状态为正在录音
}
};
const stopRecording = () => {
if (
mediaRecorderRef.current &&
mediaRecorderRef.current.state === "recording"
) {
mediaRecorderRef.current.stop();// 停止录音
setRecording(false);// 更新录音状态为未录音
// 当录音停止时触发的事件
mediaRecorderRef.current.onstop = async () => {
// 将chunks数组中的数据合并成一个Blob对象
const blob = new Blob(chunksRef.current, { type: "audio/wav" });
const formData = new FormData(); // 创建一个FormData对象,用于上传音频文件
formData.append("file", blob, "recording.wav");
getTextByAudio(formData)
.then((res: any) => {
console.log(res, 999);
})
.catch((error) => {
console.error("Error converting audio to text:", error);
// 这里可以设置一个错误状态,用于显示给用户
});
};
}
};
return (
<div>
<button
onClick={recording ? stopRecording : startRecording}
style={{ backgroundColor: recording ? "red" : "white" }}
>
{recording ? "停止录音" : "开始录音"}
</button>
</div>
);
};
export default AudioRecorder;
无注释版
import React, { useState, useEffect, useRef } from "react";
import { getTextByAudio } from "./api/audio";
const AudioRecorder = () => {
const [recording, setRecording] = useState(false);
const audioData = useRef<MediaStream | null>(null);
const mediaRecorderRef = useRef<MediaRecorder | null>(null);
const chunksRef = useRef<Blob[]>([]);
useEffect(() => {
const init = async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
});
audioData.current = stream;
} catch (error) {
console.error("Error accessing microphone:", error);
}
};
init();
}, []);
const handleMouseDown = () => {
if (audioData.current) {
chunksRef.current = []; // Reset chunks array for new recording
mediaRecorderRef.current = new MediaRecorder(audioData.current);
mediaRecorderRef.current.ondataavailable = (event) => {
if (event.data && event.data.size > 0) {
chunksRef.current.push(event.data);
}
};
mediaRecorderRef.current.start();
setRecording(true);
}
};
const handleMouseUp = () => {
if (
mediaRecorderRef.current &&
mediaRecorderRef.current.state === "recording"
) {
mediaRecorderRef.current.stop();
setRecording(false);
mediaRecorderRef.current.onstop = async () => {
const blob = new Blob(chunksRef.current, { type: "audio/wav" });
const formData = new FormData();
formData.append("file", blob, "recording.wav");
getTextByAudio(formData).then((res: any) => {
console.log(res.Segments, 6666);
});
// 以下代码为下载录音
// const url = URL.createObjectURL(blob);
// console.log(url, 'y');
// const a = document.createElement("a");
// a.style.display = "none";
// a.href = url;
// a.download = "recording.wav";
// document.body.appendChild(a);
// a.click();
// document.body.removeChild(a);
// URL.revokeObjectURL(url);
};
}
};
return (
<div>
<button
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
style={{ backgroundColor: recording ? "red" : "white" }}
>
{recording ? "正在录音..." : "开始录音"}
</button>
</div>
);
};
export default AudioRecorder;