Unable to access remote video streams by directly modifying URL parameters

Recently, I delved into experimenting with the straightforward mediasoup demo available at: https://github.com/Dirvann/mediasoup-sfu-webrtc-video-rooms

After setting up the demo, everything seemed to be functioning correctly.

The initial task on my agenda was to incorporate URL parameters to bypass the login screen. It sounded like a simple enough task, right? However, when trying to access a room directly by manipulating the URL parameters, that's where things took an unexpected turn – the remote streams of other users weren't displaying in the room! Strangely enough, they did display when a user entered a room through the login form.

What confuses me is that whether you click 'join' via the login form or have the parameters already in the URL, the same JavaScript method is triggered!

Let me walk you through the execution flow:

Initially, we have one user sharing their webcam in room 123. A second user visits the URL without the relevant parameters and encounters the login form: https://i.sstatic.net/bxfgp.png

Upon reviewing the details, the user decides to stick with the defaults and clicks the join button. This action triggers a basic function that updates the URL with the room and user values, leading to a page refresh.

After the page finishes refreshing, the required parameters are present, resulting in the video room loading and the remote stream appearing as shown here: https://i.sstatic.net/mPoEE.png

However, the issue arises when we skip the login form and directly append those necessary parameters to the URL ourselves, depicted here: https://i.sstatic.net/d35yM.png There should ideally be a remote stream displayed here since it's the same room from the previous image. I'm completely puzzled as to why this problem persists.

Included below is my index.js file, with all the modifications enclosed within the slashes towards the end of the file:

if (location.href.substr(0, 5) !== 'https')
  location.href = 'https' + location.href.substr(4, location.href.length - 4)

const socket = io()


let producer = null;

nameInput.value = 'bob' + Math.round(Math.random() * 1000)

socket.request = function request(type, data = {}) {
  return new Promise((resolve, reject) => {
    socket.emit(type, data, (data) => {
      if (data.error) {
        reject(data.error)
      } else {
        resolve(data)
      }
    })
  })
}

let rc = null

function joinRoom(name, room_id) {
  if (rc && rc.isOpen()) {
    console.log('already connected to a room')
  } else {
    rc = new RoomClient(localMedia, remoteVideos, remoteAudios, window.mediasoupClient, socket, room_id, name, roomOpen)

    addListeners()
  }

}



function roomOpen() {
  login.className = 'hidden'
  reveal(startAudioButton)
  hide(stopAudioButton)
  reveal(startVideoButton)
  hide(stopVideoButton)
  reveal(startScreenButton)
  hide(stopScreenButton)
  reveal(exitButton)
  control.className = ''
  reveal(videoMedia)
}

function hide(elem) {
  elem.className = 'hidden'
}

function reveal(elem) {
  elem.className = ''
}


function addListeners() {
  rc.on(RoomClient.EVENTS.startScreen, () => {
    hide(startScreenButton)
    reveal(stopScreenButton)
  })

  rc.on(RoomClient.EVENTS.stopScreen, () => {
    hide(stopScreenButton)
    reveal(startScreenButton)

  })

  rc.on(RoomClient.EVENTS.stopAudio, () => {
    hide(stopAudioButton)
    reveal(startAudioButton)

  })
  rc.on(RoomClient.EVENTS.startAudio, () => {
    hide(startAudioButton)
    reveal(stopAudioButton)
  })

  rc.on(RoomClient.EVENTS.startVideo, () => {
    hide(startVideoButton)
    reveal(stopVideoButton)
  })
  rc.on(RoomClient.EVENTS.stopVideo, () => {
    hide(stopVideoButton)
    reveal(startVideoButton)
  })
  rc.on(RoomClient.EVENTS.exitRoom, () => {
    hide(control)
    reveal(login)
    hide(videoMedia)

    /////////////////////////
    let indexOfQuestionMark = location.href.indexOf("?")
    location.href = location.href.split('').slice(0, indexOfQuestionMark-1).join('')
    /////////////////////////

  })
}

// Load mediaDevice options
navigator.mediaDevices.enumerateDevices().then(devices =>
  devices.forEach(device => {
    let el = null
    if ('audioinput' === device.kind) {
      el = audioSelect
    } else if ('videoinput' === device.kind) {
      el = videoSelect
    }
    if(!el) return

    let option = document.createElement('option')
    option.value = device.deviceId
    option.innerText = device.label
    el.appendChild(option)
  })
)
/////////////////////////
if (window.location.href.includes("?r=") && window.location.href.includes("n=")) {
  let indexOfRoomNumber = location.href.indexOf("?r=")+3
  let array = location.href.split('')
  let room = array.slice(indexOfRoomNumber,indexOfRoomNumber+3).join("")
  let username = array.slice(indexOfRoomNumber+6, array.length).join("")
  joinRoom(username,room)
  console.log(`Welcome to room: ${room}, ${username}`)

}

