实现1V1音视频实时互动直播系统 十二、第九节 直播客户端的实现

我们今天继续实现直播客户端的PeerConnection这个代码,上节我们只是将conn这个函数实现了一大半,在这里我们首先与这个信令服务器建立连接,然后将joined、otherjoin、full、leaved、bye、disconnect、message等函数注册在这里面处于监听状态,那发送过来这些消息之后呢我们就可以收到这些消息了,还可以做相应的处理,上节课只是简单的打了一些日志,那今天我们把PeerConnection这部分完成一下,那我们就可以写一个具体的逻辑了,当我们收到不同的信令的时候去调用不同的逻辑方法。

现在我们来写createPeerConnection,这个函数相对也比较简单,它主要做两件事,第一件事就是创建这个RTCPeerConnection,创建完了之后要给它添加一些事件,比如说我们要监听一些事件,主要就是candidate,我们要监听candidate这个事件,当收到这个事件之后要通过信令转发到另一端去做一个端对端的消息,另外我们还要监听ontrack事件,也就是说当我们收到远端的视频数据来了之后我们要在这个video标签里面显示出来,除了这个PeerConnection之外,我们还有把我们在音视频设备里面获取的音视频数据track添加到这个PeerConnection中,主要就是完成这个工作。

创建好RTCPeerConnection并设置好pcConfig之后,我们就创建好这个连接了,创建完连接之后我们需要监听一些事件,主要是有两个事件,第一个是onicecandidate,当我们收到这个事件的时候做一个处理,当我们监听到e.candidate存在我们就要发送消息给对端,另外一个参数数 ontrack,这个时候我们也可以写一个箭头函数,这个时候我们可以将收到的这个e.streams[0]也就是第一组流赋值给远端,这样当有数据来的时候,我们就可以看到这个数据了;其实这是两个事件,当这两个事件创建完了之后我们还要做一件事,也就是说当这个连接在了,我们还要给这个连接设置一些track,这个track如果是我们本地的就是localStream获取到的,如果是远端它实际走的是ontrack,所以我们就不用关心了.

所以主要就是本地,我们要做一下判断,如果localStream为真,这个时候我们要遍历它,就是获取它Tracks数组中的每一项,当我们拿到每一项track的时候我们直接pc.addTrack将它加进去就好了,这个时候如果我们是视频有音频都加到这个PeerConnection之后呢,我们进行协商的时候创建Offer它里面SDP就产生音频的媒体流和视频的媒体流,如果这时候只有音频就添加音频的媒体流,如果只有视频那就指添加视频的媒体流,就是会形成视频的媒体流,就是在SDP上,所以这个主要是起这个作用,这样才能知道双方有什么流才能进行通讯,如果你不加这个实际就不行;SDP没有表示媒体的话,那传到对方,对方就说你没有这个媒体也就不会做相应的操作,这是我们创建PeerConnection

function createPeerConnection(){

	//如果是多人的话,在这里要创建一个新的连接.
	//新创建好的要放到一个map表中。
	//key=userid, value=peerconnection
	console.log('create RTCPeerConnection!');
	if(!pc){
            var pcConfig = {
              'iceServers': [{
              'urls': 'turn:stun.al.learningrtc.cn:3478',
              'credential': "mypasswd",
              'username': "garrylea"
              }]
            };
		pc = new RTCPeerConnection(pcConfig);

		pc.onicecandidate = (e)=>{

			if(e.candidate) {
				sendMessage(roomid, {
					type: 'candidate',
					label:event.candidate.sdpMLineIndex, 
					id:event.candidate.sdpMid, 
					candidate: event.candidate.candidate
				});
			}else{
				console.log('this is the end candidate');
			}
		}

		pc.ontrack = (e)=>{
                remoteVideo.srcObject = e.streams[0];
            }
	}else {
		console.warning('the pc have be created!');
	}
    if (localStream) {
	    localStream.getTracks().forEach((track)=>{
		    pc.addTrack(track, localStream);	
	    });
    }
}

除了创建之外我们还有销毁,这个时候就比较简单了,就是说这个时候如果pc是存在的,那么我们就做这个销毁掉,我们打个console,说明我们调用了这个函数。这是这个关闭

function hangup(){
    console.log('close RTCPeerConnection!')
	if(pc) {
		pc.close();
		pc = null;
	}
}

 

还有个就是说在创建的时候已经绑定这个流了,我们还可以去关闭相应的流,就是当我们要离开的是实际是要将获取的媒体流关掉,也就是当我们结束要退出的时候我们要调用这个closeLocalMedia,我们将从设备中获取的这个track将它stop掉。

function closeLocalMedia(){

	if(localStream && localStream.getTracks()){
		localStream.getTracks().forEach((track)=>{
			track.stop();
		});
	}
	localStream = null;
}

这样我们这个PeerConnection就创建完了,创完了之后我们再看这个信令部分,在这里我们就按之前的逻辑做相应的处理了。

首先是当用户加入的时候要改变一下状态,我们的状态state就变成了joined,我们先看看有没有设置这个全局变量,一开始的时候它是初始化的,如果我们发送了这个joined,服务端给我们回了joined,这个时候我们的状态就变了,变成joined说明我们已经在这个房间中了,在这个 房间中之后我们就要创建这个PeerConnection,在这个房间之后我们就要创建这个createPeerConnection,这个时候我们创建了一个连接并且把我们本地设备获取的音视频数据,即音视频的track绑定到了这个连接上,这样就好了 。

这就是说 我们已经准备好了,如果有另外一个用户进来的时候 ,那这个时候就可以进行媒体协商了,那紧接着如果有另外一个用户就是说,也就是说现在这个房间里现在已经有了一个用户了,那么我们又调用了这个joined加入了同时服务端还会发送这个otherjoin,那么收到otherjoin收到之后,首先我们应该将它状态改变一下。

	socket.on('joined', (roomid, id) => {
		console.log('receive joined message!', roomid, id);
		state = 'joined'

		//如果是多人的话,第一个人不该在这里创建peerConnection
		//都等到收到一个otherjoin时再创建
		//所以,在这个消息里应该带当前房间的用户数
		//
		//create conn and bind media track
		createPeerConnection();
		bindTracks();

		btnConn.disabled = true;
		btnLeave.disabled = false;
		console.log('receive joined message, state=', state);
	});
	socket.on('otherjoin', (roomid) => {
		console.log('receive joined message:', roomid, state);

		//如果是多人的话,每上来一个人都要创建一个新的 peerConnection
		//
		if(state === 'joined_unbind'){
			createPeerConnection();
			bindTracks();
		}

		state = 'joined_conn';
		call();

		console.log('receive other_join message, state=', state);
	});

 

你可能感兴趣的:(WEBRTC相关)