首页IT科技js实现录音功能(记录–用JS轻松实现一个录音、录像、录屏的工具库)

js实现录音功能(记录–用JS轻松实现一个录音、录像、录屏的工具库)

时间2025-05-04 11:00:15分类IT科技浏览3803
导读:这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助...

这里给大家分享我在网上总结出来的一些知识            ,希望对大家有所帮助

从上面可以看到                  ,首先从 getUserMedia 获取输入流 mediaStream      ,以后还可以打开 video: true 来同步获取视频流            。

然后将 mediaStream 传给 mediaRecorder         ,通过 ondataavailable 来存放当前流中的 blob 数据                  。

最后一步                  ,调用 URL.createObjectURL 来生成预览链接         ,这个 API 在前端非常有用      ,比如上传图片时也可以调用它来实现图片预览                  ,而不需要真的传到后端才展示预览图片      。

在点击 开始 后            ,就可以看到当前网页正在录音啦:

现在把剩下的 暂停 以及 恢复 也实现了:

const pauseRecord = async () => { mediaRecorder.current?.pause(); } const resumeRecord = async () => { mediaRecorder.current?.resume() }

Hooks

在实现简单功能之后   ,我们来尝试一下把上面的功能都封装成 React Hook                  ,首先把这些逻辑都扔在一个函数中               ,然后返回 API:

const useMediaRecorder = () => { const [mediaUrl, setMediaUrl] = useState<string>(); const mediaStream = useRef<MediaStream>(); const mediaRecorder = useRef<MediaRecorder>(); const mediaBlobs = useRef<Blob[]>([]); const startRecord = async () => { mediaStream.current = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }); mediaRecorder.current = new MediaRecorder(mediaStream.current); mediaRecorder.current.ondataavailable = (blobEvent) => { mediaBlobs.current.push(blobEvent.data); } mediaRecorder.current.onstop = () => { const blob = new Blob(mediaBlobs.current, { type: audio/wav }) const url = URL.createObjectURL(blob); setMediaUrl(url); } mediaRecorder.current?.start(); } const pauseRecord = async () => { mediaRecorder.current?.pause(); } const resumeRecord = async () => { mediaRecorder.current?.resume() } const stopRecord = async () => { mediaRecorder.current?.stop() mediaStream.current?.getTracks().forEach((track) => track.stop()); mediaBlobs.current = []; } return { mediaUrl, startRecord, pauseRecord, resumeRecord, stopRecord, } }
在App.tsx里拿到返回值就可以了:
const App = () => { const { mediaUrl, startRecord, resumeRecord, pauseRecord, stopRecord } = useMediaRecorder(); return ( <div> <h1>react 录音</h1> <audio src={mediaUrl} controls /> <button onClick={startRecord}>开始</button> <button onClick={pauseRecord}>暂停</button> <button onClick={resumeRecord}>恢复</button> <button onClick={stopRecord}>停止</button> </div> ); }

封装好之后,现在就可以在这个 Hook 里添加更多的功能了         。

清除数据

在生成 blob url 的时候我们调用了 URL.createObjectURL API 来实现               ,生成后的 url 长这样:

blob:http://localhost:3000/e571f5b7-13bd-4c93-bc53-0c84049deb0a 复制代码

每次 URL.createObjectURL 后都会生成一个 url -> blob 的引用                  ,这样的引用也是会占用资源内存的   ,所以我们可以提供一个方法来销毁这个引用                  。

const useMediaRecorder = () => { const [mediaUrl, setMediaUrl] = useState<string>(); ... return { ... clearBlobUrl: () => { if (mediaUrl) { URL.revokeObjectURL(mediaUrl); } setMediaUrl(); } } }

录屏

上面录音和录像使用 getUserMedia 来实现            ,而 录屏则需要调用 getDisplayMedia 这个接口来实现         。

为了能更好地区分这两种情况                  ,可以给开发者提供 audio, video 以及 screen 三个参数      ,告诉我们应该调哪个接口去获取对应的输入流数据:

