Chrome 桌面捕获示例:使用 chrome.desktopCapture 与 getUserMedia 抓取屏幕/窗口流

发布时间:2026/9/21 2:14:16
Chrome 桌面捕获示例:使用 chrome.desktopCapture 与 getUserMedia 抓取屏幕/窗口流 Chrome 桌面捕获示例使用 chrome.desktopCapture 与 getUserMedia 抓取屏幕/窗口流【免费下载链接】chrome-extensions-samplesChrome Extensions Samples项目地址: https://gitcode.com/gh_mirrors/ch/chrome-extensions-samples导读本文基于 chrome-extensions-samples 仓库归档目录下的 desktop-capture 示例完整讲解如何在 Chrome 应用Chrome App中抓取桌面捕获流desktop capture feed从 manifest 中的desktopCapture权限声明到chrome.desktopCapture.chooseDesktopMedia()唤起系统级屏幕/窗口选择器再到通过navigator.webkitGetUserMedia将选中的桌面流渲染到video元素。读完本文你将掌握桌面屏幕共享类应用的最小可运行实现并理解其在 WebRTC 会议、远程协助、录屏工具等场景中的底层数据通路。示例概览与定位该示例位于仓库的_archive归档区示例目录采用 Chrome Appsmanifest_version: 2体系构建。核心文件仅 5 个是一个麻雀虽小、五脏俱全的最小演示文件职责manifest.json声明应用入口与desktopCapture权限background.js监听chrome.app.runtime.onLaunched创建应用窗口index.html承载video预览与启停按钮的界面app.js核心逻辑选择桌面源、获取媒体流、启停切换assets/screenshot_1280_800.png运行效果截图示例的实际运行效果如下左侧为捕获到的 YouTube 页面窗口流右侧为另一个浏览器窗口界面底部按钮处于 Disable Capture 状态表示捕获正在进行中三步走桌面捕获的核心工作流程从 app.js 的源码可以提炼出桌面捕获的完整链路共三步声明权限在 manifest 中声明desktopCapture权限否则 API 调用会被拒绝。选择桌面源调用chrome.desktopCapture.chooseDesktopMedia(types, callback)Chrome 会弹出系统级选择器用户可从中选择要共享的屏幕screen或窗口window回调拿到一个不透明的desktop_id即chromeMediaSourceId。消费媒体流把desktop_id通过navigator.webkitGetUserMedia的mandatory约束传入chromeMediaSource: desktop、chromeMediaSourceId: desktop_id获得真实媒体流后绑定到video播放。其中步骤 2 的desktop_id是一次性令牌必须立即在getUserMedia中消费不能在多次请求间复用。示例源码中的回调签名是onAccessApproved(desktop_id)当用户取消选择器时desktop_id为undefinedchrome.desktopCapture.chooseDesktopMedia([screen, window], onAccessApproved); function onAccessApproved(desktop_id) { if (!desktop_id) { console.log(Desktop Capture access rejected.); return; } // 拿到 desktop_id 后立即发起 getUserMedia 请求…… }manifest 权限与入口配置详解manifest.json 是整条链路的起点其关键字段如下{ name: Desktop Capture Sample, version: 2, manifest_version: 2, icons: { 16: desktop.png, 128: desktop.png }, app: { background: { scripts: [background.js] } }, permissions: [ desktopCapture ] }逐个字段说明其作用permissions: [desktopCapture]唯一必需的权限。它授权应用唤起桌面源选择器并获取desktop_id。缺少它chooseDesktopMedia无法工作。app.background.scriptsChrome Apps 的入口机制。background.js常驻后台负责在onLaunched时创建应用窗口见下文。icons应用图标示例统一复用了 desktop.png256×256manifest 中按 16 与 128 两种尺寸声明。manifest_version: 2Chrome Apps 时代的标准版本号。需要说明的是该示例位于仓库_archive归档目录Chrome Apps 体系已被逐步淘汰本文内容适合作为桌面捕获 API 工作原理的技术参考而非当前 Manifest V3 扩展的新项目起点。后台入口创建应用窗口background.js 只有 15 行演示了 Chrome Apps 的两个基础 APIchrome.app.runtime.onLaunched.addListener(function() { chrome.app.window.create(index.html, { id: desktopCaptureID, innerBounds: { width: 700, height: 600 } }); });chrome.app.runtime.onLaunched应用启动事件对应 README 中列出的 Runtime API。Chrome 在用户启动应用时触发该事件这里作为创建窗口的时机。chrome.app.window.create创建应用窗口对应 README 中列出的 Window API。id: desktopCaptureID让窗口在多次启动间保持身份恢复几何状态innerBounds指定 700×600 的初始内容区尺寸。这种事件驱动创建窗口的模式与 Manifest V3 扩展中chrome.runtime.onInstalled/ action popup 的启动范式完全不同属于 Chrome Apps 特有的生命周期模型。界面层video 预览与启停按钮index.html 的结构极简一个video autoplay用于播放捕获流一个button用于切换捕获启停。关键样式约束video元素宽 640px、高 480px背景为半透明黑rgba(0,0,0,0.25)同时以 desktop.png 居中作为占位底图——捕获尚未开始时视频区域显示应用图标占位。autoplay属性保证stream一旦通过src赋值便立即渲染无需用户额外点击播放。界面在 JS 侧通过document.querySelector(button)与document.querySelector(video)两个选择器与逻辑层解耦逻辑全部收敛在 app.js。逻辑层启停切换与 getUserMedia 约束剖析启停状态机app.js 用一个模块级布尔变量desktop_sharing维护捕获状态toggle()是唯一的入口var desktop_sharing false; var local_stream null; function toggle() { if (!desktop_sharing) { chrome.desktopCapture.chooseDesktopMedia([screen, window], onAccessApproved); } else { desktop_sharing false; if (local_stream) local_stream.stop(); local_stream null; document.querySelector(button).innerHTML Enable Capture; console.log(Desktop sharing stopped...); } }启用路径desktop_sharing false时调用chooseDesktopMedia等待用户选择源。停用路径调用local_stream.stop()显式停止本地流、重置状态并把按钮文案改回 Enable Capture。这也是常见 WebRTC 屏共享应用清理资源的范式。按钮通过 app.js 的click事件监听绑定到toggle()。onAccessApproved 与 getUserMedia 约束用户批准选择后进入onAccessApproved这是整个示例的核心function onAccessApproved(desktop_id) { if (!desktop_id) { console.log(Desktop Capture access rejected.); return; } desktop_sharing true; document.querySelector(button).innerHTML Disable Capture; console.log(Desktop sharing started.. desktop_id: desktop_id); navigator.webkitGetUserMedia({ audio: false, video: { mandatory: { chromeMediaSource: desktop, chromeMediaSourceId: desktop_id, minWidth: 1280, maxWidth: 1280, minHeight: 720, maxHeight: 720 } } }, gotStream, getUserMediaError); }这里的关键约束参数及其含义参数值作用chromeMediaSourcedesktop声明媒体源类型为桌面捕获是普通摄像头/麦克风getUserMedia与桌面捕获的分水岭chromeMediaSourceIddesktop_idchooseDesktopMedia回调返回的一次性源标识指定具体共享哪块屏幕/哪个窗口minWidth/maxWidth1280将视频分辨率强制锁定为 1280 宽min与max相等即为硬性约束minHeight/maxHeight720将视频分辨率强制锁定为 720 高audiofalse本例仅捕获画面不捕获系统音频分辨率约束的取法min与max相等表示必须恰好是这个分辨率这是一种简化的固定分辨率写法。若希望捕获到用户屏幕的原始分辨率则应像同仓库进阶示例那样把maxWidth/maxHeight设置为screen.width/screen.height见下文进阶变体。流渲染与异常处理成功回调gotStream(stream)负责把流挂到video并处理流结束事件function gotStream(stream) { local_stream stream; document.querySelector(video).src URL.createObjectURL(stream); stream.onended function() { if (desktop_sharing) { toggle(); } }; } function getUserMediaError(e) { console.log(getUserMediaError: JSON.stringify(e, null, ---)); }两个值得注意的细节URL.createObjectURL(stream)这是 Chrome Apps 时代的流绑定方式。源用户关闭了被共享的窗口、系统停止共享等结束后stream.onended触发代码通过toggle()自动回到停止状态并复位按钮形成完整的生命周期闭环。getUserMediaError的JSON.stringify(e, null, ---)以三段式缩进序列化错误对象便于在控制台诊断权限缺失、约束冲突等失败场景。进阶变体完整版 desktopCapture 示例的四个扩展点仓库的 _archive/mv2/api/desktopCapture 目录提供了一个更完整的桌面捕获变体可以作为理解chrome.desktopCapture全貌的补充参考与本文示例形成对比四种可选源类型const DESKTOP_MEDIA [screen, window, tab, audio];见 app.js。除屏幕与窗口外还支持标签页捕获与音频捕获而本文示例仅请求[screen, window]。主动取消选择器通过chrome.desktopCapture.cancelChooseDesktopMedia(pending_request_id)取消尚未完成的用户选择app.js适用于用户点了共享又反悔的场景。后台页发起选择chooseDesktopMedia也可以从后台脚本经chrome.runtime.onMessage触发background.js说明唤起选择器与消费流两个环节可以在不同上下文完成。音频约束与 WebRTC 回环进阶版通过options.canRequestAudioTrack判断所选源是否允许音频轨道并在gotStream中构造pc1/pc2两个RTCPeerConnection做本地回环app.js用于演示桌面流 WebRTC 信令如何衔接——这正是视频会议/远程协作类产品把桌面流通过 SDP offer/answer 发给远端的前置实验。常见问题与注意事项结合源码约束与 API 特性实践中有几点必须注意权限缺失manifest 未声明desktopCapture时chooseDesktopMedia不会弹出选择器且回调收到空desktop_id先检查permissions字段。desktop_id的一次性desktop_id有效期短且不可复用必须在回调内立即传入getUserMedia不要跨调用保存。用户取消/拒绝回调参数为undefined示例中直接return并输出Desktop Capture access rejected.UI 上应给出相应提示而非静默失败。分辨率约束冲突把minWidth/maxWidth设为固定值会强制缩放若希望 1:1 捕获可改用maxWidth: screen.width、maxHeight: screen.height的写法。清理资源停止共享时显式调用local_stream.stop()并监听stream.onended自动复位 UI 状态避免共享已结束但按钮仍显示 Disable的假死状态。体系适用性本示例基于 Chrome Appsmanifest_version: 2位于_archive归档目录仅作为 API 原理的参考实现面向当前的扩展开发应遵循 Manifest V3 体系。小结desktop-capture 示例用不到百行代码把chrome.desktopCapture桌面捕获的完整链路串了起来manifest 声明权限 →chooseDesktopMedia唤起系统选择器 →getUserMedia携带chromeMediaSource/chromeMediaSourceId约束获取流 → 绑定video预览并按需启停。它清晰地展示了桌面捕获 API 与 WebRTC 生态的结合点进阶版中的RTCPeerConnection回环即为例证对理解录屏、远程协助、在线会议等产品的屏幕共享能力落地路径具有直接的参考价值。如需继续深入可对照阅读 示例 README 与进阶变体 _archive/mv2/api/desktopCapture/app.js。【免费下载链接】chrome-extensions-samplesChrome Extensions Samples项目地址: https://gitcode.com/gh_mirrors/ch/chrome-extensions-samples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考