What are the steps to enable screen sharing within an Electron application?

I am currently working on developing two applications for screen sharing within a LAN setting using Electron, React, and TypeScript. The first app will capture the screen stream and broadcast it via UDP, while the second app, running on multiple devices, will receive the stream and display it. I have explored the desktopCapturer API provided by Electron, but encountered an error when attempting to run this code snippet:

desktopCapturer
      .getSources({ types: ["window", "screen"] })
      .then(async (sources) => {
        for (const source of sources) {
          if (source.name === "Entire Screen") {
            const displayMediaOptions = {
              video: {
                cursor: "always",
                mandatory: {
                  chromeMediaSource: "desktop",
                  chromeMediaSourceId: source.id,
                  maxWidth: 800,
                  maxHeight: 700,
                },
              },
              audio: false,
            };

            try {
              const stream = await navigator.mediaDevices.getUserMedia(
                displayMediaOptions
              );
              handleStream(stream);
            } catch (e) {
              handleError(e);
            }
            return;
          }
        }
      });

The specific error message is as follows:

Argument of type '{ video: { cursor: string; mandatory: { chromeMediaSource: string; chromeMediaSourceId: string; maxWidth: number; maxHeight: number; }; }; audio: boolean; }' is not assignable to parameter of type 'MediaStreamConstraints'.
  Types of property 'video' are incompatible.
    Type '{ cursor: string; mandatory: { chromeMediaSource: string; chromeMediaSourceId: string; maxWidth: number; maxHeight: number; }; }' is not assignable to type 'boolean | MediaTrackConstraints'.
      Type '{ cursor: string; mandatory: { chromeMediaSource: string; chromeMediaSourceId: string; maxWidth: number; maxHeight: number; }; }' has no properties in common with type 'MediaTrackConstraints'.ts(2345)

Upon further investigation, I discovered that the MediaTrackConstraints does not support the mandatory property. Additionally, I learned about WebRTC as a potential solution, but I am unsure if it can function in a LAN environment without external server support.

Therefore, I am seeking advice on any possible workarounds for this issue or alternative technologies that could be utilized for screen sharing within a local network?

Answer №1

When it comes to obtaining stream sources, the approach of creating the stream from the electron side can be altered by retrieving the list of source ids using desktop capturer and initiating the video stream on the renderer side, namely the react side.

Here is a method I implemented to accomplish this:

In the electron preload script:

getDesktopSources: async () =>
  await desktopCapturer
    .getSources({
      types: ['window', 'screen'],
    })
    .then((sources) =>
      sources.map((source) => ({
        id: source.id,
        name: source.name,
        appIconUrl: source?.appIcon?.toDataURL(),
        thumbnailUrl: source?.thumbnail
          ?.resize({ height: 160 })
          .toDataURL(),
      }))
    )

This preload function is invoked in the react side as shown below:

const turnScreenSharingOn = useCallback(async () => {
  const sources = await window.electron.media.getDesktopSources();
  setScreenSources(sources);
  setScreenSharePopupVisible(true);
}, []);

I display these sources in a popup for the user to select which screen they want to share. Upon selection, the following function is executed:

const onScreenChoose = useCallback(
  async (sourceId: string, cb?: () => void) => {
    const stream = await navigator.mediaDevices.getUserMedia({
      audio: false,
      video: {
        mandatory: {
          chromeMediaSource: 'desktop',
          chromeMediaSourceId: sourceId,
        },
      } as MediaTrackConstraints,
    });
    
    handleStream(stream)    

    cb?.();
  },
  []
);

The track is generated exclusively on the react side using the source id obtained from electron through desktop capturer.

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

Warning: Outdated version detected during NestJS installation on npm

Whenever I attempt to download NestJS using the command npm i -g @nestjs/cli, I encounter the following issue: npm WARN deprecated <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a6d5c9d3d4c5c3cb8ed7cbc1ccdcdffccdc3d0"><?[ ...

Is there a way for me to determine if an open port is TCP or HTTP?