const useMediaRecorder = (params: Params) => { const { audio = true, video = false, screen = false, askPermissionOnMount = false, } = params; const [mediaUrl, setMediaUrl] = useState<string>(); const mediaStream = useRef<MediaStream>(); const audioStream = useRef<MediaStream>(); const mediaRecorder = useRef<MediaRecorder>(); const mediaBlobs = useRef<Blob[]>([]); const getMediaStream = useCallback(async () => { if (screen) { // 录屏接口 mediaStream.current = await navigator.mediaDevices.getDisplayMedia({ video: true }); mediaStream.current?.getTracks()[0].addEventListener(ended, () => { stopRecord() }) if (audio) { // 添加音频输入流 audioStream.current = await navigator.mediaDevices.getUserMedia({ audio: true }) audioStream.current?.getAudioTracks().forEach(audioTrack => mediaStream.current?.addTrack(audioTrack)); } } else { // 普通的录像            、录音流 mediaStream.current = await navigator.mediaDevices.getUserMedia(({ video, audio })) } }, [screen, video, audio]) // 开始录 const startRecord = async () => { // 获取流 await getMediaStream(); mediaRecorder.current = new MediaRecorder(mediaStream.current!); mediaRecorder.current.ondataavailable = (blobEvent) => { mediaBlobs.current.push(blobEvent.data); } mediaRecorder.current.onstop = () => { const [chunk] = mediaBlobs.current; const blobProperty: BlobPropertyBag = Object.assign( { type: chunk.type }, video ? { type: video/mp4 } : { type: audio/wav } ); const blob = new Blob(mediaBlobs.current, blobProperty) const url = URL.createObjectURL(blob); setMediaUrl(url); onStop(url, mediaBlobs.current); } mediaRecorder.current?.start(); } ... }

由于我们已经允许用户来录视频以及声音         ,所以在生成 URL 时                  ,也要设置对应的 blobProperty 来生成对应媒体类型的 blobUrl      。

最后在调用 hook 时传入 screen: true         ,可以开启录屏功能:

注意:无论是录像                  、录音      、录屏都是要调用系统的能力      ,而网页只是问浏览器要这个能力                  ,但这样的前提是浏览器已经拥有了系统权限了            ,所以必须在系统设置里允许浏览器有这些权限才能录屏                  。

上面把获取媒体流的逻辑都扔在 getMediaStream 函数里的做法   ,能很方便地用它来获取用户权限                  ,假如我们想在刚加载这个组件时就获取用户摄像头         、麦克风                  、录屏权限               ,就可以在 useEffect 里调用它

useEffect(() => { if (askPermissionOnMount) { getMediaStream().then(); } }, [audio, screen, video, getMediaStream, askPermissionOnMount])

预览

录像只需要在getUserMedia的时候设置{ video: true }就可以实现录像了            。为了能更方便用户在使用时能边录边看效果,我们可以把视频流也返回给用户:

return { ... getMediaStream: () => mediaStream.current, getAudioStream: () => audioStream.current }

用户在拿到这些mediaStream之后就可以直接赋值到srcObject上来进行预览了:

<button onClick={() => previewVideo.current!.srcObject = getMediaStream() || null}> 预览 </button>

禁音

最后               ,我们来实现禁音功能                  ,原理也同样简单   。拿到audioStream里面的audioTrack   ,再将它们设置enabled = false就可以了                  。

const toggleMute = (isMute: boolean) => { mediaStream.current?.getAudioTracks().forEach(track => track.enabled = !isMute); audioStream.current?.getAudioTracks().forEach(track => track.enabled = !isMute) setIsMuted(isMute); }
使用时可以用它来禁用和开启声道:
<button onClick={() => toggleMute(!isMuted)}>{isMuted ? 打开声音 : 禁音}</button>

总结

上面用 WebRTC 的 API 简单地实现了一个录音         、录像      、录屏工具 Hook            ,这里稍微做下总结吧:

getUserMedia 可用于获取麦克风以及摄像头的流 getDisplayMedia 则用于获取屏幕的视频                  、音频流 录东西的本质是 stream -> blobList -> blob url                  ,其中 MediaRecorder 可监听 stream 从而获取 blob 数据 MediaRecorder 还提供了开始            、结束   、暂停                  、恢复等多个与 Record 相关的接口 createObjectURL 与 revokeObjectURL 是反义词      ,一个是创建引用         ,另一个是销毁 禁音可通过 track.enabled = false 关闭音轨来实现

本文转载于:

https://juejin.cn/post/7071101341396893732

如果对您有所帮助                  ,欢迎您点个关注         ,我会定时更新技术文档      ,大家一起讨论学习                  ,一起进步               。

声明:本站所有文章            ,如无特殊说明或标注   ,均为本站原创发布。任何个人或组织                  ,在未征得本站同意时               ,禁止复制               、盗用、采集               、发布本站内容到任何网站                  、书籍等各类媒体平台               。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理                  。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
python中的local(python中local本地对象) pso是什么文件(PSof1.exe – PSof1是什么进程 有什么作用)