WebRTC简单入门与实践
一、前言
WebRTC 技术已经广泛在各个行业及场景中被应用,但对多数开发者来说,实时音视频及相关技术却是比较不常接触到的。
做为一名 Web 开发者,WebRTC 这块的概念着实花了不少时间才搞明白,一是 WebRTC 本身有较多的独有概念,二是虽然带"Web"字样,但依赖底层概念和网络却是 Web 开发很少接触到的;
本篇文章以 0 经验音视频开发者 视角,类比常用的 Web 技术,期望帮助您简单入门 WebRTC 技术,耐心看完本篇文章,你将:了解什么是 WebRTC掌握 WebRTC 通话原理利用 Chrome debug WebRTC 应用
适合阅读对象 :Web开发,有 js 基础,对 WebRTC 感兴趣的同学二、使用示例
没有接触过 WebRTC 技术的同学,可以先体验下 ZEGO 的 GoEnjoy 产品,里面包含了 WebRTC 在浏览器中的标准使用方案,包括不限于:设备检测、兼容性检测、弱网断网应对策略等,应用是免费的,可戳--->示例 Demo 传送门
在进入正文之前,让我们先对它有个基本的印象吧!
三、简单介绍
体验完 Demo 后,有必要再了解一下技术的发展历史、应用场景等,这些能让我们知道它为什么优秀,哪方面优秀,有哪些缺点等。
程序员经常用到 5W1H 分析法,那么本文就按照这个思路给大家做一下介绍:
What
WebRTC(Web Real-Time Communication),一个可以让用户用自己流量 实现音视频实时通信的框架(APIs),支持浏览器(Firefox、Chrome、safari)以及 iOS、Android 原生系统。
When
2017 年 12 月成为 W3C 草案,国内微信浏览器 19 年下半年才支持,国内手机自带浏览器目前还有不少兼容问题,2021 年 1 月 26 日,成为 W3C 正式标准。
Who
2011年 Google 收购多个子项目(GIPS,On2,VPx),成立了现在的 WebRTC 项目,目前是 Google 的一个开源项目。
Where
可应用在社交/娱乐/教育/工具 等需要实时音视频高效沟通的场景,例如:最近很火的元宇宙。
Why
W3C 标准,开源,插件化,整体效果佳。
How
也是本文重中之中,最终的目的也是让大家能知道如何使用。
在正式代码讲解之前,有一些概念需要先普及一下(您也可以先看完代码后,再回来看这个段落,加深理解。):
MediaStream:流媒体对象,音/视频数据的一种封装格式,挂载到 video 或 audio 标签上播放;
RTCPeerConnection:会话控制,网络和媒体信息收发,作用类似 http 对象;
SDP :主要用于两个会话实体之间的媒体协商,作用类似 http 中的配置项。
结合下图类比会更容易理解:
四、前置思考问题
在讲解代码前,还需要思考以下几个问题,否则会不清楚为什么代码中需要交换 SDP,cadidate等(您也可以先看完代码后,再回来看这个段落,加深理解)。
【更多 音视频学习资料 ,点击链接+Q「链接」免费领取↓↓,先码住不迷路~】
双方使用浏览器通信,浏览器能力,网络情况等不一致会对通信有很大影响,一起思考下下面 2 个问题:1、视频编码能力不一样?
peer-A 和 peer-B 是视频互动的两边浏览器,他们通讯前必须在视频编码能力上先达成一致,如下图,最终协商出共同的H264,如果无法达成一致,则通讯失败。
2 .电脑之间,大多数是在某个局域网中,需要 NAT(Network Address Translation,网络地址转换),因此并不能直接通信
显示情况如下图:
通俗一点比喻: 阿宅今年 30 了(不是我,不要乱猜)被父母逼婚,他只能求助媒婆,才可能被另一个阿宅认识。
媒婆解决阿宅社恐问题,NAT 也需要一种方式绕过,双方才能建立通信,我们需要用到 STUN 和 TURN。五、代码讲解
终于到我们的代码讲解部分了,下面的代码会按照推流段顺序,分阶段讲解每个步骤所需要用到的API(如果你是直接看代码,建议看完后再回去看第三、四 Part 的介绍,理解会更加深刻)。
步骤一:创建数据源
localStream 作为发送端本地预览画面:// 创建数据源 const localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true, }); // 显示数据源,localVideo 是 html 中的 video 标签 localVideo.srcObject = localStream;
步骤二:创建发送数据实例
用于发送步骤一中创建的数据:// 本地实例 const pc1 = new RTCPeerConnection(); // 对端实例 const pc2 = new RTCPeerConnection();
步骤三:配置实例
做这一步的目的是为了交换两端的信息:icecandidate 和 SDP
icecandidate:包含通信协议(TCP/UDP)和通信IP,STUN和TURN协议中描述网络信息的格式规范,解决双方网络链接问题;
SDP:浏览器能力,包括不限于音视频编码格式,带宽,流控策略等;解决前置思考中,双方能力不匹配问题,通过交换双方 SDP 浏览器会自动选择双方都支持的视频编码格式。// 告诉对端,本端地址 pc1.addEventListener("icecandidate", async (e) => { // 发送给对端 // 对端添加本端地址 if (e.candidate) { await pc2.addIceCandidate(e.candidate); } }); pc2.addEventListener("icecandidate", async (e) => { // 发送给本端 // 本端添加对端地址 if (e.candidate) { await pc1.addIceCandidate(e.candidate); } }); // 创建本端SDP,告诉本端浏览器支持哪些能力 const offer = await pc1.createOffer(); pc1.setLocalDescription(offer); // 创建远端SDP,告诉远端浏览器支持哪些能力 const answer = await pc2.createAnswer(); pc2.setLocalDescription(answer); // …发送远端SDP给本端 // 接收远端sdp,告诉远端浏览器支持哪些能力 pc1.setRemoteDescription(answer); // 接收客户端sdp,告诉远端浏览器支持哪些能力 pc2.setRemoteDescription(offer);
步骤四:发送数据localStream.getTracks().forEach( (track) => pc1.addTrack(track, localStream) );
【更多 音视频学习资料 ,点击链接+Q「链接」免费领取↓↓,先码住不迷路~】
步骤五:完整精简版Typescript代码
注意,这里使用的 typescript 编写,实际运行需要先转成 js。const pc1 = new RTCPeerConnection(); pc1.addEventListener("icecandidate", async (e) => { if (e.candidate) { await pc2.addIceCandidate(e.candidate); } }); pc1.addEventListener("iceconnectionstatechange", (e) => { console.log("pc1: iceconnectionstatechange", e); }); const pc2 = new RTCPeerConnection(); pc2.addEventListener("icecandidate", async (e) => { if (e.candidate) { await pc1.addIceCandidate(e.candidate); } }); pc2.addEventListener("iceconnectionstatechange", (e) => { console.log("pc2: iceconnectionstatechange", e); }); pc2.addEventListener("track", (e) => { if (e.streams.length > 0) { remoteVideo.srcObject = e.streams[0]; } }); const remoteVideo = document.querySelector("#remoteVideo") as HTMLVideoElement; const localVideo = document.querySelector("#localVideo") as HTMLVideoElement; async function pushStream(answer: RTCSessionDescriptionInit) { pc1.setRemoteDescription(answer); } async function pullStream(offer: RTCSessionDescriptionInit): Promise { pc2.setRemoteDescription(offer); const answer = await pc2.createAnswer(); pc2.setLocalDescription(answer); console.warn("answer", answer); pushStream(answer); } window.onload = async () => { const localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true, }); localVideo.srcObject = localStream; localStream.getTracks().forEach((track) => pc1.addTrack(track, localStream)); const offer = await pc1.createOffer(); pc1.setLocalDescription(offer); console.warn("pc1 offer", offer); pullStream(offer); };六、应用举例
学习完理论知识,接下来我们一起再实践下,加深对知识的理解 —— 通过 Chrome浏览器 debug WebRTC应用。学会 debug 既可以加深理解,也是后续写代码必不可少的技能,千万不少跳过这一步哦:
1、点击打开示例DEMO
2、另打开一个tab页面,输入: chrome://webrtc-internals/
3、DEMO 中输入相关信息开始直播, 切回到 2 中的 tab 页面,如下图:
蓝色部分:对应的是代码中SDP的处理过程
绿色部分:对应的是网络链接情况
4、继续下来,可以看到推流中实时数据变化:
蓝色部分:拉流实时数据,包括分辨率,码率,丢包率等
绿色部分:推流实时数据,包括分辨率,码率,丢包率等
更多字段理解,可戳这里进行深入学习:Identifiers for WebRTC"s Statistics API七、结尾
随着硬件网络的更新换代,我们经历了由文字->图片->视频 载体变更的过程。随着 5G 的普及,音视频技术融于无形正在成为现实,WebRTC 作为其中最重要框架之一,浏览器的支持成熟度也在快速完善当中
————————————————
版权声明:本文为CSDN博主「ZEGO即构科技」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zego_0616/article/details/123420765
#程序员##音视频开发##WebRTC#
兔年春节广元市剑阁县接待游客突破36万人次来源人民网四川频道原创稿游客登剑门关关楼。王春波摄阿迪力在剑门关景区表演高空走钢丝。剑阁县融媒体中心供图刚刚过去的兔年春节假期,广元市剑阁县A级景区共接待游客36。49万人次,其中
四川这两县或将抱团,助推广元发展说到四川的城市,可能很多人对于广元这个名字十分陌生,的确,相比于我们熟知的那些城市,广元这座城市在四川省内的存在感并不是那么强烈。但这并不代表广元不重要,这里自古就是进入蜀地的重要
Web3。0将如何引领互联网技术变革?随着当前各类信息技术的迭代创新,互联网正呈现向下一代互联网演进的趋势。加速布局下一代互联网技术既是自身发展的实际需求,也是参与全球竞争的重要一步。如今互联网正处在Web2。0向We
智能客服系统能为银行带来哪些价值?随着人工智能大数据区块链云计算等技术的逐渐成熟,各技术在不同行业的落地场景也日渐完善,商业银行一直面临着巨变的外部经营环境和持续变化的客户需求。在此背景下,数智化转型是各银行的迫切
生态系统微生物组学研究获进展人类和其他生物共享一个微生物地球。微生物时刻影响着生态系统的过程和功能,对人类和地球健康至关重要。随着分子基因组学的发展,我们对生态系统中每一组分相联系微生物功能的认知不断深入,剖
阿里扔出王炸底牌!老美的人工智能领域大受冲击,究竟发生了什么就在前段时间,阿里达摩院正式发布了2023年十大科技趋势,其中共包括生成式AI云计算体系架构城市数字孪生等一系列前沿技术,以及未来科技发展趋势。2017年阿里正式宣布成立达摩院,并
木札岭,洛阳的丛林秘境国家4A级景区木札岭原始生态旅游区位于河南洛阳市嵩县东南部,属伏牛山国家级自然保护区,是世界地质公园,由九撞沟原始森林官帽峰三大游览区组成。沿着游览步道,眼观千姿百态古藤树,耳听千
开年狂飙!上刀山下火海!德宏这场傈僳族狂欢太精彩春临大地百花艳,节至人间万象新。1月30日,陇川县2023年傈僳族阔时节在户撒乡坪山傈僳文化园隆重举行。傈僳族同胞穿上节日盛装齐跳阔时狂欢,共庆盛会。阔时意为新年,阔时节是傈僳族最
春节饮食的第一大忌,你中招了吗?暴饮暴食是节日期间饮食的第一大忌。节日期间,聚餐频繁,不容易控制食量。很容易形成这样一种不良饮食习惯早晨不吃饭,中午吃得较多,晚餐胡吃海塞,把胃撑得满满的。然而,一次性摄入大量富含
中超又一只球队解散中超运行发展体系不健康为何不低下头颅学日本毫无意外,又一只中超足球俱乐部解散退出中超联赛,中超联赛多年不健康的运行发展体系让人唏嘘!管理者为何不肯低下头颅学习近邻日本健康的足球发展体系和校园青训足球?1月25日武汉长江足球
研究揭示罗伯逊易位在牛属物种形成中的作用罗伯逊易位又称着丝粒融合,是指两条近端着丝粒异源染色体在进化过程中发生着丝粒染色体融合,形成一条中部或近中着丝粒染色体。罗伯逊易位是核型进化的主要驱动因素之一,传统观念认为这种类型