浏览器mediaDevices.getDisplayMedia,实现屏幕截图
发布于 作者:苏南大叔 来源:程序如此灵动~
本文要描述的功能,来自浏览器的navigator.mediaDevices.getDisplayMedia()
,普通网页代码就可以调用。功能的提供方是浏览器,能实现的功能非常强大,能想象的空间很多。浏览器定义这个功能为"共享",本文需求定义它为"截图"。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。本文测试环境:win10
,chrome@132.0.6834.160
。通过浏览器提供的"共享屏幕"功能,获取浏览器某个标签页或者某个程序的完整界面,然后再把当前帧保存为图片。
截图使用过程
在使用open-webui
的过程中,发现了这个比较新奇的"截图"功能,苏南大叔也是首次看到这样"截图"的。扒拉了一下源代码,发现功能来自于navigator.mediaDevices.getDisplayMedia()
。
原版源码
这段代码来自于open-webui
这个项目里面的\src\lib\components\channel\MessageInput.svelte
文件,截图如下:
纵观代码,并没有什么太高大上的权限设定,普通的代码即可搞定。
情景复现例子
下面的代码,主要来自open-webui
,略有修改。最终的截图直接下载,并没有变相提交到文件上传窗口。
<button onclick="javascript:screenshot()">截图</button>
<script>
async function screenshot() {
try {
const mediaStream = await navigator.mediaDevices.getDisplayMedia({
video: { cursor: "never" },
audio: false,
});
const video = document.createElement("video");
video.srcObject = mediaStream;
await video.play();
const canvas = document.createElement("canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const context = canvas.getContext("2d");
context.drawImage(video, 0, 0, canvas.width, canvas.height);
const aTag = document.createElement("a");
aTag.href = canvas.toDataURL("image/png");
aTag.download = "screenshot.png";
aTag.click();
window.focus();
mediaStream.getTracks().forEach((track) => track.stop());
video.srcObject = null;
} catch (error) {
console.error("Error capturing screen:", error);
}
}
</script>
代码解释
这里对上面的代码稍稍做一点解释:
基础配置
{
video: { cursor: "never" },
audio: false,
}
只要视频,不要鼠标,不要音频。鼠标会透传[这是一个很难接收的奇怪现象],实际上会增加误解。
视频src
video.srcObject = mediaStream;
比起死循环一帧一帧的canvas
重画,这个方案显然好的多。
结束共享
不及时结束共享的话,会在浏览器下方一直有“共享”提示,而且顶部tab
标签也会有录制的图片提示。令人紧张不安。
mediaStream.getTracks().forEach((track) => track.stop());
相关文章
仔细研究这个navigator.mediaDevices.getDisplayMedia()
的话,就会发现它能做的事情很多很强大。除了截图,还能录像,还能结合webrtc
远程语音对话等等。
下面的这个链接,有很多高大上的webrtc
的例子,欢迎查看。


