我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

本文要描述的功能,来自浏览器的navigator.mediaDevices.getDisplayMedia(),普通网页代码就可以调用。功能的提供方是浏览器,能实现的功能非常强大,能想象的空间很多。浏览器定义这个功能为"共享",本文需求定义它为"截图"。

苏南大叔:浏览器mediaDevices.getDisplayMedia,实现屏幕截图 - 浏览器mediaDevices
浏览器mediaDevices.getDisplayMedia,实现屏幕截图(图5-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。本文测试环境:win10chrome@132.0.6834.160。通过浏览器提供的"共享屏幕"功能,获取浏览器某个标签页或者某个程序的完整界面,然后再把当前帧保存为图片。

截图使用过程

在使用open-webui的过程中,发现了这个比较新奇的"截图"功能,苏南大叔也是首次看到这样"截图"的。扒拉了一下源代码,发现功能来自于navigator.mediaDevices.getDisplayMedia()

苏南大叔:浏览器mediaDevices.getDisplayMedia,实现屏幕截图 - 分享功能截图
浏览器mediaDevices.getDisplayMedia,实现屏幕截图(图5-2)

原版源码

这段代码来自于open-webui这个项目里面的\src\lib\components\channel\MessageInput.svelte文件,截图如下:

苏南大叔:浏览器mediaDevices.getDisplayMedia,实现屏幕截图 - 源码来自open-webui
浏览器mediaDevices.getDisplayMedia,实现屏幕截图(图5-3)

纵观代码,并没有什么太高大上的权限设定,普通的代码即可搞定。

情景复现例子

下面的代码,主要来自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>

苏南大叔:浏览器mediaDevices.getDisplayMedia,实现屏幕截图 - 屏幕截图代码
浏览器mediaDevices.getDisplayMedia,实现屏幕截图(图5-4)

代码解释

这里对上面的代码稍稍做一点解释:

基础配置

{
 video: { cursor: "never" },
 audio: false,
}

只要视频,不要鼠标,不要音频。鼠标会透传[这是一个很难接收的奇怪现象],实际上会增加误解。

视频src

video.srcObject = mediaStream;

比起死循环一帧一帧的canvas重画,这个方案显然好的多。

结束共享

不及时结束共享的话,会在浏览器下方一直有“共享”提示,而且顶部tab标签也会有录制的图片提示。令人紧张不安。

mediaStream.getTracks().forEach((track) => track.stop());

苏南大叔:浏览器mediaDevices.getDisplayMedia,实现屏幕截图 - 及时结束共享
浏览器mediaDevices.getDisplayMedia,实现屏幕截图(图5-5)

相关文章

仔细研究这个navigator.mediaDevices.getDisplayMedia()的话,就会发现它能做的事情很多很强大。除了截图,还能录像,还能结合webrtc远程语音对话等等。

下面的这个链接,有很多高大上的webrtc的例子,欢迎查看。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   h5