RTCPeerConnection传输视频流(三)
你会学到什么
在这一步中,您将了解如何:
- 使用WebRTC Shim(adapter.js)兼容浏览器差异。
- 使用RTCPeerConnection API来传输视频流。
- 控制媒体捕捉和流媒体。
此步骤的完整版本位于step-2文件夹中。
什么是RTCPeerConnection?
RTCPeerConnection是一个用于使WebRTC调用视频和音频流并交换数据的API。
本示例在同一页上设置两个RTCPeerConnection对象(称为对等)之间的连接。
没有多少实际用途,但可以很好理解RTCPeerConnection的工作原理。
添加video元素和控制按钮
在index.html中用两个视频元素和三个按钮替换单个视频元素:
<video id="localVideo" autoplay></video>
<video id="remoteVideo" autoplay></video>
<div>
<button id="startButton">Start</button>
<button id="callButton">Call</button>
<button id="hangupButton">Hang Up</button>
</div>
添加 adapter.js shim
在main.js文件的上方添加一个adapter.js的链接:
adapter.js是一个垫片,以隔离应用程序的规格变化和前缀差异。
事实上,用于WebRTC实施的标准和协议是高度稳定的,并且只有少数前缀名称。
在这一步中,我们链接到最新版本的adapter.js的本地副本 - 适用于本例子,但不适用于生产应用程序。 adapter.js GitHub repo解释了确保您的应用程序总是访问最新版本的技术。
有关完整的WebRTC互操作信息,请参阅webrtc.org/web-apis/interop。
Index.html文件代码如下所示:
<!DOCTYPE html>
<html>
<head>
<title>Realtime communication with WebRTC</title>
<link rel="stylesheet" href="css/main.css" />
</head>
<body>
<h1>Realtime communication with WebRTC</h1>
<video id="localVideo" autoplay></video>
<video id="remoteVideo" autoplay></video>
<div>
<button id="startButton">Start</button>
<button id="callButton">Call</button>
<button id="hangupButton">Hang Up</button>
</div>
<script src="js/lib/adapter.js"></script>
<script src="js/main.js"></script>
</body>
</html>
安装RTCPeerConnection代码
将main.js替换为step-02文件夹中的版本。
调用call
打开index.html,单击“开始”按钮从网络摄像机获取视频,然后单击“call”以建立对等连接。 您应该在两个视频元素中看到相同的视频(来自网络摄像头)。 查看浏览器控制台以显示WebRTC日志记录。
工作原理:
这一步做了很多...
如果你想跳过下面的解释,那很好。
你仍然可以继续使用示例代码!
WebRTC使用RTCPeerConnection API建立连接,以在WebRTC客户端(称为对等点)之间传输视频流。
在这个例子中,两个RTCPeerConnection对象在同一个页面上:pc1和pc2。 没有太多的实际用途,但很好的展示了API的工作原理。
在WebRTC对等设备之间建立呼叫涉及三个任务:
- 为呼叫的每一端创建一个RTCPeerConnection,并在每一端添加来自getUserMedia()的本地流。
- 获取和共享网络信息:潜在的连接终端被称为ICE候选人
- 获取及共享本地和远程描述:关于SDP格式的本地媒体的元数据。
想象一下Alice和Bob想使用RTCPeerConnection来建立一个视频聊天。
首先,Alice和Bob交换网络信息。 “查找候选者”这个表达是指使用ICE框架查找网络接口和端口的过程。
- Alice使用onicecandidate处理程序创建一个RTCPeerConnection对象。 这对应于main.js中的以下代码:
pc1 = new RTCPeerConnection(servers); trace('Created local peer connection object pc1'); pc1.onicecandidate = function(e) { onIceCandidate(pc1, e); }; ``` * Alice调用getUserMedia()并添加传递给它的流: ```javascript pc1.addStream(localStream); ``` * 网络候选变得可用时,调用步骤1中的onicecandidate处理函数。 * Alice将序列化的候选数据发送给Bob。 在一个真正的应用程序中,这个过程(称为信令)通过消息传递服务进行 - 您将在后面的步骤中学习如何做到这一点。 当然,在这个步骤中,两个RTCPeerConnection对象位于同一页面上,可以直接进行通信而不需要外部消息传递。 * 当Bob从Alice获得候选消息时,他调用addIceCandidate(),将候选添加到远程对等描述中: ```javascript function onIceCandidate(pc, event) { if (event.candidate) { getOtherPc(pc).addIceCandidate( new RTCIceCandidate(event.candidate) ).then( function() { onAddIceCandidateSuccess(pc); }, function(err) { onAddIceCandidateError(pc, err); } ); trace(getName(pc) + ' ICE candidate: \n' + event.candidate.candidate); } }
WebRTC对等体还需要查找并交换本地和远程音频和视频媒体信息,例如分辨率和编解码器功能。 交换媒体配置信息的信令通过使用被称为SDP的会话描述协议格式来交换,被称为提议和应答的元数据块:
-
Alice运行RTCPeerConnection createOffer()方法。 返回的promise提供了一个RTCSessionDescription:Alice的本地会话描述:
-
如果成功,Alice使用setLocalDescription()设置本地描述,然后通过它的信令通道将这个会话描述发送给Bob。
- Bob使用setRemoteDescription()将Alice发送的描述设置为远程描述。
- Bob运行RTCPeerConnection createAnswer()方法,并将其从Alice获得的远程描述传递给它,以便可以生成与她相兼容的本地会话。 createAnswer() promise传递RTCSessionDescription:Bob将其设置为本地描述并发送给Alice。
-
当Alice获得Bob的会话描述时,她将其设置为具有setRemoteDescription()的远程描述。
function onCreateOfferSuccess(desc) { pc1.setLocalDescription(desc).then( function() { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); pc2.setRemoteDescription(desc).then( function() { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError ); // Since the 'remote' side has no media stream you need // to pass in the right constraints in order for it to // accept the incoming offer of audio and video. pc2.createAnswer().then( onCreateAnswerSuccess, onCreateSessionDescriptionError ); } function onCreateAnswerSuccess(desc) { pc2.setLocalDescription(desc).then( function() { onSetLocalSuccess(pc2); }, onSetSessionDescriptionError ); pc1.setRemoteDescription(desc).then( function() { onSetRemoteSuccess(pc1); }, onSetSessionDescriptionError ); }
-
Ping!
知识扩展
- 打开 chrome://webrtc-internals , 这里提供了WebRTC统计和调试数据。 (Chrome网址的完整列表位于chrome://about)
- 使用CSS设置页面样式:
把视频并排放置。
使按钮的宽度相同,文字更大。
确保布局在移动设备上运行。
- 在Chrome开发工具控制台中,查看pc1和pc2的localStream
- 从控制台查看 pc1.localDescription的SDP格式是什么样?
你学到了什么
在这一步你学会了如何:
- 使用WebRTC Shim adapter.js shim 兼容浏览器差异。
- 使用RTCPeerConnection API来传输视频流。
- 捕捉和控制流媒体。
- 在对等点之间启用WebRTC共享媒体和网络信息。
此步骤的完整版本位于step-2文件夹中。
Tips
这一步有很多东西要学习! 要更详细的内容参考RTCPeerConnection的其他资源,请查看webrtc.org/start。 本页面包含JavaScript框架的建议 - 如果您想使用WebRTC,但不想围绕API。
从adapter.js GitHub仓库中找到更多关于adapter.js shim 程序的信息。
想看看世界上最好的视频聊天应用程序是什么样子? 看看AppRTC,WebRTC项目的WebRTC调用规范应用程序:app,code。 呼叫建立时间小于500毫秒。
最佳实践
为了使您的代码具有前瞻性,请使用新的基于Promise的API,并通过使用adapter.js启用不支持它们(webrtc)的浏览器。
下一步
这一步展示了如何使用WebRTC在对等体之间传输视频 - 但是这个实验也是关于数据的!
在下一步中,将了解如何使用RTCDataChannel传输任意数据流。