The ontrack listener for WebRTC peerConnection fails to fire

Primarily, the challenge I'm facing is unique from what I have come across in my research on "google". My setup involves using Spring Boot as a signaling server to establish connections between two different tabs of the browser or utilizing two peerConnections within a single tab.

The connectivity between peers seems solid and messages are being transmitted without issues. However, upon executing the sendStream function with a button click, the track event listener on the second tab fails to 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();
    })
}

Answer №1

When you already have an established WebRTC connection, renegotiation becomes necessary in order for a new track to be sent.

This is because peers must select codecs and other parameters found in the SDP. Without this information, your browser won't know how to compress the video being sent so that the receiver can decode it.

For more details, please refer to the note at the top of the page: https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack

If this applies to your situation, it is likely that you will need to establish the onnegotiationneeded callback and then proceed to send a new offer / receive a new answer.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Mongoose and MongoDB in Node.js fail to deliver results for Geospatial Box query

I am struggling to execute a Geo Box query using Mongoose and not getting any results. Here is a simplified test case I have put together: var mongoose = require('mongoose'); // Schema definition var locationSchema = mongoose.Schema({ useri ...

Converting an image to base64 format for storing in localStorage using Javascript

Currently, I am working on code that sets the background-image of a link. This is what I have so far: $("a.link").css("background-image", "url('images/icon.png')"); However, I want to enhance it by storing the image in localStorage: if (!local ...

Utilize React to generate HTML content and send it as the email body through Node.js

I am currently working on a react application that consists of two main pages - AddStatus and ViewStatus. Both of these are implemented as react components. My current task involves sending out an email daily at a specific time, containing the details dis ...

What is the process for incorporating JavaScript-generated coordination into an HTML form?

As a newcomer to Javascript, I am on a mission to integrate geo coordination directly into an HTML form input field. After learning from W3Schools how to generate user latitude and longitude Coordination, I am now eager to input them directly into an HTML ...

Guide to navigating to a particular component in React JS

I've designed a web application using React that doesn't contain any HTML, and I've broken down each page into smaller modules. For instance, on the main page, the first module (located at the top) contains a button that, when clicked, shoul ...

A bug in the modal dialog is causing it to disregard the value of

I want to transfer certain modal properties in this manner service.confirm = function(message, confirmProperties) { return $uibModal.open({ templateUrl: 'app/modal/alert/alert.tpl.html', controller: 'alertCon ...

JavaScript and HTML with Node.js

Exploring the world of HTML, running smoothly with a static IP address 192.168.56.152 using apache on the host computer. <!DOCTYPE html> <html > <head> <title>OnlinePage</title> <meta charset="utf-8"& ...

Issue with React submit button for posting data is not functioning as intended

My dilemma lies within a Modal component containing a Form and Button. The goal is to trigger a POST request (managed in a separate file) upon the user clicking the button, which will run a simulation using the validated input values. Surprisingly, the onC ...

Exploring the application of javascript method within a Vue template

Currently, I am attempting to extract a numeric value from the end of a URL. However, I am encountering an error in doing so. It has been a while since I last worked with Vue, but I know that we can use methods/functions to achieve the desired outcome. Cou ...

Troubleshooting Google Authorization Issue in Angular 17: How to Fix the Error TS2304: 'google' Not Found in Angular 17

I am encountering an issue while attempting to integrate Google Auth into my Angular(+Express) application using the Google Identity Services library. Despite following the instructions provided in the Google tutorial, I am facing the error: "[ERROR] TS230 ...

3D Object Anchored in Environment - Three.js

In my current scene, I have two objects at play. Utilizing the LeapTrackballControls library for camera movement creates a dynamic where one object appears to rotate based on hand movements. However, an issue arises as the second object also moves along w ...

Cross-Origin Resource Sharing (CORS) for enabling the remote inclusion of JavaScript

I have a unique javascript widget that is designed to be embedded from an external server (e.g. ) The javascript, which contains a simple alert('hello'), is generated by a php script. Upon execution, I include a header like this: <?php heade ...

Steps to eliminate pre-chosen alternatives upon loading select control?

When using react-select with pre-selected options and multiple select enabled, the issue arises where clicking on the Select box still displays the already pre-selected options. How can I remove these duplicate options from the list? Below is a snippet of ...

Exploring the Enzyme library in React to trigger an onClick event with a specific parameter

In my quest to simulate an onClick method in my unit tests using Enzyme for React, I have encountered various tutorials on simulating an onClick event that takes an event e. For example: handleClick(e) { // Does something } .... <MyComponent onCli ...

The progress bar in Next JS 13 seems to be malfunctioning and is not displaying any

After transitioning to the new Next JS 13 app directory, I encountered an issue where the progress bar at the top does not function when the page loads. In the previous version, Next JS 12, there was a package named nprogress and nextNprogress that simpli ...

Guide to verifying a value within a JSON object in Ionic 2

Is there a way to check the value of "no_cover" in thumbnail[0] and replace it with asset/sss.jpg in order to display on the listpage? I have attempted to include <img src="{{item.LINKS.thumbnail[0]}}"> in Listpage.html, but it only shows the thumbna ...

Struggles encountered while configuring React

I'm in need of assistance with setting up React, even though I have both Node and npm installed. When I enter the following command: npx create-react-app new-test-react --use-npm I encounter the following error message: npm ERR! code ENOTFOUND npm E ...

Excessive JSON formatting is consuming an excessive amount of storage space

As I work on developing a website that recommends locations to visit in NYC, I am facing an issue with saving JSON data in local storage. My goal is to allow users to add their own suggestions and eventually integrate MongoDB into the site. To build the si ...

Suggestions for breaking out of the function update()?

Having some trouble escaping my update() function. Here's the attempt I've made: if (score.l1 > 20) { break; } However, all I get is an error message saying "Illegal break statement" ...

Is there a different method to retrieve language bundles with next-i18next instead of using a customized Node server?

Currently, I am developing a Next.js application that will utilize i18next translations organized in the recommended file structure for bundles. For example: static/locales/en/common.js static/locales/de/common.js You can refer to this article: https://m ...