ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

使用 Screen-Capturing.js 与 desktopCapture 扩展实现 WebRTC 屏幕捕获:完整集成指南

使用 Screen-Capturing.js 与 desktopCapture 扩展实现 WebRTC 屏幕捕获:完整集成指南 示例工程【免费下载链接】WebRTC-ExperimentWebRTC, WebRTC and WebRTC. Everything here is all about WebRTC!!项目地址https://gitcode.com/gh_mirrors/we/WebRTC-Experiment点击查看免费下载导读Screen-Capturing.js 是 WebRTC-Experiment 仓库中用于在网页端捕获屏幕/应用窗口 MediaStream 的前端脚本库它依赖配套的 Chrome desktopCapture 扩展Chrome-Extensions/Screen-Capturing.js/Screen-Capturing.js。本指南将带你走通下载并改造扩展 → 修改 manifest.json 白名单 → 在页面中引入脚本 → 调用各 API 捕获屏幕与系统音频的完整链路并结合仓库源码剖析底层 postMessage 消息协议与 chrome.desktopCapture 调用原理。读完本文你可以在自己的 HTTPs 域上独立完成 Chrome 屏幕共享的集成与排错。重要前提该扩展自 2019 年起已停止维护原作者明确声明use at your own risk。新项目请优先使用浏览器原生的getDisplayMediaAPI本文中的扩展方案仅适用于需要兼容旧版 Chrome34或需要sourceId细粒度控制的遗留场景。先看现代替代方案getDisplayMedia在深入扩展方案之前务必先掌握现代浏览器提供的原生屏幕捕获 API。README 开篇即给出推荐的统一封装它按能力降级依次尝试navigator.getDisplayMedia、navigator.mediaDevices.getDisplayMedia最后才回退到扩展方案getScreenStream(function(screenStream) { video.srcObject screenStream; }); function getScreenStream(callback) { if (navigator.getDisplayMedia) { navigator.getDisplayMedia({ video: true }).then(screenStream { callback(screenStream); }); } else if (navigator.mediaDevices.getDisplayMedia) { navigator.mediaDevices.getDisplayMedia({ video: true }).then(screenStream { callback(screenStream); }); } else { getScreenId(function(error, sourceId, screen_constraints) { navigator.mediaDevices.getUserMedia(screen_constraints).then(function(screenStream) { callback(screenStream); }); }); } }getDisplayMedia由浏览器直接弹窗让用户选择整个屏幕 / 应用窗口 / 标签页无需安装任何扩展、无需部署白名单这是目前唯一推荐的方案。只有当用户浏览器不支持该 API 时才需要走下文的扩展路径。工作原理与消息协议源码剖析Screen-Capturing.js 本身不直接调用chrome.desktopCapture它通过postMessage 消息协议与扩展的 content-script 通信扩展的 background-script 再调用底层 API 返回sourceId。整条链路由三个脚本协作完成脚本角色仓库路径Screen-Capturing.js网页侧 API 封装发送/接收 postMessageChrome-Extensions/Screen-Capturing.js/Screen-Capturing.jscontent-script.js网页与 background 之间的消息中转站Chrome-Extensions/desktopCapture/content-script.jsbackground-script.js调用chrome.desktopCapture.chooseDesktopMedia返回 sourceIdChrome-Extensions/desktopCapture/background-script.js网页侧postMessage 的发送与接收Screen-Capturing.js 在加载时注册message事件监听并且只处理同源消息window.addEventListener(message, function(event) { if (event.origin ! window.location.origin) { return; } onMessageCallback(event.data); });onMessageCallback处理三类响应见 Screen-Capturing.js收到字符串PermissionDeniedError用户点了取消直接以该字符串回调便于调用方判断收到rtcmulticonnection-extension-loaded扩展通知自己已在页面中注入脚本据此将内部状态chromeMediaSource置为desktop收到携带sourceId的对象扩展共享了临时 sourceId同时携带canRequestAudioTrack布尔值表示本次选择的源是否允许捕获系统音频。中转站content-scriptcontent-script.js 维护一个rtcmulticonnectionMessages白名单对象包含are-you-there、get-sourceId、audio-plus-tab三个字符串只放行白名单内的消息避免与其他无关 postMessage 冲突网页发来are-you-there时content-script 直接回复rtcmulticonnection-extension-loaded让网页快速探测扩展存在性网页发来get-sourceId或audio-plus-tab或携带get-custom-sourceId数组的消息时通过chrome.runtime.connect()建立的 Port 转发给 background-scriptbackground 返回的消息再通过window.postMessage(message, *)广播回网页。底层background-script 与 chooseDesktopMediabackground-script.js 在chrome.runtime.onConnect中监听 Port 消息根据消息类型配置screenOptions并调用chrome.desktopCapture.chooseDesktopMedia(screenOptions, port.sender.tab, onAccessApproved)get-sourceId使用默认选项[screen, window]让用户选择整屏或某个应用窗口audio-plus-tab将选项扩展为[screen, window, audio, tab]即额外允许捕获标签页和系统音频{ get-custom-sourceId: [...] }使用调用方自定义的选项数组。用户确认后onAccessApproved(sourceId, opts)被回调若sourceId为空点了取消回传PermissionDeniedError否则回传{ sourceId: sourceId, canRequestAudioTrack: !!opts.canRequestAudioTrack }。这个 sourceId 最终被写入 getUserMedia 的chromeMediaSourceId约束中从而拿到屏幕 MediaStream。第一步下载并改造 desktopCapture 扩展使用 Screen-Capturing.js 前必须先准备扩展。仓库中的扩展源码位于 Chrome-Extensions/desktopCapture你需要自行下载、改造并发布下载 desktopCapture 目录全部文件修改 manifest.json 中 content-scripts 的matches白名单把默认的https://www.webrtc-experiment.com/*替换为你自己的域名通过chrome://extensions/以加载已解压的扩展程序方式本地测试或打包成 ZIP 上传 Google Web Store 发布。manifest.json 关键配置原仓库 manifest.json 的完整配置如下version 3.7、manifest_version 2{ name : Screen Capturing, author: Muaz Khan, version : 3.7, manifest_version : 2, minimum_chrome_version: 34, description : Capture full-screen or specific applications screen on any HTTPs domain!, background: { scripts: [background-script.js], persistent: false }, content_scripts: [ { js: [ content-script.js ], all_frames: true, run_at: document_end, matches: [https://www.webrtc-experiment.com/*] }], icons : { 48 : icon.png }, permissions: [ desktopCapture ], web_accessible_resources: [ icon.png ] }你需要改动的核心只有matches例如换成你的域名matches: [https://www.your-domain.com/*]配置要点说明minimum_chrome_version: 34chrome.desktopCaptureAPI 自 Chrome 34 起可用这是扩展的最低兼容版本permissions中的desktopCapture声明使用桌面捕获 API 的权限all_frames: true页面中所有 iframe 都会注入 content-script保证getScreenId这类 iframe 嵌套方案也能工作background.persistent: false使用事件驱动非持久后台页web_accessible_resources中的icon.png网页侧通过chrome-extension://id/icon.png探测扩展安装状态时需要使用它见下文getChromeExtensionStatus原理。第二步在页面中引入 Screen-Capturing.js扩展就绪后在你的 HTTPs 页面中引入脚本仓库同时提供 CDN 用法与本地 index.html 演示页script srchttps://www.webrtc-experiment.com/Screen-Capturing.js/script script srchttps://webrtc.github.io/adapter/adapter-latest.js/script若希望离线使用可直接拷贝仓库中的 Screen-Capturing.js 到你的站点也可以使用 npm 包npm install webrtc-screen-capturing # node_modules/webrtc-screen-capturing/Screen-Capturing.js脚本同时支持 Chrome 与 FirefoxFirefox 无需扩展getScreenConstraints会直接返回{ mozMediaSource: window, mediaSource: window }约束见 Screen-Capturing.js。API 全览与用法示例getScreenConstraints获取可直接传给navigator.mediaDevices.getUserMedia的屏幕捕获约束对象内部自动完成扩展可用性检查、sourceId 获取与约束组装getScreenConstraints(function(error, screen_constraints) { if (error) { return alert(error); } if(screen_constraints.canRequestAudioTrack) { // 本次选择的源支持捕获系统扬声器音频 // getUserMedia({audio:screen_constraints}) } navigator.mediaDevices.getUserMedia({ video: screen_constraints }).then(function(stream) { var video document.querySelector(video); video.src URL.createObjectURL(stream); video.play(); }).catch(function(error) { alert(JSON.stringify(error, null, \t)); }); });从源码Screen-Capturing.js可以看到其内部组装的约束结构var screen_constraints { mandatory: { chromeMediaSource: chromeMediaSource, // screen 或 desktop maxWidth: screen.width 1920 ? screen.width : 1920, maxHeight: screen.height 1080 ? screen.height : 1080 }, optional: [] };其中chromeMediaSource默认是screen一旦探测到扩展存在其值变为desktop并且脚本会请求扩展返回 sourceId 后写入screen_constraints.mandatory.chromeMediaSourceId。maxWidth/maxHeight以屏幕实际分辨率与 1920×1080 中较大者为准。getScreenConstraintsWithAudio与getScreenConstraints相同但额外包含系统音频扬声器。实现上只是以captureSourceIdWithAudiotrue调用getScreenConstraints进而走getSourceIdWithAudio路径getScreenConstraintsWithAudio(function(error, screen_constraints) { if (error) { return alert(error); } navigator.mediaDevices.getUserMedia({ video: screen_constraints, audio: screen_constraints // 必须同时传 audio 这一行 }).then(function(stream) { var video document.querySelector(video); video.src URL.createObjectURL(stream); video.play(); }).catch(function(error) { alert(JSON.stringify(error, null, \t)); }); });演示页 index.html 中还给出了更稳妥的写法先检查screen_constraints.canRequestAudioTrack true再决定是否把 audio 约束传出去navigator.mediaDevices.getUserMedia({ video: screen_constraints, audio: screen_constraints.canRequestAudioTrack ? screen_constraints : false }).then(...)getSourceId直接向扩展索取sourceId即chromeMediaSourceId适合进阶用户自行组装约束getSourceId(function(sourceId, canRequestAudioTrack) { if(sourceId ! PermissionDeniedError) { // 拿到 sourceId组装自己的 getUserMedia 约束 } if(canRequestAudioTrack true) { // 系统音频扬声器可用 } });注意其实现细节若sourceId已缓存会立即用缓存值回调if(sourceId) return callback(sourceId);避免重复弹出选择框否则设置screenCallback并通过window.postMessage(get-sourceId, *)向扩展请求。getCustomSourceId按需指定捕获来源类型第一个参数必须是数组。支持的格式window捕获指定应用窗口screen捕获整个屏幕tab捕获标签页audio捕获系统音频var our_own_choices [tab, audio]; getCustomSourceId(our_own_choices, function(sourceId, canRequestAudioTrack) { if(sourceId ! PermissionDeniedError) { // 你的代码 } if(canRequestAudioTrack true) { // 系统音频扬声器可用 } });底层通过window.postMessage({ get-custom-sourceId: arr }, *)把数组传给扩展background-script 收到后将其直接作为chooseDesktopMedia的选项。getSourceIdWithAudiogetSourceId的含系统音频版本与getScreenConstraintsWithAudio对应getSourceIdWithAudio(function(sourceId, canRequestAudioTrack) { if(sourceId ! PermissionDeniedError) { // 你的代码 } if(canRequestAudioTrack true) { // 系统音频扬声器可用 } });getChromeExtensionStatus推荐使用的扩展状态检测方法比isChromeExtensionAvailable更可靠。它在页面中创建一个指向chrome-extension://id/icon.png的img元素onload说明扩展已安装随后再通过 postMessage 握手判断是否启用onerror说明未安装。可省略参数此时使用默认扩展 IDajhifddimkapgcifgcodmmfdlknahffk若使用自己发布的扩展请传入自己的扩展 ID。// 传你自己的扩展 ID不传则使用默认 ID getChromeExtensionStatus(your-extension-id, function(status) { if(status installed-enabled) { // 已安装且已启用 } if(status installed-disabled) { // 已安装但被禁用 } if(status not-installed) { // 未安装 } if(status not-chrome) { // 非 Chrome 浏览器Firefox 等 } });注意在非 Chrome 浏览器源码中用typeof window.InstallTrigger判断 Firefox中会直接回调not-chrome。isChromeExtensionAvailable较简化的存在性探测向扩展发送are-you-there2 秒后仍未收到响应则判定不可用isChromeExtensionAvailable(function(isAvailable) { if(!isAvailable) alert(Chrome extension is either not installed or disabled.); });官方文档建议优先使用getChromeExtensionStatus因为它能区分未安装与已禁用两种状态。常见问题无法重复捕获屏幕屏幕捕获一次后再次调用 API 却不再弹窗解决办法是先把sourceId置为null再调用任意 APIsourceId null; // 关键一行 getScreenConstraints(function(error, screen_constraints) { if (error) { return alert(error); } navigator.mediaDevices.getUserMedia({ video: screen_constraints }).then(function(stream) { var video document.querySelector(video); video.src URL.createObjectURL(stream); video.play(); }).catch(function(error) { alert(JSON.stringify(error, null, \t)); }); });原因在源码中可见getSourceId、getCustomSourceId、getSourceIdWithAudio都会检查全局变量sourceId是否已有缓存值存在则直接复用而不再请求扩展清空它即可让下一次调用重新触发chooseDesktopMedia选择框。同理如果你的业务需要每次都让用户重新选择可以在回调前主动清理sourceId。进阶替代方案getScreenId.js免发布扩展如果不想自己发布扩展仓库还提供了 getScreenId.js 方案。它使用iframe 黑客技巧页面中的 iframe 从https://www.webrtc-experiment.com/域加载该域已在官方扩展白名单内iframe 与扩展通过 postMessage 交换 sourceId再转发回你的页面从而让同一个官方扩展在任意 HTTPs 域可用。其完整调用方式与 APIgetScreenId、getChromeExtensionStatus、自定义参数捕获音频/标签页等见 getScreenId.js/README.md。script srchttps://www.WebRTC-Experiment.com/getScreenId.js/script script srchttps://webrtc.github.io/adapter/adapter-latest.js/script video controls autoplay/video script getScreenId(function (error, sourceId, screen_constraints) { navigator.mediaDevices.getUserMedia(screen_constraints).then(function (stream) { document.querySelector(video).src URL.createObjectURL(stream); }).catch(function (error) { console.error(error); }); }); /script该方案同样有局限在 iframe 内使用时 postMessage 机制可能失效官方建议此时改用 WebSocket 或外部服务器中转 sourceId并且同样需要 HTTPs 环境。本地运行演示仓库为演示页提供了极简静态服务器server.js基于 Node.js 原生 http 模块默认监听 9001 端口仅做静态文件服务并屏蔽对 server.js 自身的访问node server.js # Server listening at http://localhost:9001技术栈与适用场景小结方案适用场景关键限制getDisplayMedia现代 Chrome/Edge/Firefox需用户手动选择源不支持旧版 Chrome 34-70 等Screen-Capturing.js 自发布扩展需要固定扩展、细粒度 sourceId 控制的 HTTPs 站点需改 manifest 白名单并发布扩展已停止维护getScreenId.js 官方扩展不想发布扩展、任意 HTTPs 域快速验证依赖官方扩展与 iframe 中转iframe 内不可用最后再次提醒新项目请直接使用getDisplayMediaScreen-Capturing.js 与 desktopCapture 扩展仅作为历史兼容方案保留。本文所有 API 行为均可对照仓库源码验证网页侧封装见 Screen-Capturing.js消息中转见 content-script.js底层桌面捕获见 background-script.js完整交互演示见 index.html。赞分享示例工程【免费下载链接】WebRTC-ExperimentWebRTC, WebRTC and WebRTC. Everything here is all about WebRTC!!项目地址https://gitcode.com/gh_mirrors/we/WebRTC-Experiment点击查看免费下载相关推荐如何快速实现屏幕翻译Screen Translator 完整使用指南如何快速实现屏幕翻译Screen Translator 完整使用指南 Screen Translator 是一款强大的开源屏幕翻译工具集成了屏幕捕捉、OCR桌面应用OCRElectron屏幕捕获实现屏幕截图与录屏功能Electron屏幕捕获实现屏幕截图与录屏功能 在桌面应用开发中屏幕捕获是一个常见且重要的功能需求。无论是用于远程协助、教学演示、游戏录制还是应用监控屏幕桌面应用跨平台前端屏幕翻译终极指南Screen Translator完整使用教程屏幕翻译终极指南Screen Translator完整使用教程 Screen Translator是一款功能强大的开源屏幕翻译工具它通过智能屏幕捕捉、精准O桌面应用OCR上一篇**探索分布式应用的新纪元Iroh**下一篇黑鸟BlackbirdSwift中的SQLite轻骑兵创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表