前言
在当今这个信息爆炸的时代,屏幕录制已成为一种较为常见的需求。无论是制作教学视频、演示产品功能、记录游戏精彩瞬间,还是进行远程协作,录屏功能都扮演着至关重要的角色。
你是否曾想过,无需安装任何第三方软件,仅通过浏览器就能轻松实现屏幕录制?这听起来似乎有些不可思议,但 Web API 中的 getDisplayMedia
接口却让这一切成为可能。
getDisplayMedia
是一个强大的 API,它允许 Web 应用程序捕获屏幕或特定窗口的内容,并将其作为媒体流进行处理。这意味着你可以像操作摄像头或麦克风一样,对屏幕内容进行录制、编辑、甚至实时传输。
在传统的屏幕录制方案中,我们通常需要依赖桌面应用程序或浏览器插件。这些方案往往存在以下问题:
- 平台限制: 桌面应用程序通常只能在特定操作系统上运行,而浏览器插件也可能受限于浏览器类型。
- 安装繁琐: 用户需要下载、安装额外的软件或插件,这增加了使用门槛。
- 安全隐患: 第三方软件或插件可能存在安全风险,甚至泄露用户隐私。
- 性能问题: 某些录屏软件可能会占用大量系统资源,导致电脑运行缓慢。
而 getDisplayMedia
的出现,完美地解决了上述问题。它具有以下优势:
- 跨平台: 只要浏览器支持
getDisplayMedia
,就可以在任何操作系统上使用,无需考虑平台兼容性。 - 无需安装: 作为 Web API 的一部分,
getDisplayMedia
无需任何额外安装,直接在浏览器中即可使用。 - 安全可靠:
getDisplayMedia
的使用受到浏览器的严格控制,用户可以明确选择要共享的屏幕内容,避免隐私泄露。 - 性能优异: 浏览器对
getDisplayMedia
进行了优化,录制过程流畅,资源占用低。
Web API经过长期的发展,尤其是最近,发展相当迅猛,现在已经支持很多功能了,一些原生就支持的功能也是做的相当好,这也带来了现在一些跨端应用的升级。有许多跨端的App框架可以考虑,就比如Tauri2.0就开启了跨端,又或者Uni X,现在也是在做原生级别的跨端应用框架。
如果你对这个API本身很感兴趣,建议看看原文
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia。
在本文中,将直接开始使用Web API中MediaDevices的getDisplayMedia方法来实现录屏或直播效果。(如果你有兴趣可以继续探索),我将带领你深入了解 getDisplayMedia
的方方面面。我们将从基本概念入手,逐步探索其用法、参数配置、事件处理,以及如何结合其他 Web API 实现完整的录屏功能。
无论你是一位 Web 开发新手,还是经验丰富的工程师,相信都能从本文中获益匪浅。让我们一起踏上这段精彩的旅程,揭开 getDisplayMedia
的神秘面纱吧!
一、认识getD该处使用的url网络请求的数据。
—isplayMedia
getDisplayMedia方法是浏览器Web API中MediaDevices的一个函数。它允许网页开发者在浏览器中捕获和共享用户设备(如屏幕、窗口或摄像头)的媒体内容。
通过调用getDisplayMedia方法,网页开发者可以请求用户允许共享屏幕、窗口或摄像头的权限。一旦用户授权,网页开发者就可以在网页中获取媒体流,并将其用于实时通信、视频录制、屏幕分享等功能。
使用getDisplayMedia方法的一般步骤如下:
-
调用getDisplayMedia方法,传递一个MediaStreamConstraints对象作为参数,该对象描述了要请求的媒体类型和约束条件。
-
如果用户允许共享媒体内容,则返回一个Promise对象,该Promise对象解析为一个MediaStream对象。如果用户拒绝共享或硬件不可用,则Promise对象会被拒绝。
-
使用返回的媒体流进行进一步的操作,如获取媒体流中的轨道,显示在网页中,发送到服务器等。
getDisplayMedia方法该处使用的url网络请求的数据。
—通常与其他媒体相关的API(如MediaRecorder和WebRTC)结合使用,以便实现功能丰富的实时通信和多媒体应用程序。
二、使用步骤
经过我查找getDisplayMedia的相关资料,getDisplayMedia的使用方法基本上可以分为两种:
- 获取流,然后设置到一个新建的video标签,然都对video的流进行处理。
- 获取流,然后使用MediaStreamTrackProcessor转换为视频帧进行处理。
方法2会有更多的用处,比如实现在线剪辑,批量剪辑,以及AI剪辑都有很大的帮助。除此以外,还有另一种使用stream API的通道写法,但是我写了怎么也不生效,如果有大佬还麻烦请帮我看看怎么回事。
1.使用方法一实现录屏
方法一其实质就是将视频源直接设置到video标签,然后video标签会自动处理一些数据,算是比较常用的方式,代码如下
// 获取canvas元素
let canvas = document.getElementById('canvas');
// 获取2d上下文
let ctx = canvas.getContext('2d');
// 创建video标签
let video = document.createElement('video');
// 异步或者不异步都行,选择你喜欢的一种方式
async function start() {
const userStream = await navigator.mediaDevices.getDisplayMedia({
// 开启视频
video: true,
// 关闭音频,选择适合你的
audio: false
});
// video标签的源设置为获取到的流
video.srcObject = userStream;
// 播放视频
video.play();
// 请求动画帧
window.requestAnimationFrame(frame);
}
// 这里是每帧进行的处理
frame = () => {
if (video.readyState == video.HAVE_ENOUGH_DATA) {
canvas.hidden = false;
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 做其他事情,比如绘制二维码或者文字或者扫描二维码,只要你有想法
}
window.requestAnimationFrame(frame);
}
function stop(){
video.srcObject.getTracks().forEach((track) => track.stop());
}
2.使用方法二实现录屏
方法二是官方给出的结合stream API之前的一种死循环的方式来读取视频流的每帧,然后绘制到canvas。
// 获取canvas元素
let canvas = document.getElementById('canvas');
// 获取2d上下文
let ctx = canvas.getContext('2d');
// 创建video标签
let video = document.createElement('video');
// 异步或者不异步都行,选择你喜欢的一种方式
const track = null;
async function start() {
const userStream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: false
});
track = userStream.getVideoTracks()[0];
const processor = new MediaStreamTrackProcessor(track);
const reader = processor.readable.getReader();
while (true) {
const {done, value} = await reader.read();
if (done) {
break;
}
const frame = value;
// 这里对每帧进行处理
ctx.drawImage(frame, 0, 0, canvas.width, canvas.height);
frame.close();
}
}
function stop(){
track.stop();
}
3. 运行效果
延伸
- 要想实现完整的录屏功能,还需要实现保存录像文件等功能,在后面如果接触到了文件操作等,我会详细的写如何将录制的文件保存下来。 如果你现在就有兴趣想要研究,建议看前面的
MDN
。 - 该功能可以使用谷歌的
stream api
来做,但是我的代码一直不能正常运行,希望能有大佬帮我看看。 - 除了Stream API,实际上还可以用rxjs做,目前我也在研究中,如果有了结果我会发另一篇文章来介绍如何使用rxjs来实现,
rxjs
对于流操作还是比较擅长的。