从 0 打造音视频直播系统
李超
前新东方音视频直播技术专家,前沪江音视频架构师
32579 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 41 讲
WebRTC 1对1通话 (23讲)
从 0 打造音视频直播系统
15
15
1.0x
00:00/00:00
登录|注册

05 | 原来浏览器还能抓取桌面?

解决问题的办法
视频编码方式容易出现桌面模糊的现象
浏览器支持情况
商用客户端录制
录制桌面
桌面的展示
抓取桌面
观看端渲染
观看端解码
传输
共享端桌面数据的编码
共享端桌面数据的采集
信令控制
桌面数据
控制
显示
解码
传输
压缩编码
抓屏
桌面也可以当作一种特殊的视频数据
远程控制端的处理过程
共享者的处理过程
浏览器的更广阔应用空间
WebRTC的愿景
共享桌面的必备功能
思考时间
小结
如何共享桌面
WebRTC与RDP/VNC的异同点
RDP和VNC远程桌面协议
共享桌面的处理过程
共享桌面的基本原理
WebRTC 处理过程中的位置
原来浏览器还能抓取桌面?
参考文章

该思维导图由 AI 生成,仅供参考

无论是做音视频会议,还是做远程教育,共享桌面都是一个必备功能。如果说在 PC 或 Mac 端写个共享桌面程序你不会有太多感受,但通过浏览器也可以共享桌面是不是觉得就有些神奇了呢?
WebRTC 的愿景就是要让这些看似神奇的事情,不知不觉地发生在我们身边。
你可以想象一下,假如浏览器有了共享桌面功能,这会使得浏览器有更广阔的应用空间,一个最直接的例子就是我们可以直接通过浏览器进行远程办公、远程协助等工作,而不用再下载共享桌面的应用了,这大大提高了我们的工作效率。

在 WebRTC 处理过程中的位置

在正式进行主题之前,我们还是来看看本文在整个 WebRTC 处理过程中的位置,如下图所示:
WebRTC 处理过程图
没错,它仍然属于音视频采集的范畴,但是这次采集的不是音视频数据而是桌面。不过这也没什么关系,桌面也可以当作一种特殊的视频数据来看待

共享桌面的基本原理

共享桌面的基本原理其实非常简单,我们可以分“两头”来说明:
对于共享者,每秒钟抓取多次屏幕(可以是 3 次、5 次等),每次抓取的屏幕都与上一次抓取的屏幕做比较,取它们的差值,然后对差值进行压缩;如果是第一次抓屏或切幕的情况,即本次抓取的屏幕与上一次抓取屏幕的变化率超过 80% 时,就做全屏的帧内压缩,其过程与 JPEG 图像压缩类似(有兴趣的可以自行学习)。最后再将压缩后的数据通过传输模块传送到观看端;数据到达观看端后,再进行解码,这样即可还原出整幅图片并显示出来。
对于远程控制端,当用户通过鼠标点击共享桌面的某个位置时,会首先计算出鼠标实际点击的位置,然后将其作为参数,通过信令发送给共享端。共享端收到信令后,会模拟本地鼠标,即调用相关的 API,完成最终的操作。一般情况下,当操作完成后,共享端桌面也发生了一些变化,此时就又回到上面共享者的流程了,我就不再赘述了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

