构建高效、跨平台的录音软件——基于Electron、webrtc和React的完美结合
背景
在现代科技日益发展的今天,我们的电脑和手机设备能够完成许多日常任务,其中之一就是录音。无论是进行会议记录、语音备忘录还是创作音乐,录音是我们生活中经常用到的功能之一。本文将介绍如何使用
Electron
、webrtc
和React
搭建一个高效、跨平台的录音软件,帮助使用者轻松完成各种录音任务。
工具
- electron
- react
- antd
- webrtc
Electron和React介绍
Electron
和React
的协同 Electron
是一个基于Chromium
和Node.js
的开发框架,用于构建跨平台的桌面应用程序。通过与React
的结合,可以轻松实现复杂的用户界面和交互体验,既能满足用户需求,又能提高开发效率。因此,将Electron
和React
应用于录音软件的开发中,能够为用户提供更好的体验,并且从开发者角度来看,更加便捷和高效。
webrtc介绍
WebRTC
技术的应用 WebRT
C是一项用于浏览器之间实时通信的开放性标准,它提供了音频、视频和数据传输的能力,适用于广泛的应用场景。在录音软件中,我们可以借助WebRTC技术实现实时录音功能,并且支持在线分享和协作。用户可以通过网页链接,将录音内容分享给其他人,并实现实时的在线播放和评论,极大地提高了录音的灵活性和可用性。
实现
要在WebRTC
和React
中实现录音功能,我们可以按照以下步骤进行:
步骤一:设置WebRTC音频流
- 导入
getUserMedia
函数,这是一个WebRTC提供的用于获取音频和视频流的函数。 - 使用
getUserMedia
函数请求用户授权获取音频流,并将其保存在React组件中的状态中。 - 将音频流绑定到HTML5的
audio
或video
元素上,以便实时预览录音。
// html
<div
className={`${styles.recordAudio} ${
window.isElectron ? styles.electron : styles.web
}`}
>
<div className="timer">
<Timer
seconds={timer.seconds}
minutes={timer.minutes}
hours={timer.hours}
/>
</div>
<Wavesurfer ref={wavesurferRef} />
</div>
// js
const wavesurferRef = useRef<any>(); // 音波图对象
const mediaStream = useRef<MediaStream>(); //媒体流对象
const mediaRecorder = useRef<MediaRecorder>(); // 媒体录制器对象
const recordedChunks = useRef<Blob[]>([]); // 存储录制的音频数据
const audioTrack = useRef<any>(); // 音频轨道对象
const [isPause, setIsPause] = useState(false); // 标记是否暂停
const [isRecording, setIsRecording] = useState(false); // 标记是否正在录制
const [isMute, setIsMute] = useState(false); // 标记是否静音
function startRecording() {
navigator.mediaDevices
.getUserMedia({ audio: true })
.then((stream) => {
mediaStream.current = stream;
audioTrack.current = stream.getAudioTracks()[0];
audioTrack.current.enabled = true; // 开启音频轨道
mediaRecorder.current = new MediaRecorder(stream);
mediaRecorder.current.start();
setIsRecording(true);
wavesurferRef.current.play();
timer.start();
console.log("开始录音...");
})
.catch((error) => {
console.error("无法获取麦克风权限:", error);
});
}
步骤二:录音控制
- 创建React组件,包括开始、暂停和停止录音的按钮。
<div className="recorderTools">
<Button
shape="circle"
icon={<BsTrash />}
className="toolbarIcon resetBtn"
title="删除"
disabled={!isRecording}
onClick={stopRecording}
/>
{isRecording ? (
<Button
danger
type="primary"
shape="circle"
icon={<BsCheckLg />}
className="toolbarIcon stopBtn"
title="保存"
disabled={!isRecording}
onClick={saveRecording}
/>
) : (
<Button
danger
type="primary"
shape="circle"
icon={<BsRecordFill />}
className="toolbarIcon playBtn"
title="开始"
onClick={startRecording}
/>
)}
{isPause ? (
<Button
type="primary"
shape="circle"
icon={<BsPlayFill />}
className="toolbarIcon resumeBtn"
title="继续"
disabled={!isRecording}
onClick={resumeRecording}
/>
) : (
<Button
type="primary"
shape="circle"
icon={<BsPauseFill />}
className="toolbarIcon pauseBtn"
title="暂停"
disabled={!isRecording}
onClick={pauseRecording}
/>
)}
</div>
- 使用
MediaRecorder
接口,它是WebRTC提供的用于录制音频和视频的接口。 - 在开始录音按钮的点击事件中,创建一个新的
MediaRecorder
实例,将音频流作为输入。 - 定义录音的文件格式和音频编码等设置。
- 绑定
ondataavailable
和onstop
事件监听器,分别处理录制过程中的音频数据和录制结束时的操作。 - 在停止录音按钮的点击事件中,调用
stop
方法停止录音,并触发onstop
事件。
mediaRecorder.current = new MediaRecorder(stream);
mediaRecorder.current.addEventListener("dataavailable", (e) => {
if (e.data.size > 0) {
recordedChunks.current.push(e.data);
}
});
mediaRecorder.current.addEventListener("stop", () => {
isSave.current && exportRecording();
});
// 静音
function muteRecording() {
if (audioTrack.current) {
audioTrack.current.enabled = false; // 关闭音频轨道
setIsMute(true);
console.log("录音已静音");
}
}
// 取消静音
function unmuteRecording() {
if (audioTrack.current) {
audioTrack.current.enabled = true; // 开启音频轨道
setIsMute(false);
console.log("取消静音");
}
}
// 恢复录制
function resumeRecording() {
if (isPause && mediaRecorder.current.state === "paused") {
mediaRecorder.current.resume();
setIsPause(false);
wavesurferRef.current.play();
timer.start();
console.log("恢复录音...");
}
}
// 暂停录制
function pauseRecording() {
if (!isPause && mediaRecorder.current.state === "recording") {
mediaRecorder.current.pause();
setIsPause(true);
wavesurferRef.current.pause();
timer.pause();
console.log("录音已暂停");
}
}
步骤三:保存和导出录音文件
- 在
onstop
事件中,将录音数据存储在React组件的状态中。 - 添加保存和导出按钮,用于将录音保存成文件或导出为其他格式。
- 在保存按钮的点击事件中,将录音数据转换成Blob对象,并使用
URL.createObjectURL
生成文件的URL。 - 可以使用
<a>
标签的download
属性,将URL绑定到href
上,以便用户可以下载录音文件。
// 停止录制,并将录制的音频数据导出为 Blob 对象
function stopRecording() {
if (isRecording) {
mediaRecorder.current.stop();
mediaStream.current?.getTracks().forEach((track) => track.stop());
setIsRecording(false);
timer.reset(null, false);
wavesurferRef.current.reset();
recordedChunks.current = [];
console.log("录音完成!");
}
}
// 导出录制的音频文件
function saveRecording() {
stopRecording();
isSave.current = true;
}
// 导出录制的音频文件
function exportRecording() {
if (recordedChunks.current.length > 0) {
const blob = new Blob(recordedChunks.current, { type: "audio/webm" });
const url = URL.createObjectURL(blob);
if (window.electronAPI) {
window.electronAPI.sendRaDownloadRecord(url);
} else {
const link = document.createElement("a");
link.href = url;
link.download = `pear-rec_${+new Date()}.webm`;
link.click();
recordedChunks.current = [];
isSave.current = false;
}
}
}
需要注意的是,WebRTC和React只提供了录音的底层功能,如获取音频流、录音和编码等,而录音软件的具体界面设计和逻辑控制需要根据实际需求进行开发。同时,为了确保在不同浏览器和平台上的兼容性,可能需要进行一些浏览器特定的处理和适配。
总结
通过Electron
、WebRTC
和React
的结合,我们可以构建一款创新的录音软件,将实时录音和在线分享功能融入其中,为用户提供更加灵活且高品质的录音体验。同时,开发者也可以享受Electron
和React
带来的开发效率和便捷性。我们相信,这样的录音软件将成为用户录音需求的最佳解决方案,并推动录音领域的进一步创新。
Q&A
- Q: 有源码吗?
当然有,地址如下:github.com/027xiguapi/…,有兴趣的话可以大家一起探讨,同时也欢迎大家fork
和star
转载自:https://juejin.cn/post/7272523490498215991