媒体数据获取与播放
持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
写作背景:
在学习 WebRTC 音视频开发前,我们先来学习了解一下音频、视频等媒体数据的获取与播放。了解一下入门级的 API 的使用。
API 介绍:
MediaDevices:
developer.mozilla.org/zh-CN/docs/…
这个 API 提供了如何访问媒体数据输入的设备,如 PC 电脑的摄像头、麦克风、屏幕共享等。
MediaDevices.getUserMedia():
通过传入不同的约束提条件来获取到不同的媒体数据流,前提的用户授权使用的情况下。使用到摄像头、麦克风时浏览器就会对用户提示并希望得到用户授权。
MediaDevices.getDisplayMedia():
在得到用户授权后可以选择屏幕、窗口、Chrome 标签页进行媒体流的获取。在获取 Mac 屏幕/窗口进行屏幕共享的时候需要在 Mac 的【偏好设置】=>【安全与隐私】=>【隐私】=>【屏幕录制】中勾选允许Chrome。
获取摄像头视频数据流:
- 设置约束条件,允许视频,禁用音频:
const constraints: MediaStreamConstraints = { audio: false, video: true };
- 同步调用getUserMedia得到媒体流:
const stream = await navigator.mediaDevices.getUserMedia(constraints);
- 通过媒体流得到设备的信息,如设备名称:
const videoTracks = stream.getVideoTracks(); console.log(videoTracks[0].label);
- 通过 video 标签播放媒体流,这里不适用 src 属性,要使用 srcObject 属性,这个属性是HTMLMediaElement 类的其中一员,所以我们在 TypeScript 编写代码的时候在泛型约束时指定了它:
const video = ref<HTMLMediaElement>(); const openCamera = async () => { try { const constraints: MediaStreamConstraints = { audio: false, video: true }; const stream = await navigator.mediaDevices.getUserMedia(constraints); const videoTracks = stream.getVideoTracks(); console.log(videoTracks[0].label); video.value!.srcObject = stream; } catch (error) { message.error(`获取用户媒体数据错误:${error}`); } }; // video元素定义 <video ref="video" autoplay></video>
获取麦克风音频数据流:
与上面获取摄像头媒体数据类似,只是使用不同的约束与不同的播放标签,请看完整代码:
const audio = ref<HTMLMediaElement>(); const openMicrophone = async () => { try { const constraints: MediaStreamConstraints = { audio: true, video: false }; const stream = await navigator.mediaDevices.getUserMedia(constraints); const audioTracks = stream.getAudioTracks(); console.log(audioTracks[0].label); audio.value!.srcObject = stream; } catch (error) { message.error(`获取用户媒体数据错误:${error}`); } }; // audio元素定义 <audio ref="audio" autoplay controls></audio>
截取视频流输入到画布:
在进行播放摄像头数据的过程中我们可以截取其中的一个画面输出到画布中,这个案例工作前需要正常得到摄像头返回的媒体数据流:
因为我们要得到 video 标签的一个宽高来设置我们的画布尺寸,所以在泛型约束的时候我们增加一个HTMLVideoElement 类型约束:
const captureVideo = async () => { const videoSource = video.value as HTMLVideoElement; canvas.value!.width = videoSource.videoWidth; canvas.value!.height = videoSource.videoHeight; canvas.value ?.getContext("2d") ?.drawImage(videoSource, 0, 0, canvas.value!.width, canvas.value!.height); }; // canvas元素定义 <canvas ref="canvas"></canvas>
通过浏览器共享屏幕:
我们这里有少许的不同,我们需要使用 getDisplayMedia,但是同样将得到的媒体流交由 video 标签播放:
const shareScreen = async () => { try { const stream = await navigator.mediaDevices.getDisplayMedia({ video: true, }); const videoTracks = stream.getVideoTracks(); console.log(videoTracks[0].label); video.value!.srcObject = stream; } catch (error) { console.log((error as Error).name); message.error(`获取用户媒体数据错误:${error}`); } }; // video元素定义 <video ref="video" autoplay></video>
注:我们上面有提到的,屏幕录制的权限,一定要在系统偏好中提前设置,要不你的看到 NotAllowedError: Permission denied by system 的❌错误提示。
结语:
通过上面 4 个场景用例我们熟悉了在浏览器中通过规范的 API 来实现媒体数据的读取与播放,大大节省了音视频在 web 端开发的难度,明天继续学!
var code = "7bfe37f3-fd67-4269-b546-343a74a9b472"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!