function addParams(name, room_id) {
  window.location.href = `${location.href}?r=${room_id}+n=${name}`
}
//////////////////////////

The Join button within index.html invokes the addParams function directly, visible here:

<html>

<head>
    <script src="socket.io/socket.io.js"></script>
    <script src="modules/mediasoupclient.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.2.8/EventEmitter.min.js"></script>
    <script src="RoomClient.js"></script>
    <style>
        .containers {
            display: grid;
            grid-gap: 5px;
            grid-template-columns: repeat(auto-fit, 1fr);
            grid-template-rows: repeat(auto-fit, 300px);
        }

        .container {
            display: flex;
        }

        .vid {
            flex: 0 1 auto;
            height: 400px;
        }

        .settings {
            background-color: #4CAF50;
            border: none;
            color: white;
            padding: 5px 10px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 14px;
            margin: 2px 2px;
            cursor: pointer;
        }

        .hidden {
            display: none
        }
    </style>
</head>

<body>
    <div id="login">
        Room:   <input id="roomidInput" value="123" type="text" />
        <!--<button id="createRoom" onclick="createRoom(roomid.value)" label="createRoom">Create Room</button>-->
        <br />
        User: <input id='nameInput' value="bob" type="text" />
        <button id='joinButton' onclick="addParams(nameInput.value, roomidInput.value)">Join</button>
    </div>
    <div id="control" class="hidden">
        <button id='exitButton' class='hidden' onclick="rc.exit()">Exit</button>
        <br/>
        audio: <select id="audioSelect">
        </select>
        <br/>
        video: <select id="videoSelect">
        </select>
        <br />
        <button id='startAudioButton' class='hidden' onclick="rc.produce(RoomClient.mediaType.audio, audioSelect.value)">audio</button>
        <button id='stopAudioButton' class='hidden' onclick="rc.closeProducer(RoomClient.mediaType.audio)">close
            audio</button>
        <button id='startVideoButton' class='hidden' onclick="rc.produce(RoomClient.mediaType.video, videoSelect.value)">video</button>
        <button id='stopVideoButton' class='hidden' onclick="rc.closeProducer(RoomClient.mediaType.video)">close
            video</button>
        <button id='startScreenButton' class='hidden' onclick="rc.produce(RoomClient.mediaType.screen)">screen</button>
        <button id='stopScreenButton' class='hidden' onclick="rc.closeProducer(RoomClient.mediaType.screen)">close
            screen</button>
        <br />
    </div>




    <div id='videoMedia' class='hidden'>
        <h2>------local------</h2>
        <div id="localMedia"></div>
        <!--<video id="localVideo" autoplay inline class="vid"></video>-->
        <!--<video id="localScreen" autoplay inline class="vid"></video>-->
        <h2>-----remote-----</h2>
        <div id="remoteVideos" class="container">
        </div>

        <div id="remoteAudios"></div>

    </div>
</body>
<footer>
    <script src="index.js"></script>
</footer>

</html>

Kindly note that the only files I've made changes to are the ones mentioned above. All other files remain identical to those in the GitHub repository for the demo (linked in the introduction).

It would greatly appreciate any guidance provided to help me uncover the root cause of this predicament. If the presence of URL parameters is what's affecting the room connections, then why does inserting them directly into the URL seem to yield such different outcomes?

Thank you sincerely for your time and any support you can offer! :)

Answer №1

The main distinction lies in the absence of user interaction required to establish the connection. Some browser functions necessitate user input, which may be the contributing factor to why it's not functioning as expected. Check out this link for more information on Autoplay policy changes.

To potentially resolve the issue, consider adding a button that triggers the joinRoom function when visiting the webpage.

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

Designing an interactive HTML table that adapts to various screen

Currently utilizing Bootstrap to create a responsive HTML table on smaller devices like the iPad, but seeking a more polished and professional alternative. Searching for a JQuery/JavaScript or CSS solution without relying on plugins. Would appreciate any ...

Scrolling Container Following Down the Page, Halts at Its Own Bottom (Similar to Twitter)

I am facing an issue and need some help. I am working on creating a three-column page layout where the middle section is for posts, the right section is for links and references (a bit long), and the left section is fixed. My question is: How can I preven ...

Replacing the useEffect hook with @tanstack/react-query

