|
@@ -70,61 +70,72 @@
|
|
|
return result ? decodeURIComponent(result[2]) : "";
|
|
|
}
|
|
|
|
|
|
+ // 从URL参数中获取当前用户ID和目标用户ID
|
|
|
var userId = getUserParamByName("userId");
|
|
|
var targetUserId = getUserParamByName("targetUserId");
|
|
|
-
|
|
|
- //initiating a call
|
|
|
- //our username
|
|
|
var connectedUser = targetUserId;
|
|
|
- //connecting to our signaling server
|
|
|
+
|
|
|
+ // 初始化WebSocket连接对象,用于信令服务器通信
|
|
|
var conn = new WebSocket("ws://"+wsHost+":"+wsPort+"/ws/video-chat/"+userId);
|
|
|
conn.onopen = function () {
|
|
|
console.log("Connected to the signaling server");
|
|
|
};
|
|
|
|
|
|
- //when we got a message from a signaling server
|
|
|
+ // 处理从信令服务器接收到的消息
|
|
|
+ // 当WebSocket接收到信令服务器发送的消息时,触发此事件处理函数
|
|
|
conn.onmessage = function (msg) {
|
|
|
+ console.log("Got message", msg.data); // 打印接收到的消息内容到控制台,用于调试
|
|
|
|
|
|
- console.log("Got message", msg.data);
|
|
|
-
|
|
|
+ // 解析从服务器接收到的JSON格式的消息数据
|
|
|
var data = JSON.parse(msg.data);
|
|
|
+ // 根据消息类型进行不同的处理
|
|
|
switch(data.type) {
|
|
|
+ // 当消息类型为"offer"时,表示远端用户希望建立连接,并发送了他们的SDP(会话描述协议)信息
|
|
|
case "offer":
|
|
|
+ // 调用handleOffer函数处理offer,设置远端描述,并创建answer响应
|
|
|
handleOffer(data.offer);
|
|
|
break;
|
|
|
+ // 当消息类型为"answer"时,表示远端用户对我们之前发送的offer做出了响应,并发送了他们的SDP信息
|
|
|
case "answer":
|
|
|
+ // 调用handleAnswer函数处理answer,设置远端描述
|
|
|
handleAnswer(data.answer);
|
|
|
break;
|
|
|
- //when a remote peer sends an ice candidate to us
|
|
|
+ // 当消息类型为"candidate"时,表示远端用户发送了ICE候选信息,用于NAT穿透和连接建立
|
|
|
case "candidate":
|
|
|
+ // 调用handleCandidate函数处理ICE候选信息,添加到RTCPeerConnection中
|
|
|
handleCandidate(data.candidate);
|
|
|
break;
|
|
|
+ // 当消息类型为"leave"时,表示远端用户希望结束通话
|
|
|
case "leave":
|
|
|
+ // 调用handleLeave函数处理离开事件,关闭连接并清理资源
|
|
|
handleLeave();
|
|
|
break;
|
|
|
+ // 默认情况,不进行任何操作
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ // 处理WebSocket连接错误
|
|
|
conn.onerror = function (err) {
|
|
|
console.log("Got error", err);
|
|
|
};
|
|
|
|
|
|
- //alias for sending JSON encoded messages
|
|
|
+ // 发送消息到信令服务器
|
|
|
function send(message) {
|
|
|
- //attach the other peer username to our messages
|
|
|
conn.send(JSON.stringify(message));
|
|
|
}
|
|
|
|
|
|
+ // 获取页面上的按钮和视频元素
|
|
|
var hangUpBtn = document.querySelector("#hangUpBtn");
|
|
|
var localVideo = document.querySelector("#localVideo");
|
|
|
var remoteVideo = document.querySelector("#remoteVideo");
|
|
|
|
|
|
- var yourConn;
|
|
|
+ // 声明RTCPeerConnection对象和流对象
|
|
|
+ var peerConnection;
|
|
|
var stream;
|
|
|
|
|
|
- // callPage.style.display = "none";
|
|
|
+ // 检测浏览器是否支持WebRTC API
|
|
|
var PeerConnection = (window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.RTCPeerConnection || undefined);
|
|
|
var RTCSessionDescription = (window.webkitRTCSessionDescription || window.mozRTCSessionDescription || window.RTCSessionDescription || undefined);
|
|
|
navigator.getUserMedia = (navigator.getUserMedia ||
|
|
@@ -132,13 +143,10 @@
|
|
|
navigator.mozGetUserMedia ||
|
|
|
navigator.msGetUserMedia);
|
|
|
|
|
|
- //getting local video stream
|
|
|
+ // 请求用户的音视频流
|
|
|
navigator.getUserMedia({ video: true, audio: true }, function (myStream) {
|
|
|
stream = myStream;
|
|
|
- // displaying local video stream on the page
|
|
|
- localVideo.srcObject = stream;
|
|
|
-
|
|
|
- // using Google public stun server
|
|
|
+ localVideo.srcObject = stream; // 将本地流绑定到本地视频元素
|
|
|
var configuration = {
|
|
|
"iceServers": [
|
|
|
{
|
|
@@ -146,19 +154,12 @@
|
|
|
}
|
|
|
]
|
|
|
};
|
|
|
-
|
|
|
- yourConn = new PeerConnection(configuration);
|
|
|
-
|
|
|
- // setup stream listening
|
|
|
- yourConn.addStream(stream);
|
|
|
-
|
|
|
- //when a remote user adds stream to the peer connection, we display it
|
|
|
- yourConn.onaddstream = function (e) {
|
|
|
- remoteVideo.srcObject = e.stream;
|
|
|
+ peerConnection = new PeerConnection(configuration); // 创建RTCPeerConnection对象
|
|
|
+ peerConnection.addStream(stream); // 将本地流添加到连接中
|
|
|
+ peerConnection.onaddstream = function (e) {
|
|
|
+ remoteVideo.srcObject = e.stream; // 将远程流绑定到远程视频元素
|
|
|
};
|
|
|
-
|
|
|
- // Setup ice handling
|
|
|
- yourConn.onicecandidate = function (event) {
|
|
|
+ peerConnection.onicecandidate = function (event) {
|
|
|
if (event.candidate) {
|
|
|
send({
|
|
|
type: "candidate",
|
|
@@ -168,31 +169,27 @@
|
|
|
});
|
|
|
}
|
|
|
};
|
|
|
- // create an offer
|
|
|
- yourConn.createOffer(function (offer) {
|
|
|
+ // 创建一个offer描述
|
|
|
+ peerConnection.createOffer(function (offer) {
|
|
|
send({
|
|
|
type: "offer",
|
|
|
offer: offer,
|
|
|
userId: userId,
|
|
|
targetUserId: targetUserId
|
|
|
});
|
|
|
- yourConn.setLocalDescription(offer);
|
|
|
+ peerConnection.setLocalDescription(offer);
|
|
|
}, function (error) {
|
|
|
alert("Error when creating an offer");
|
|
|
});
|
|
|
-
|
|
|
-
|
|
|
}, function (error) {
|
|
|
console.log(error);
|
|
|
});
|
|
|
|
|
|
- //when somebody sends us an offer
|
|
|
+ // 处理收到的offer
|
|
|
function handleOffer(offer) {
|
|
|
- yourConn.setRemoteDescription(new RTCSessionDescription(offer));
|
|
|
-
|
|
|
- //create an answer to an offer
|
|
|
- yourConn.createAnswer(function (answer) {
|
|
|
- yourConn.setLocalDescription(answer);
|
|
|
+ peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
|
|
|
+ peerConnection.createAnswer(function (answer) {
|
|
|
+ peerConnection.setLocalDescription(answer);
|
|
|
send({
|
|
|
type: "answer",
|
|
|
answer: answer,
|
|
@@ -204,39 +201,34 @@
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- //when we got an answer from a remote user
|
|
|
+ // 处理收到的answer
|
|
|
function handleAnswer(answer) {
|
|
|
- yourConn.setRemoteDescription(new RTCSessionDescription(answer));
|
|
|
+ peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
|
|
|
}
|
|
|
|
|
|
- //when we got an ice candidate from a remote user
|
|
|
+ // 处理收到的ICE候选
|
|
|
function handleCandidate(candidate) {
|
|
|
- yourConn.addIceCandidate(new RTCIceCandidate(candidate));
|
|
|
+ peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
|
|
|
}
|
|
|
|
|
|
- //hang up
|
|
|
+ // 挂断按钮事件监听器
|
|
|
hangUpBtn.addEventListener("click", function () {
|
|
|
-
|
|
|
send({
|
|
|
type: "leave",
|
|
|
userId: userId,
|
|
|
targetUserId: targetUserId
|
|
|
});
|
|
|
-
|
|
|
handleLeave();
|
|
|
});
|
|
|
|
|
|
+ // 处理离开事件
|
|
|
function handleLeave() {
|
|
|
connectedUser = null;
|
|
|
remoteVideo.src = null;
|
|
|
-
|
|
|
- yourConn.close();
|
|
|
- yourConn.onicecandidate = null;
|
|
|
- yourConn.onaddstream = null;
|
|
|
- layer.closeAll();
|
|
|
+ peerConnection.close(); // 关闭RTCPeerConnection
|
|
|
+ peerConnection.onicecandidate = null;
|
|
|
+ peerConnection.onaddstream = null;
|
|
|
+ layer.closeAll(); // 关闭所有层(可能是第三方库函数)
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
</script>
|
|
|
</html>
|