the ontrack not treggerd even if i add the ice candidate and the state is connected and also the connection stable and booth browsers are connected !! but the on track is not working i use spring boot as signalign server and he is doing his work on changing offer and answer between browsers and i use the chrom webrtc internal too check the status of my peer and it is connected but i don't understand why the on track is not triggered i need help
const [socketUrl, setSocketUrl] = useState('ws://localhost:8085/socket');
const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl);
const [peerConnection, setPeerConnection] = useState(null);
const [dataChannel, setDataChannel] = useState(null);
const [mediaStream, setMediaStream] = useState(null);
const [receivedMessage, setReceivedMessage] = useState('');
const [display,setDisplay] = useState(false)
const [videoElement, setVideoElement] = useState(null);
useEffect(() => {
if (readyState === WebSocket.OPEN) {
console.log("WebSocket connection opened");
const configuration = {
iceServers: [
{
urls: 'stun:stun.l.google.com:19302'
},
{
urls: 'turn:10.158.29.39:3478?transport=udp',
credential: 'XXXXXXXXXXXXX',
username: 'XXXXXXXXXXXXXXX'
},
{
urls: 'turn:10.158.29.39:3478?transport=tcp',
credential: 'XXXXXXXXXXXXX',
username: 'XXXXXXXXXXXXXXX'
}
],
offerToReceiveAudio: true,
offerToReceiveVideo: true
};
var pc = new RTCPeerConnection(configuration);
console.log('creating a peer connection ')
setPeerConnection(pc);
setDisplay(true);
// Corrected the variable name here
var dataChannel = pc.createDataChannel("dataChannel", { reliable: true });
console.log("Data channel created:", dataChannel);
pc.ondatachannel = function(event) {
console.log("Received data channel:", event.channel);
var dataChannel = event.channel;
dataChannel.onopen = function(event) {
console.log("Data channel is open");
// You can now send messages through this data channel
console.log('sending message')
dataChannel.send("Hello from receiver!");
};
dataChannel.onerror = function(error) {
console.error("Data channel error:", error);
};
dataChannel.onclose = function() {
console.log("Data channel is closed");
};
};
dataChannel.onmessage = function(event) {
console.log('you have a new message')
console.log("Received message:", event.data);
// Handle the received message here
};
function sendMessageThroughDataChannel(message) {
if (dataChannel && dataChannel.readyState === "open") {
dataChannel.send(message);
console.log('message send')
} else {
console.error("Data channel is not open or not initialized.");
}
}
pc.onerror = function(error) {
console.error("Peer connection error:", error);
};
pc.onicecandidate = (event) => {
console.log("ICE candidate:", event.candidate);
if (event.candidate) {
console.log("New ICE candidate:", event.candidate);
// Optionally, log the entire SDP
console.log("Current SDP:", pc.localDescription);
sendMessage(JSON.stringify({ event: "candidate", data: event.candidate }));
} else {
console.log("No more ICE candidates.");
}
};
pc.oniceerror = function(error) {
console.error("ICE error:", error);
};
const remoteVideo = document.querySelector('#remoteVideo');
pc.addEventListener('track', async (event) => {
console.log('hey')
const [remoteStream] = event.streams;
remoteVideo.srcObject = remoteStream;
});
pc.oniceconnectionstatechange = async (event) => {
console.log(`ICE connection state changed to ${pc.iceConnectionState}`);
if (pc.iceConnectionState === 'connected') {
const localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
localStream.getTracks().forEach(track => {
pc.addTrack(track, localStream);
});
checkIfStreamAdded(pc);
}
};
function checkIfStreamAdded(pc) {
// Get the senders (tracks) that are currently being sent
const senders = pc.getSenders();
// Check if there are any senders (tracks) being sent
if (senders.length > 0) {
console.log("Streams are added to the peer connection.");
} else {
console.log("No streams are added to the peer connection.");
}
}
// Create offer
pc.createOffer()
.then((offer) => {
console.log("Creating offer...");
pc.setLocalDescription(offer);
sendMessage(JSON.stringify({ event: "offer", data: offer }));
})
.catch((error) => {
console.error("Failed to create offer", error);
});
}
else {
console.error("WebSocket connection not open!");
}
}, [readyState, sendMessage]);
useEffect(() => {
if (lastMessage && lastMessage.data) {
const message = JSON.parse(lastMessage.data);
console.log('Received message:', message.data);
switch (message.event) {
case "offer":
console.log("Setting remote description for offer...");
console.log('here', message.data)
peerConnection.setRemoteDescription(new RTCSessionDescription(message.data))
.then(() => {
console.log("Creating answer...");
return peerConnection.createAnswer();
})
.then((answer) => {
console.log('Sending answer');
peerConnection.setLocalDescription(answer);
sendMessage(JSON.stringify({ event: "answer", data: answer }));
})
.catch((error) => {
console.error("Failed to create answer", error);
});
break;
case "answer":
console.log("Setting remote description for answer...");
peerConnection.setRemoteDescription(new RTCSessionDescription(message.data));
break;
case "candidate":
console.log("Adding ICE candidate...");
peerConnection.addIceCandidate(new RTCIceCandidate(message.data));
break;
default:
console.log('Default case');
setReceivedMessage(message.data);
break;
}
}
}, [lastMessage, peerConnection]);
i try too do an application of live streaming
You are adding the track when the iceconnectionstate
changes to connected
(and note that this can happen multiple times) but you do not call createOffer, setLocalDescription et al afterwards which is required.
Move the addTrack
calls before you call createOffer.