Lately, I made the decision to switch from my useEffect data fetches to react-query. While my useEffect implementation was working flawlessly, I encountered various issues when trying to directly convert my code for react-query. All the examples I found ...

What is the reason for encodeURIComponent not encoding single quotes or apostrophes?

Although the escape() function was deprecated and replaced by encodeURIComponent, there is an issue with encodeURIComponent as it doesn't encode the single quote/apostrophe character. This poses a problem when trying to escape apostrophes in someone&a ...

Encountering issues while trying to install Java using NPM

Encountering errors when attempting to run the following command to install java dependencies for NPM. NPM install -g java In need of assistance to fix this error. C:\WINDOWS\system32>npm i -g java [email protected] install C:\D ...

Is it possible for a memory leak to occur in node.js when using new Date()?

For this particular case, when updating an existing MongoDB document with new Date() causing a potential memory leak is a question that arises. One might wonder if allocating a new object with the new keyword necessitates manual deallocation to prevent lea ...

Retrieve the value of an object property within a function

I'm facing a bit of a challenge here and couldn't find a solution. Here's an illustration of the object I am working with: obj = { key1 : {val : "hi", val2 : "pizza"}, key2 : {val : "hello", val2 : "cheese"} ...

What could be the reason for the malfunction of this angular binding?

Looking at the HTML below: <input type="checkbox" name="person" [(ngModel)]="person.selected" /> This input is part of a ngFor loop. Testing has revealed that despite some values of selected being true and others false, all checkboxes appear check ...

Transfer information between two devices remotely through AJAX

I am in the process of developing a web application that utilizes a mobile phone as a controller, similar to this example: . The concept is quite simple - I just need to transfer text entered on the phone to the computer. There is no need for a database, ...

Having trouble correctly parsing XML data using JavaScript

My input field contains the following XML code: <?xml version="1.0" encoding="utf-8"?> <players timestamp="1536505850"> <player id="0518" name="Eagles, Philadelphia" position="Def" team="PHI" /> <player id="10271" name="Jones, Jul ...

Tips for integrating AudioControl with Phonegap

I couldn't find a suitable plugin, so I decided to create my own. My goal is to activate silent mode using a JavaScript command, however, I am encountering an error with the undefined method getSystemService. It seems like there may be a problem with ...

Refreshing the current window with the ``Window.location.reload()`` function

I have integrated a map that displays clients using markers. The map I am utilizing is Leaflet with an AngularJS directive. The issue I am facing is that when I initially access the map, it functions correctly. However, when I change routes, all the marke ...

Cutting imagery to create a new design element

https://i.sstatic.net/IAh0h.jpg There is an image above with 6 gears (circles with pointy edges). My goal is to separate them into individual pictures and, on each picture's hover, have a relevant line with text appear. How can I achieve this? The a ...

What steps can be taken to adjust a module required in Node.js prior to initiating the build process?

Module A.js (standard NPM package): module.exports = { ... const wsUrl = `ws://${customHostname}:${customPort}/sockjs-node/websocket`; ... }; Module B.js: const a = require('A'); Is there a way to substitute ${customHostname} & ${cu ...

Exploring the interactive features of discord.js version 12

Currently, I have a bot set up to log when invites are created, but the logs are only going to a specific channel ID that I designated. I would like to make it so that this can be changed on a per-server basis. Intended Output User: !log channel (CHANNEL ...

There was an issue with the vue-server-renderer where the render function or template was not defined in the component

In my project with Vue 2.7 and webpack4 for SSR, I encountered an error message stating: render function or template not defined in component: anonymous. This issue arises under the following circumstances: When using a child component. <template> ...

Is it possible to implement drag and drop functionality for uploading .ply, .stl, and .obj files in an angular application?

One problem I'm facing is uploading 3D models in angular, specifically files with the extensions .ply, .stl, and .obj. The ng2-upload plugin I'm currently using for drag'n'drop doesn't support these file types. When I upload a file ...

Rapid polygon merging with JavaScript

I have a large geoJSON file containing polygons and multi-polygons, totaling 2.5 MB in size. My goal is to merge all these shapes to display them on a map within a web browser environment. In my Python workflow, I am using shapely.ops.unary_union which p ...

Filtering elements in a table using jQuery

Can anyone provide a solution to display students without a class and hide the rest (where td Class-name is empty) using only jQuery or JS? I tried looking in the documentation but got lost. Any help would be appreciated. Example: table image The table ...

Is the input field not properly centered on the page?

Can someone explain why the input field is not aligning in the center? I am new to web development and need some assistance. <input type="text" id="search_bar" class="form-control" placeholder="Search" align="center"> In my CSS, I've ...