Search code examples
javascriptreactjswebrtc

WebRTC onTrack not triggered


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


Solution

  • 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.