First of all, issue here is different from all I found in "google" as I'm using Spring Boot as signaling server to connect two different browser's tabs or they are using two peerConnection to send stream within one tab.
Peers seem to be connected and messages are sent correctly. However, when I run sendStream with button, second tab track event listener doesn't trigger.
//connecting to our signaling server
var conn = new WebSocket('ws://localhost:8080/socket');
conn.onopen = function() {
console.log("Connected to the signaling server");
initialize();
};
conn.onmessage = function(msg) {
console.log("Got message", msg.data);
var content = JSON.parse(msg.data);
var data = content.data;
switch (content.event) {
// when somebody wants to call us
case "offer":
handleOffer(data);
break;
case "answer":
handleAnswer(data);
break;
// when a remote peer sends an ice candidate to us
case "candidate":
handleCandidate(data);
break;
default:
break;
}
};
function send(message) {
conn.send(JSON.stringify(message));
}
var peerConnection;
var dataChannel;
var input = document.getElementById("messageInput");
function initialize() {
var configuration = null;
peerConnection = new RTCPeerConnection(configuration);
// Setup ice handling
peerConnection.onicecandidate = function(event) {
if (event.candidate) {
send({
event : "candidate",
data : event.candidate
});
}
};
const remoteVideo = document.getElementById('video');
peerConnection.addEventListener('track', async (event) => {
const [remoteStream] = event.streams;
remoteVideo.srcObject = remoteStream;
console.log("STREAM RECEIVED");
});
// creating data channel
dataChannel = peerConnection.createDataChannel("dataChannel", {
reliable : true
});
dataChannel.onerror = function(error) {
console.log("Error occured on datachannel:", error);
};
// when we receive a message from the other peer, printing it on the console
dataChannel.onmessage = function(event) {
console.log("message:", event.data);
};
dataChannel.onclose = function() {
console.log("data channel is closed");
};
peerConnection.ondatachannel = function (event) {
dataChannel = event.channel;
};
}
function createOffer() {
peerConnection.createOffer(function(offer) {
send({
event : "offer",
data : offer
});
peerConnection.setLocalDescription(offer);
}, function(error) {
alert("Error creating an offer");
});
}
function handleOffer(offer) {
peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
// create and send an answer to an offer
peerConnection.createAnswer(function(answer) {
peerConnection.setLocalDescription(answer);
send({
event : "answer",
data : answer
});
}, function(error) {
alert("Error creating an answer");
});
};
function handleCandidate(candidate) {
peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
};
function handleAnswer(answer) {
peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
console.log("connection established successfully!!");
};
function sendMessage() {
dataChannel.send(input.value);
input.value = "";
}
async function sendStream() {
const localStream = await navigator.mediaDevices.getUserMedia({audio: false, video: true});
localStream.getTracks().forEach(track => {
peerConnection.addTrack(track, localStream);
console.log("STREAM SENT")
const localVideo = document.getElementById('video2');
addVideoStream(localVideo, localStream);
});
}
function addVideoStream(video, stream) {
video.srcObject = stream;
video.addEventListener('loadedmetadata', () => {
video.play();
})
}
If you already have an established WebRTC connection, renegotiation is needed for the new track to be sent.
The reason is that peers need to choose codecs and other parameters included in SDP. Otherwise your browser won't tell how to compress the video you want to send so the receiver can decode it.
See the note on top of the page: https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack
So you probably need to set up onnegotiationneeded
callback and then send a new offer / receive a new answer.