Currently, I am using a Windows server (Windows 7), and when I run the netstat -an command, it only indicates whether ports are TCP or UDP. However, I have discovered that node.js differentiates between HTTP ports and TCP ports (example found at the bottom ...

I am interested in creating a Discord bot that can send interval messages

I am trying to set up a discord bot that sends a message at regular intervals, like every 10 minutes. However, I keep running into an error. Can someone please assist me with this issue? (Apologies for any language errors in my message) Below is the code ...

Neglecting to send a socket signal while assigning a variable to a socket message

In my client-side script, I am using the following snippet: socket.on('bla', function(data) { if (data == ID) { console.log('I don't understand what's happening here.'); } }) socket.on(ID, function(data) { ...

Angular - Electron interface fails to reflect updated model changes

Whenever I click on a field that allows me to choose a folder from an electron dialog, the dialog opens up and I am able to select the desired folder. However, after clicking okay, even though the folder path is saved in my model, it does not immediately s ...

Building a web application using the Nuxt.js framework and Express generator

Seeking help to seamlessly integrate an express app generated with express generator into my nuxt.js application. Came across this https://github.com/nuxt-community/express-template, although it seems to only cover basic express applications. Any recomme ...

Does DustJS configuration on the server side allow new lines without escaping them?

I am currently using DustJS in combination with ExpressJS and NodeJS. When ExpressJS renders my DustJS templates, it automatically escapes the new lines and white spaces. However, since I am incorporating JavaScript into my DustJS templates, I want to pre ...

retrieving information from the database and passing it to the controller

I'm in the process of developing a new API with Express, following the MVC architecture. However, I've been facing difficulties getting the data to successfully return from the database access file to the controllers file. Initially, I attempted ...

What is the process of extracting information from a JSON file and how do I convert the Date object for data retrieval?

export interface post { id: number; title: string; published: boolean; flagged: string; updatedAt: Date; } ...

The type parameter is overlooked by body-parser

When handling inbound requests with a Content-Type: application/vnd.surveymonkey.response.v1+json, I encountered some difficulties using the body-parser. According to the documentation, the body-parser's json factory method should only parse json and ...

Instructions on transferring information from the app.component to its child components

I am currently working with Angular 6 and I have a specific requirement. I need to send data retrieved from an external API in my app.component to other child components. Instead of repeatedly calling the common API/service in every component, I want to ma ...

Why isn't Nodemon monitoring the directory in webpack-typescript-node.js?

Here are the contents of the package.json file for a TypeScript project using webpack and node.js: "scripts": { "build": "webpack", "dev:start": "nodemon --watch src --exec \"node -r dotenv/co ...

Configuring proxy settings in npm-yeoman package

I'm currently developing my Angular application using Yeoman. I've configured proxies and registry settings as shown below: npm config set proxy http://proxy.tcs.com:8080 npm config set https-proxy http://proxy.tcs.com:8080 npm config set reg ...

Error: The node user directory does not exist, please check your command input

After foolishly running this script in an attempt to avoid using sudo for npm -g commands, my node_modules directory has now moved to: /Users/myusername/.npm-packages/lib/node_modules Now when trying to run commands like yo or bower, I encounter the error ...

Delaying the initialization of an object in Node.js to make requests wait

Imagine having an application that provides exchange rates for the current day. The process involves retrieving data via REST, storing it in a cache, and then serving clients from this cache. I want the request to a 3rd party API to only occur when someone ...

Encountering issues with retrieving application setting variables from Azure App Service in a ReactJS TypeScript application resulting in '

My dilemma lies in my app setup which involves a Node.js runtime stack serving a ReactJs Typescript application. I have set some API URLs in the application settings, and attempted to access them in ReactJs components using process.env.REACT_APP_URL, only ...

Error: The property 'case sensitive routing' cannot be accessed because it is undefined

Task at hand: Running ExpressJS port using Node.js, nodemon, and lib. Operating System: Windows 10 Home x64 Node.JS Version: Lts The Challenge: Getting the ExpressJS port to run successfully. Current Issue: Encountering an internal file error, potentiall ...

Socket.on seems to be malfunctioning

Currently, I am in the process of creating a message board for practice purposes and have successfully implemented notifications and a chat application using socket.io. My next goal is to add basic video call functionality, but I have encountered some dif ...

NodeJS CORS functionality failing to function properly in the Google Chrome browser

In my nodejs script, I have implemented CORS as shown below: var express = require('express') , cors = require('cors') , app = express(); app.use(cors()); To fetch JSON data from another domain, I am using an AJAX request. While ...

Installing sodium on Raspberry Pi leads to installation failure

Despite using sudo to install Sodium with NPM on my Raspberry Pi, the installation always fails and continues to mention a lack of write access to /home/Captain/node_modules/libsodium. I'm puzzled as to why this issue persists even with elevated privi ...