WebRTC技术实现了浏览器共享桌面功能,为远程办公和协助带来便利。文章介绍了共享桌面的基本原理,包括屏幕抓取、压缩编码、传输、解码、显示和控制等步骤。相较于传统远程桌面协议,WebRTC利用视频编码技术和浏览器API实现桌面数据采集和展示。通过getDisplayMedia API抓取桌面数据,并通过HTML中的<video>标签展示。这项技术将提高工作效率,使远程办公更加便捷。另外,文章还介绍了通过浏览器API抓取和录制桌面的方法,展示了相关的HTML和JavaScript代码。最后,文章提出了关于视频编码方式导致桌面模糊的问题,并鼓励读者分享解决方法。文章内容简洁明了,为读者提供了深入了解WebRTC技术和桌面共享的基础知识。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《从 0 打造音视频直播系统》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(35)

  • 最新
  • 精选
  • 恋着歌
    如果是解决网络引起的模糊,那么可能就要牺牲实时性,提高延迟,就像我们看视频时卡顿要缓冲一下。 具体的解决方法是: 1,解决网络问题😂 2,关闭 Web RTC 的自适应码率,frameRate,width,height 设置固定值或高范围值。

    作者回复: 赞!

    2019-07-25
    2
    13
  • 月光伴奏
    老师!文中(不能在采集桌面的同时采集音频),好像是能同时采集的,弹出了一个分享音频的选择框,勾上好像就能采集音频了

    作者回复: 不能用同一个 stream进行采集

    2019-11-22
    2
    7
  • 春风吹又生
    老师,webrtc能否录制系统内声音呢?

    作者回复: 你是指的播放了的多媒体文件的声音吧?是可以的!

    2019-10-27
    2
    3
  • 魏仁勋
    老师,我现在在用electron-vue写客户端,但是我想分享我的屏幕,结果报这个错误navigator.mediaDevices.getDisplayMedia is not a function,但是我是能看到视频和听到声音的,我之前在web是可以调的,请问这是为什么呢

    作者回复: 感觉你在调用 vue时,没有真正调用到系统的 API,而是被封装了,你要自己查一下。还有一个种可能是你的electron用的chomre核版本太低了

    2020-11-13
    2
  • 宇宙之王
    是不是这一讲的代码只能在Chrome下面运行,别的浏览器不支持,我试了一下,edge和火狐获取不到桌面,另,看到所有代码里面都有<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> 为什么要引入这两个js,删掉好像一样可以运行

    作者回复: chrome对webrtc兼容的最好,共享桌面是一个试验性的功能,所以其它浏览器支持的不好; adapter-latest.js 主要为了兼容老版本chrome浏览器;socket.io.js是 socket.io的js 客户端;

    2020-08-23
    2
    2
  • 月光伴奏
    老师,也就是说webrtc这个分享时没办法实现分享系统声音的嘛?分享游戏听不到声音的嘛?

    作者回复: 可以分别采集,然后入到同一个stream中。

    2019-11-15
    2
    2
  • Embrace
    老师,按照demo写的,录下来的桌面视频好模糊,调整了分辨率和帧率也没啥用,分辨率太大了,录下来的视频会嵌套变成很多层;另外getDisplayMedia接口的具体参数在哪里能查到? MDN的参数很简单,跟实际要用到的相比少了很多

    作者回复: webrtc1.0规范手册,网上查一下

    2020-10-19
    2
    1
  • ZeroIce
    老师,录制的像素太低怎么办?

    作者回复: getUserMedia API 中调整一下分辩率就好了!

    2019-08-04
    1
  • ZeroIce
    交作业:https://codepen.io/vicksiyi/pen/oKGJzL // 判断是否为PC端的Chrome let ifMachine = (() => { var ua = navigator.userAgent, isWindowsPhone = /(?:Windows Phone)/.test(ua), isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone, isAndroid = /(?:Android)/.test(ua), isFireFox = /(?:Firefox)/.test(ua), isChrome = /(?:Chrome|CriOS)/.test(ua), isTablet = /(?:iPad|PlayBook)/.test(ua) || (isAndroid && !/(?:Mobile)/.test(ua)) || (isFireFox && /(?:Tablet)/.test(ua)), isPhone = /(?:iPhone)/.test(ua) && !isTablet, isPc = !isPhone && !isAndroid && !isSymbian; return { isChrome: isChrome, isPc: isPc }; })();

    作者回复: 赞!

    2019-08-04
    1
  • K
    //第一部分代码 let videoTypes = "video/webm\;codecs=vp8"; let userMediaSetting = { video: true }; let playVideo = document.querySelector('video#play'); let rePlayVideo = document.querySelector('video#replay'); let recordingButton = document.querySelector('button#recording'); let playbackButton = document.querySelector('button#playback'); let downloadButton = document.querySelector('button#download'); let buffer; let mediaRecorder; let blob; function init() { if (!(mediaSupport() && mediaRecorderSupport())) return; getVideo(); } function mediaSupport() { if (!navigator.mediaDevices) { console.log('不支持 mediaDevices'); return false; } console.log('支持 mediaDevices'); return true; } function mediaRecorderSupport() { if (!MediaRecorder.isTypeSupported(videoTypes)) { console.log(`不支持 ${videoTypes}`); return false; } console.log(`支持 ${videoTypes}`); return true; } function getVideo() { navigator.mediaDevices.getDisplayMedia(userMediaSetting) .then(handleGetVideo) .catch(handleGetVideoError) } function handleGetVideo(mediaStream) { playVideo.srcObject = mediaStream; } function handleGetVideoError(err) { console.log(`获取视频输入出错: ${err.name} : ${err.message}`) } function recordingVideo() { if ( typeof(mediaRecorder) != "undefined" && mediaRecorder.state === 'recording') { console.log('已开始录制,请勿重复录制'); return; } console.log('开始录制'); buffer = []; let options = { mimeType : videoTypes }; mediaRecorder = new MediaRecorder(playVideo.srcObject, options); mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start(10); } function handleDataAvailable(d) { if (d && d.data && d.data.size > 0) { buffer.push(d.data); } }

    作者回复: 赞!

    2019-07-25
    1
收起评论
显示
设置
留言
35
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部