Failed to set session description: OperationError: Failed to set remote answer sdp: Called in wrong state: STATE_INPROGRESS
Failed to set session description: OperationError: Failed to set remote answer sdp: Called in wrong state: STATE_INPROGRESS
我使用了 Angular JS:- 从服务器端获取空间 Id/Token 以连接网络套接字
应用程序中使用了以下代码 -
app.controller("videoCallingController",
["$scope", "$location", "$rootScope", "$localStorage", 'AuthenticationService', "CommonService", "videoService",
function ($scope, $location, $rootScope, $localStorage, AuthenticationService, CommonService, videoService) {
$scope.UserInfo = getLoggedInUserDetails();
if ($scope.UserInfo == null) {
window.location.replace("/login.html#/");
}
$scope.offerConversationDetails = JSON.parse(localStorage.getItem('offerConversationDetails')); //$rootScope.offerConversationDetails;
$scope.IsCallBtn = false;
$scope.IsCallEnd = false;
$scope.IsRemoteStreaming = false;
//------- start custom Web socket ----------------
var ws;
function initWS(groupname) {
// var groupname = "TestRoom";
ws = new WebSocket("wss://" + location.host + "/api/" + "api/Values/Get?id=" + groupname);
ws.onopen = function () { };
ws.onmessage = function (evt) {
var signal = null;
if (!pc1) { answerCall(); }
signal = JSON.parse(evt.data);
if (signal.sdp) {
console.log("Received SDP from remote peer.");
pc1.setRemoteDescription(new RTCSessionDescription(signal.sdp));
createAndSendAnswer(signal.sdp);
}
else if (signal.candidate) {
console.log("Received ICECandidate from remote peer.");
//pc1.addIceCandidate(new RTCIceCandidate(signal.candidate));
addIceCandidate(signal);
} else if (signal.closeConnection) {
console.log("Received 'close call' signal from remote peer.");
//endCall();
}
};
ws.onerror = function (evt) {
console.log(evt.message);
};
ws.onclose = function () {
console.log("disconnected");
};
}
function sendWS(msg) {
if (ws.readyState == WebSocket.OPEN) {
ws.send(msg);
}
}
function closeWS() {
ws.close();
}
//------- end custom Web socket ----------------
//---- start Html element selectors ------------
//var callButton = document.getElementById('callButton');
//callButton.onclick = initiateCall;
var startTime;
var localVideo = document.getElementById('localVideo');
var remoteVideo = document.getElementById('remoteVideo');
localVideo.addEventListener('loadedmetadata', function () {
trace('Local video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});
remoteVideo.addEventListener('loadedmetadata', function () {
trace('Remote video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});
remoteVideo.onresize = function () {
trace('Remote video size changed to ' +
remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
// We'll use the first onsize callback as an indication that video has started
// playing out.
if (startTime) {
var elapsedTime = window.performance.now() - startTime;
trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
startTime = null;
}
};
//---- end Html element selectors ------------
var localStream;
var pc1;
// var pc2;
var offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
function getName(pc) {
return 'pc1'; //(pc === pc1) ? 'pc1' : 'pc2';
}
function getOtherPc(pc) {
return pc1; //(pc === pc1) ? pc2 : pc1;
}
function gotStream(stream) {
trace('Received local stream');
//localVideo = attachMediaStream(localVideo, stream);
// attachMediaStream(localVideo, stream);
console.log(attachMediaStream(localVideo, stream));
localStream = stream;
// callButton.disabled = false;
muteAudio(stream);
}
function muteAudio(stream) {
var AudioTrack = stream.getAudioTracks()[0];
//var localAudioBtn = document.getElementById('localAudioBtn');
var muteBtn = document.getElementById('localAudioMuteBtn');
var unMuteBtn = document.getElementById('localAudioUnMuteBtn');
//localAudioBtn.style.visibility = 'visible';
unMuteBtn.onclick = MuteUnMute;
muteBtn.onclick = MuteUnMute;
function MuteUnMute() {
AudioTrack.enabled = !AudioTrack.enabled;
muteBtn.className = 'btn btn-info btn-lg' + (AudioTrack.enabled ? '' : ' hidden');
unMuteBtn.className = 'btn btn-warning btn-lg' + (AudioTrack.enabled ? ' hidden' : '');
//localAudioBtn.className = 'button button-mute' + (AudioTrack.enabled ? '' : ' muted');
};
}
function gumFailed(e) {
alert('getUserMedia() error: ' + e.name);
}
function start() {
trace('Requesting local stream');
// startButton.disabled = true;
var constraints = {
audio: true,
video: { width: 1280, height: 720 } //true
};
if (typeof Promise === 'undefined') {
navigator.getUserMedia(constraints, gotStream, gumFailed);
} else {
navigator.mediaDevices.getUserMedia(constraints)
.then(gotStream)
.catch(gumFailed);
}
}
var Room = {};
Room.createNewRoom = function () {
if ($scope.offerConversationDetails.type == 'owner') {
videoService.CreateNewRoom($scope.offerConversationDetails.offerId, function (resp) {
if (resp.status === iresponseStatus.success) {
console.log("CreateNewRoom");
console.log(resp.result);
$scope.roomDetails = resp.result;
$rootScope.offerRoomId = $scope.roomDetails.RoomId;
Room.getRoomStatusById($scope.roomDetails.RoomId);
}
else if (resp.status === iresponseStatus.error) {
if (resp.error.code == 5) {
callDateTimeExpired(resp.error.message);
}
displayNoty("error", resp.error.message);
console.log(resp.error);
setTimeout(function () { Room.createNewRoom(); }, 10000);
}
});
}
}
Room.getRoomToken = function () {
if ($scope.offerConversationDetails.type == 'winner') {
videoService.GetRoomToken($scope.offerConversationDetails.offerId, function (resp) {
if (resp.status === iresponseStatus.success) {
console.log("Get Room Token");
console.log(resp.result);
$scope.roomDetails = resp.result;
$rootScope.offerRoomId = $scope.roomDetails.RoomId;
initWS($scope.roomDetails.RoomToken);
}
else if (resp.status === iresponseStatus.error) {
console.log(resp.error);
if (resp.error.code == 5) {
callDateTimeExpired(resp.error.message);
}
setTimeout(function () { Room.getRoomToken(); }, 1000);
}
});
}
}
Room.getRoomStatusById = function (roomId) {
if ($scope.offerConversationDetails.type == 'owner') {
videoService.GetRoomStatusById(roomId, function (resp) {
if (resp.status === iresponseStatus.success) {
if (resp.result == 2) //Active
{
initWS($scope.roomDetails.RoomToken);
$scope.IsCallBtn = true;
}
else {
//setTimeout(Room.getRoomStatusById(roomId), 100);
setTimeout(function () { Room.getRoomStatusById(roomId); }, 100);
}
}
else if (resp.status === iresponseStatus.error) {
console.log(resp.error);
if (resp.error.code == 5) {
callDateTimeExpired(resp.error.message);
}
//setTimeout(Room.getRoomStatusById(roomId), 100);
setTimeout(function () { Room.getRoomStatusById(roomId); }, 100);
}
});
}
}
Room.updateRoomConsumption = function () {
if ($scope.offerConversationDetails.type == 'owner') {
updateRoomConsumption_interval = setInterval(UpdateRoomConsumption(), 5000);
}
}
var updateRoomConsumption_interval = null;
function UpdateRoomConsumption() {
if ($scope.offerConversationDetails.ChatDurationSeconds > $scope.seconds) {
videoService.UpdateRoomConsumption($scope.roomDetails.RoomId, $scope.seconds, function (resp) {
if (resp.status === iresponseStatus.success) {
// $scope.seconds += 5;
//setTimeout(function () { Room.updateRoomConsumption(); }, 5000);
}
else if (resp.status === iresponseStatus.error) {
console.log(resp.error);
}
});
}
else {
EndCall();
clearInterval(updateRoomConsumption_interval);
}
$scope.seconds = $scope.seconds + 5;
}
//initWS();
start();
Room.createNewRoom();
Room.getRoomToken();
function prepareCall() {
// callButton.disabled = true;
trace('Starting call');
startTime = 4410; //window.performance.now();
var videoTracks = localStream.getVideoTracks();
var audioTracks = localStream.getAudioTracks();
if (videoTracks.length > 0) {
trace('Using video device: ' + videoTracks[0].label);
}
if (audioTracks.length > 0) {
trace('Using audio device: ' + audioTracks[0].label);
}
// var servers = null;
var servers = {
iceServers: [
//{ url: "stun:23.21.150.121" },
{ url: "stun:stun.1.google.com:19302" }
//{ url: !isFirefox ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121' }
]
};
pc1 = new RTCPeerConnection(servers);
trace('Created local peer connection object pc1');
pc1.onicecandidate = function (e) {
onIceCandidate(pc1, e);
};
// pc2 = new RTCPeerConnection(servers);
//trace('Created remote peer connection object pc2');
//pc2.onicecandidate = function (e) {
// onIceCandidate(pc2, e);
//};
pc1.oniceconnectionstatechange = function (e) {
onIceStateChange(pc1, e);
};
//pc2.oniceconnectionstatechange = function (e) {
// onIceStateChange(pc2, e);
//};
pc1.onaddstream = gotRemoteStream;
};
// run start(true) to initiate a call
$scope.initiateCall = function () {
prepareCall();
pc1.addStream(localStream);
trace('Added local stream to pc1');
trace('pc1 createOffer start');
pc1.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError,
offerOptions);
};
function answerCall() {
prepareCall();
pc1.addStream(localStream);
trace('Added local stream to pc1');
//createAndSendAnswer();
};
function onCreateSessionDescriptionError(error) {
trace('Failed to create session description: ' + error.toString());
}
function onCreateOfferSuccess(desc) {
trace('Offer from pc1\n' + desc.sdp);
trace('pc1 setLocalDescription start');
pc1.setLocalDescription(desc, function () {
onSetLocalSuccess(pc1);
sendWS(JSON.stringify({ "sdp": desc }));
}, onSetSessionDescriptionError);
}
function createAndSendAnswer(desc) {
// trace('pc2 setRemoteDescription start');
pc1.setRemoteDescription(desc, function () {
onSetRemoteSuccess(pc1);
}, onSetSessionDescriptionError);
trace('pc2 createAnswer start');
//Since the 'remote' side has no media stream we need
// to pass in the right constraints in order for it to
// accept the incoming offer of audio and video.
pc1.createAnswer(onCreateAnswerSuccess, onCreateSessionDescriptionError);
};
function onSetLocalSuccess(pc) {
trace(getName(pc) + ' setLocalDescription complete');
}
function onSetRemoteSuccess(pc) {
trace(getName(pc) + ' setRemoteDescription complete');
}
function onSetSessionDescriptionError(error) {
trace('Failed to set session description: ' + error.toString());
}
function gotRemoteStream(event) {
// remoteVideo = attachMediaStream(remoteVideo, e.stream);
if (event != null && event != undefined && event.stream != null && event.stream != undefined) {
$scope.offerConversationDetails.ChatDurationSeconds = $scope.offerConversationDetails.ChatDuration * 60;
$scope.IsDisplayTimer = true; $scope.IsRemoteStreaming = true; $scope.IsCallBtn = false;
$scope.$apply();
initializeClock('clockdiv', $scope.offerConversationDetails.ChatDurationSeconds);
$scope.seconds = 0;
Room.updateRoomConsumption($scope.seconds);
//event.stream.oninactive = function ()
//{
// if ($scope.IsCallEnd == false)
// hangup();
// alert("remote streaming get stop");
//}
}
console.log(attachMediaStream(remoteVideo, event.stream));
trace('pc2 received remote stream');
}
function onCreateAnswerSuccess(desc) {
//trace('Answer from pc2:\n' + desc.sdp);
//trace('pc2 setLocalDescription start');
//pc2.setLocalDescription(desc, function () {
// onSetLocalSuccess(pc2);
//}, onSetSessionDescriptionError);
trace('pc1 setRemoteDescription start');
pc1.setLocalDescription(desc, function () {
onSetRemoteSuccess(pc1);
sendWS(JSON.stringify({ "sdp": desc }));
}, onSetSessionDescriptionError);
}
function onIceCandidate(pc, event) {
if (!event || !event.candidate) return;
sendWS(JSON.stringify({ "candidate": event.candidate }));
//var candidate = event.candidate;
//if (candidate) {
// getOtherPc(pc).addIceCandidate(new RTCIceCandidate(event.candidate),
// function () {
// onAddIceCandidateSuccess(pc);
// },
// function (err) {
// onAddIceCandidateError(pc, err);
// }
// );
// trace(getName(pc) + ' ICE candidate: \n' + event.candidate.candidate);
//}
}
function addIceCandidate(event) {
pc1.addIceCandidate(new RTCIceCandidate(event.candidate),
function () {
onAddIceCandidateSuccess(pc1);
},
function (err) {
onAddIceCandidateError(pc1, err);
}
);
trace(pc1 + ' ICE candidate: \n' + event.candidate.candidate);
}
function onAddIceCandidateSuccess(pc) {
trace(getName(pc) + ' addIceCandidate success');
}
function onAddIceCandidateError(pc, error) {
trace(getName(pc) + ' failed to add ICE Candidate: ' + error.toString());
}
function onIceStateChange(pc, event) {
if (pc) {
trace(getName(pc) + ' ICE state: ' + pc.iceConnectionState);
console.log('ICE state change event: ', event);
if (pc.iceConnectionState == 'disconnected' || pc.iceConnectionState == 'failed') {
EndCall();
}
}
}
function EndCall() {
hangup();
console.log("chatduration =" + $scope.offerConversationDetails.ChatDurationSeconds);
console.log("consumption =" + $scope.seconds);
//if ($scope.IsManuallyEnded != true)
//{
alertify.alert('Mepleez Conversation', 'Your conversation got finished. Please give conversation feedback to us.',
function () {
//hangup();
window.location.replace("/video.html#/experience");
});
//}
}
function callDateTimeExpired(message) {
alertify.alert('Mepleez Conversation', message,
function () {
// window.location.replace("/video.html#/experience");
window.location.replace("/index.html#/");
});
}
$scope.onEndCallBtnClick = function () {
//alertify.prompt('Cancel call', 'Please enter the reason for cancelling call', 'Busy with other stuff '
// , function (evt, value) {
// }
// , function () { });
alertify.confirm('End Call', 'Are you sure?', function () {
$scope.IsManuallyEnded = true;
hangup();
window.location.replace("/video.html#/experience");
}
, function () { });
}
function hangup() {
$scope.IsCallEnd = true;
trace('Ending call');
pc1.close();
// pc2.close();
pc1 = null;
// pc2 = null;
//hangupButton.disabled = true;
// callButton.disabled = false;
localStream.getTracks().forEach(function (track) {
track.stop();
});
localVideo.src = "";
remoteVideo.src = "";
closeWS();
// window.location.replace("/video.html#/experience");
}
$scope.dragOptions = {
start: function (e) {
console.log("STARTING");
},
drag: function (e) {
console.log("DRAGGING");
},
stop: function (e) {
console.log("STOPPING");
},
container: 'container'
}
SDP序列化后会有一些特殊字符进入。
所以要删除它使用下面的代码
// Workaround
function maybeAddLineBreakToEnd(sdp) {
var endWithLineBreak = new RegExp(/\n$/);
if (!endWithLineBreak.test(sdp)) {
return sdp + '\n';
}
return sdp;
}
function gotDescription(desc) {
var offer = desc;
offerSdpTextarea.value = desc.sdp;
var sdp = offerSdpTextarea.value;
sdp = maybeAddLineBreakToEnd(sdp);
console.log(sdp);
sdp = sdp.replace(/\n/g, '\r\n');
offer.sdp = sdp;
pc1.setLocalDescription(offer,
onSetOfferSDPSuccess,
onSetSDPError);
trace('Modified Offer from localPeerConnection \n' + sdp);
// sendWS(JSON.stringify({ "sdp": desc }));
sendWS(JSON.stringify(offer));
}
我使用了 Angular JS:- 从服务器端获取空间 Id/Token 以连接网络套接字 应用程序中使用了以下代码 -
app.controller("videoCallingController",
["$scope", "$location", "$rootScope", "$localStorage", 'AuthenticationService', "CommonService", "videoService",
function ($scope, $location, $rootScope, $localStorage, AuthenticationService, CommonService, videoService) {
$scope.UserInfo = getLoggedInUserDetails();
if ($scope.UserInfo == null) {
window.location.replace("/login.html#/");
}
$scope.offerConversationDetails = JSON.parse(localStorage.getItem('offerConversationDetails')); //$rootScope.offerConversationDetails;
$scope.IsCallBtn = false;
$scope.IsCallEnd = false;
$scope.IsRemoteStreaming = false;
//------- start custom Web socket ----------------
var ws;
function initWS(groupname) {
// var groupname = "TestRoom";
ws = new WebSocket("wss://" + location.host + "/api/" + "api/Values/Get?id=" + groupname);
ws.onopen = function () { };
ws.onmessage = function (evt) {
var signal = null;
if (!pc1) { answerCall(); }
signal = JSON.parse(evt.data);
if (signal.sdp) {
console.log("Received SDP from remote peer.");
pc1.setRemoteDescription(new RTCSessionDescription(signal.sdp));
createAndSendAnswer(signal.sdp);
}
else if (signal.candidate) {
console.log("Received ICECandidate from remote peer.");
//pc1.addIceCandidate(new RTCIceCandidate(signal.candidate));
addIceCandidate(signal);
} else if (signal.closeConnection) {
console.log("Received 'close call' signal from remote peer.");
//endCall();
}
};
ws.onerror = function (evt) {
console.log(evt.message);
};
ws.onclose = function () {
console.log("disconnected");
};
}
function sendWS(msg) {
if (ws.readyState == WebSocket.OPEN) {
ws.send(msg);
}
}
function closeWS() {
ws.close();
}
//------- end custom Web socket ----------------
//---- start Html element selectors ------------
//var callButton = document.getElementById('callButton');
//callButton.onclick = initiateCall;
var startTime;
var localVideo = document.getElementById('localVideo');
var remoteVideo = document.getElementById('remoteVideo');
localVideo.addEventListener('loadedmetadata', function () {
trace('Local video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});
remoteVideo.addEventListener('loadedmetadata', function () {
trace('Remote video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});
remoteVideo.onresize = function () {
trace('Remote video size changed to ' +
remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
// We'll use the first onsize callback as an indication that video has started
// playing out.
if (startTime) {
var elapsedTime = window.performance.now() - startTime;
trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
startTime = null;
}
};
//---- end Html element selectors ------------
var localStream;
var pc1;
// var pc2;
var offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
function getName(pc) {
return 'pc1'; //(pc === pc1) ? 'pc1' : 'pc2';
}
function getOtherPc(pc) {
return pc1; //(pc === pc1) ? pc2 : pc1;
}
function gotStream(stream) {
trace('Received local stream');
//localVideo = attachMediaStream(localVideo, stream);
// attachMediaStream(localVideo, stream);
console.log(attachMediaStream(localVideo, stream));
localStream = stream;
// callButton.disabled = false;
muteAudio(stream);
}
function muteAudio(stream) {
var AudioTrack = stream.getAudioTracks()[0];
//var localAudioBtn = document.getElementById('localAudioBtn');
var muteBtn = document.getElementById('localAudioMuteBtn');
var unMuteBtn = document.getElementById('localAudioUnMuteBtn');
//localAudioBtn.style.visibility = 'visible';
unMuteBtn.onclick = MuteUnMute;
muteBtn.onclick = MuteUnMute;
function MuteUnMute() {
AudioTrack.enabled = !AudioTrack.enabled;
muteBtn.className = 'btn btn-info btn-lg' + (AudioTrack.enabled ? '' : ' hidden');
unMuteBtn.className = 'btn btn-warning btn-lg' + (AudioTrack.enabled ? ' hidden' : '');
//localAudioBtn.className = 'button button-mute' + (AudioTrack.enabled ? '' : ' muted');
};
}
function gumFailed(e) {
alert('getUserMedia() error: ' + e.name);
}
function start() {
trace('Requesting local stream');
// startButton.disabled = true;
var constraints = {
audio: true,
video: { width: 1280, height: 720 } //true
};
if (typeof Promise === 'undefined') {
navigator.getUserMedia(constraints, gotStream, gumFailed);
} else {
navigator.mediaDevices.getUserMedia(constraints)
.then(gotStream)
.catch(gumFailed);
}
}
var Room = {};
Room.createNewRoom = function () {
if ($scope.offerConversationDetails.type == 'owner') {
videoService.CreateNewRoom($scope.offerConversationDetails.offerId, function (resp) {
if (resp.status === iresponseStatus.success) {
console.log("CreateNewRoom");
console.log(resp.result);
$scope.roomDetails = resp.result;
$rootScope.offerRoomId = $scope.roomDetails.RoomId;
Room.getRoomStatusById($scope.roomDetails.RoomId);
}
else if (resp.status === iresponseStatus.error) {
if (resp.error.code == 5) {
callDateTimeExpired(resp.error.message);
}
displayNoty("error", resp.error.message);
console.log(resp.error);
setTimeout(function () { Room.createNewRoom(); }, 10000);
}
});
}
}
Room.getRoomToken = function () {
if ($scope.offerConversationDetails.type == 'winner') {
videoService.GetRoomToken($scope.offerConversationDetails.offerId, function (resp) {
if (resp.status === iresponseStatus.success) {
console.log("Get Room Token");
console.log(resp.result);
$scope.roomDetails = resp.result;
$rootScope.offerRoomId = $scope.roomDetails.RoomId;
initWS($scope.roomDetails.RoomToken);
}
else if (resp.status === iresponseStatus.error) {
console.log(resp.error);
if (resp.error.code == 5) {
callDateTimeExpired(resp.error.message);
}
setTimeout(function () { Room.getRoomToken(); }, 1000);
}
});
}
}
Room.getRoomStatusById = function (roomId) {
if ($scope.offerConversationDetails.type == 'owner') {
videoService.GetRoomStatusById(roomId, function (resp) {
if (resp.status === iresponseStatus.success) {
if (resp.result == 2) //Active
{
initWS($scope.roomDetails.RoomToken);
$scope.IsCallBtn = true;
}
else {
//setTimeout(Room.getRoomStatusById(roomId), 100);
setTimeout(function () { Room.getRoomStatusById(roomId); }, 100);
}
}
else if (resp.status === iresponseStatus.error) {
console.log(resp.error);
if (resp.error.code == 5) {
callDateTimeExpired(resp.error.message);
}
//setTimeout(Room.getRoomStatusById(roomId), 100);
setTimeout(function () { Room.getRoomStatusById(roomId); }, 100);
}
});
}
}
Room.updateRoomConsumption = function () {
if ($scope.offerConversationDetails.type == 'owner') {
updateRoomConsumption_interval = setInterval(UpdateRoomConsumption(), 5000);
}
}
var updateRoomConsumption_interval = null;
function UpdateRoomConsumption() {
if ($scope.offerConversationDetails.ChatDurationSeconds > $scope.seconds) {
videoService.UpdateRoomConsumption($scope.roomDetails.RoomId, $scope.seconds, function (resp) {
if (resp.status === iresponseStatus.success) {
// $scope.seconds += 5;
//setTimeout(function () { Room.updateRoomConsumption(); }, 5000);
}
else if (resp.status === iresponseStatus.error) {
console.log(resp.error);
}
});
}
else {
EndCall();
clearInterval(updateRoomConsumption_interval);
}
$scope.seconds = $scope.seconds + 5;
}
//initWS();
start();
Room.createNewRoom();
Room.getRoomToken();
function prepareCall() {
// callButton.disabled = true;
trace('Starting call');
startTime = 4410; //window.performance.now();
var videoTracks = localStream.getVideoTracks();
var audioTracks = localStream.getAudioTracks();
if (videoTracks.length > 0) {
trace('Using video device: ' + videoTracks[0].label);
}
if (audioTracks.length > 0) {
trace('Using audio device: ' + audioTracks[0].label);
}
// var servers = null;
var servers = {
iceServers: [
//{ url: "stun:23.21.150.121" },
{ url: "stun:stun.1.google.com:19302" }
//{ url: !isFirefox ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121' }
]
};
pc1 = new RTCPeerConnection(servers);
trace('Created local peer connection object pc1');
pc1.onicecandidate = function (e) {
onIceCandidate(pc1, e);
};
// pc2 = new RTCPeerConnection(servers);
//trace('Created remote peer connection object pc2');
//pc2.onicecandidate = function (e) {
// onIceCandidate(pc2, e);
//};
pc1.oniceconnectionstatechange = function (e) {
onIceStateChange(pc1, e);
};
//pc2.oniceconnectionstatechange = function (e) {
// onIceStateChange(pc2, e);
//};
pc1.onaddstream = gotRemoteStream;
};
// run start(true) to initiate a call
$scope.initiateCall = function () {
prepareCall();
pc1.addStream(localStream);
trace('Added local stream to pc1');
trace('pc1 createOffer start');
pc1.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError,
offerOptions);
};
function answerCall() {
prepareCall();
pc1.addStream(localStream);
trace('Added local stream to pc1');
//createAndSendAnswer();
};
function onCreateSessionDescriptionError(error) {
trace('Failed to create session description: ' + error.toString());
}
function onCreateOfferSuccess(desc) {
trace('Offer from pc1\n' + desc.sdp);
trace('pc1 setLocalDescription start');
pc1.setLocalDescription(desc, function () {
onSetLocalSuccess(pc1);
sendWS(JSON.stringify({ "sdp": desc }));
}, onSetSessionDescriptionError);
}
function createAndSendAnswer(desc) {
// trace('pc2 setRemoteDescription start');
pc1.setRemoteDescription(desc, function () {
onSetRemoteSuccess(pc1);
}, onSetSessionDescriptionError);
trace('pc2 createAnswer start');
//Since the 'remote' side has no media stream we need
// to pass in the right constraints in order for it to
// accept the incoming offer of audio and video.
pc1.createAnswer(onCreateAnswerSuccess, onCreateSessionDescriptionError);
};
function onSetLocalSuccess(pc) {
trace(getName(pc) + ' setLocalDescription complete');
}
function onSetRemoteSuccess(pc) {
trace(getName(pc) + ' setRemoteDescription complete');
}
function onSetSessionDescriptionError(error) {
trace('Failed to set session description: ' + error.toString());
}
function gotRemoteStream(event) {
// remoteVideo = attachMediaStream(remoteVideo, e.stream);
if (event != null && event != undefined && event.stream != null && event.stream != undefined) {
$scope.offerConversationDetails.ChatDurationSeconds = $scope.offerConversationDetails.ChatDuration * 60;
$scope.IsDisplayTimer = true; $scope.IsRemoteStreaming = true; $scope.IsCallBtn = false;
$scope.$apply();
initializeClock('clockdiv', $scope.offerConversationDetails.ChatDurationSeconds);
$scope.seconds = 0;
Room.updateRoomConsumption($scope.seconds);
//event.stream.oninactive = function ()
//{
// if ($scope.IsCallEnd == false)
// hangup();
// alert("remote streaming get stop");
//}
}
console.log(attachMediaStream(remoteVideo, event.stream));
trace('pc2 received remote stream');
}
function onCreateAnswerSuccess(desc) {
//trace('Answer from pc2:\n' + desc.sdp);
//trace('pc2 setLocalDescription start');
//pc2.setLocalDescription(desc, function () {
// onSetLocalSuccess(pc2);
//}, onSetSessionDescriptionError);
trace('pc1 setRemoteDescription start');
pc1.setLocalDescription(desc, function () {
onSetRemoteSuccess(pc1);
sendWS(JSON.stringify({ "sdp": desc }));
}, onSetSessionDescriptionError);
}
function onIceCandidate(pc, event) {
if (!event || !event.candidate) return;
sendWS(JSON.stringify({ "candidate": event.candidate }));
//var candidate = event.candidate;
//if (candidate) {
// getOtherPc(pc).addIceCandidate(new RTCIceCandidate(event.candidate),
// function () {
// onAddIceCandidateSuccess(pc);
// },
// function (err) {
// onAddIceCandidateError(pc, err);
// }
// );
// trace(getName(pc) + ' ICE candidate: \n' + event.candidate.candidate);
//}
}
function addIceCandidate(event) {
pc1.addIceCandidate(new RTCIceCandidate(event.candidate),
function () {
onAddIceCandidateSuccess(pc1);
},
function (err) {
onAddIceCandidateError(pc1, err);
}
);
trace(pc1 + ' ICE candidate: \n' + event.candidate.candidate);
}
function onAddIceCandidateSuccess(pc) {
trace(getName(pc) + ' addIceCandidate success');
}
function onAddIceCandidateError(pc, error) {
trace(getName(pc) + ' failed to add ICE Candidate: ' + error.toString());
}
function onIceStateChange(pc, event) {
if (pc) {
trace(getName(pc) + ' ICE state: ' + pc.iceConnectionState);
console.log('ICE state change event: ', event);
if (pc.iceConnectionState == 'disconnected' || pc.iceConnectionState == 'failed') {
EndCall();
}
}
}
function EndCall() {
hangup();
console.log("chatduration =" + $scope.offerConversationDetails.ChatDurationSeconds);
console.log("consumption =" + $scope.seconds);
//if ($scope.IsManuallyEnded != true)
//{
alertify.alert('Mepleez Conversation', 'Your conversation got finished. Please give conversation feedback to us.',
function () {
//hangup();
window.location.replace("/video.html#/experience");
});
//}
}
function callDateTimeExpired(message) {
alertify.alert('Mepleez Conversation', message,
function () {
// window.location.replace("/video.html#/experience");
window.location.replace("/index.html#/");
});
}
$scope.onEndCallBtnClick = function () {
//alertify.prompt('Cancel call', 'Please enter the reason for cancelling call', 'Busy with other stuff '
// , function (evt, value) {
// }
// , function () { });
alertify.confirm('End Call', 'Are you sure?', function () {
$scope.IsManuallyEnded = true;
hangup();
window.location.replace("/video.html#/experience");
}
, function () { });
}
function hangup() {
$scope.IsCallEnd = true;
trace('Ending call');
pc1.close();
// pc2.close();
pc1 = null;
// pc2 = null;
//hangupButton.disabled = true;
// callButton.disabled = false;
localStream.getTracks().forEach(function (track) {
track.stop();
});
localVideo.src = "";
remoteVideo.src = "";
closeWS();
// window.location.replace("/video.html#/experience");
}
$scope.dragOptions = {
start: function (e) {
console.log("STARTING");
},
drag: function (e) {
console.log("DRAGGING");
},
stop: function (e) {
console.log("STOPPING");
},
container: 'container'
}
SDP序列化后会有一些特殊字符进入。 所以要删除它使用下面的代码
// Workaround
function maybeAddLineBreakToEnd(sdp) {
var endWithLineBreak = new RegExp(/\n$/);
if (!endWithLineBreak.test(sdp)) {
return sdp + '\n';
}
return sdp;
}
function gotDescription(desc) {
var offer = desc;
offerSdpTextarea.value = desc.sdp;
var sdp = offerSdpTextarea.value;
sdp = maybeAddLineBreakToEnd(sdp);
console.log(sdp);
sdp = sdp.replace(/\n/g, '\r\n');
offer.sdp = sdp;
pc1.setLocalDescription(offer,
onSetOfferSDPSuccess,
onSetSDPError);
trace('Modified Offer from localPeerConnection \n' + sdp);
// sendWS(JSON.stringify({ "sdp": desc }));
sendWS(JSON.stringify(offer));
}