WebRTC是Google搞出来的,但很多浏览器并不支持,还有一些移动端的设备也没有支持,所以在这种情况下,要使用WebRTC,需要从官方的代码入手。官方有什么文档是针对这方面的,不过如果不是做平台移植方面的,不建议从源代码开始,因为1,要翻墙,2代码很大,一共有几个G的东西要下载,3,好像还不支持断点续传,所以还是算了吧。
以iOS为例,建议直接使用CocoaPods上面的东西,名字是libjingle_peerconnection。
使用这个库里面的东西并不是很麻烦,但要搞清楚里面的逻辑却挺头大的,因为Google提供了一个例子,AppRTCDemo,里面由于使用了很多Google自己的一个架构,把整个Demo搞得剧复杂无比,不过搞清楚原理后,只需要使用几个简单的API就可以实现WebRTC的通信。
WebRTC要工作起来,需要一下几个方面
1. 双方建立PeerConnection
2. 一端创建和发出Offer,另一端接收Offer后响应Answer
3. PeerConnection的两端交换SDP信息
建立PeerConnection需要ICE信息,里面提供的网络打洞穿墙等路径数据,
RTCIceServer *iceServer = [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:YOUR_SERVER] username:USERNAME_OR_EMPTY_STRING password:PASSWORD_OR_EMPTY_STRING]]; RTCPeerConnectionFactory *pcFactory = [[RTCPeerConnectionFactory alloc] init]; RTCPeerConnection *peerConnection = [pcFactory peerConnectionWithICEServers:iceServers constraints:nil delegate:self];
一端创建Offer
RTCMediaConstraints *constraints = [RTCMediaConstraints alloc] initWithMandatoryConstraints: @[ [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"], [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"] ] optionalConstraints: nil]; [peerConnection createOfferWithConstraints:constraints];
这之后的动作都是通过peerConnection的delegate来完成的
createOffer之后,会触发didCreateSessionDescription方法,可以在这个方法中来设置localDescription
- (void)peerConnection:(RTCPeerConnection *)peerConnection didCreateSessionDescription:(RTCSessionDescription *)sdp error:(NSError *)error { [peerConnection setLocalDescription:sdp] }
localDescription设置成功后,会触发didSetSessionDescriptionWithError的方法
- (void)peerConnection:(RTCPeerConnection *)peerConnection didSetSessionDescriptionWithError:(NSError *)error { if (peerConnection.signalingState == RTCSignalingHaveLocalOffer) { // 通过Signaling Channel发送Offer之类的信息 } }
当另一端收到Offer时,要设置remoteDescription
RTCSessionDescription *remoteDesc = [[RTCSessionDescription alloc] initWithType:@"answer" sdp:sdp]; [peerConnection setRemoteDescription:remoteDesc];
剩下的一些delegate都是跟ICE的candidate相关的,处理在建立PeerConnection时的P2P连接信息
- (void)peerConnection:(RTCPeerConnection *)peerConnection gotICECandidate:(RTCICECandidate *)candidate { // 获得Candidate信息,通过signaling channel发送给另一端 }
当通过signaling channel收到candidate信息后,添加到peerConnection,让P2P来处理打洞信息
RTCICECandidate *candidate = [[RTCICECandidate alloc] initWithMid:SDP_MID index:SDP_M_LINE_INDEX sdp:SDP_CANDIDATE]; [self.rtcPeerConnection addICECandidate:candidate];
最后一个是媒体数据处理,当peerConnection收到媒体数据时,会触发另一个方法
- (void)peerConnection:(RTCPeerConnection *)peerConnection addedStream:(RTCMediaStream *)stream { // Create a new render view with a size of your choice RTCEAGLVideoView *renderView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectMake(100, 100)]; [stream.videoTracks.lastObject addRenderer:self.renderView]; // RTCEAGLVideoView is a subclass of UIView, so renderView // can be inserted into your view hierarchy where it suits your application. }
总共这些方法就能够简单的让WebRTC工作起来,但还需要很多别的处理,比如iOS的默认speaker播放声音,音视频编解码,chrome用的v8,iOS用的是H264,还有很多问题要等待一一处理