Comments (11)
@saghul I made a new minimalist Electron app example and its not crashing anymore when using setupScreenSharingMain
(although I never got the screensharing to work anyways). I will continue investigating, but it might be something on my end.
from jitsi-meet-electron-sdk.
I am using Node v20.8.1.
├── [email protected]
├── [email protected]
├── @jitsi/[email protected]
├── @jitsi/[email protected]
├── [email protected]
├── @vitejs/[email protected]
For context, I am working on a Vite React project. When I run my Electron main file I also start an Express server that serves the static files of the React project to localhost:4000/. In my main electron file, I start the Express server, create a window, and then load localhost:4000/ onto that window to interact with the React app. Locally, @jitsi/react-sdk has worked great with the Vite project. But when using the app inside an Electron window, screen sharing crashes. And my understanding is that I need to use '@jitsi/electron-sdk' to fix this.
I have tried 3 different approaches which have all failed.
Approach 1: Setting nodeIntegration to false and contextIsolation to true
This appears to be best practice for security reasons.
electron/main/index.ts:
...
win = new BrowserWindow({
title: 'Main window',
webPreferences: {
preload,
contextIsolation: true,
nodeIntegration: false,
sandbox: false
}
})
const appName = 'doffice'
const osxBundleId = 'com.ebox.doffice'
setupScreenSharingMain(win, appName, osxBundleId)
...
Then I expose the render setup functions to my React app using a contextBridge.
electron/preload/index.ts:
import {
setupScreenSharingRender,
initPopupsConfigurationRender,
setupPowerMonitorRender
} from '@jitsi/electron-sdk'
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron'
const whitelistedIpcChannels = ['protocol-data-msg', 'renderer-ready']
function openExternalLink (url: string): void {
ipcRenderer.send('jitsi-open-url', url)
}
/**
* Setup the renderer process.
*
* @param api - API object.
* @param options - Options for what to enable.
* @returns void
*/
function setupRenderer (api: any): void { // Replace `any` with a more specific type if available
initPopupsConfigurationRender(api)
const iframe = api.getIFrame()
setupScreenSharingRender(api)
setupPowerMonitorRender(api)
}
contextBridge.exposeInMainWorld('electron', {
openExternalLink,
setupRenderer,
ipc: {
on: (channel: any, listener: any) => {
if (!whitelistedIpcChannels.includes(channel)) {
return
}
ipcRenderer.on(channel, listener)
},
send: (channel: any, ...args: any) => {
if (!whitelistedIpcChannels.includes(channel)) {
return
}
ipcRenderer.send(channel, ...args)
},
removeListener: (channel: any, listener: any) => {
if (!whitelistedIpcChannels.includes(channel)) {
return
}
ipcRenderer.removeListener(channel, listener)
}
}
})
And finally in my React Jitsi Meets Component:
...
const handleApiReady = (externalApi: ExtendedJitsiMeetExternalApi) => {
window.electron.setupRenderer(externalApi)
...
When initializing the Jitsi meet, this approach results in:
Error: An object could not be cloned.
at de (index-64573305.js:312:34866)
at onApiReady (index-64573305.js:312:36517)
It seems like I am unable to pass through the entire externalApi object through a context bridge. This seems to be an Electron contstraint and I have to move on to a different approach. Others mentioned that I need to slim down the object passed through the bridge, but after looking into the jitsi-meet-electron-sdk functions called in the preload file, the entire externalApi object seems to be required. This could be the same as this person's issue: #337
Approach 2: Same as Approach 1 but import the functions directly in Vite React without using a bridge
In my React Vite Meeting Component I import the functions like so:
import {
setupScreenSharingRender,
initPopupsConfigurationRender,
setupPowerMonitorRender
} from '@jitsi/electron-sdk'
And define the setupRenderer function:
function setupRenderer (api: any): void {
initPopupsConfigurationRender(api)
setupScreenSharingRender(api)
setupPowerMonitorRender(api)
}
And finally:
const handleApiReady = (externalApi: ExtendedJitsiMeetExternalApi) => {
setupRenderer(jitsiApi.current)
Does not work because I get:
Uncaught ReferenceError: require is not defined
I was unable to exactly find where this error was located, but looking at the static javascript, these lines are causing it:
, Ype = require("fs")
, Cu = require("path")
, Xpe = require("os")
And just a few lines below were these lines:
var o = ["platform=" + i3, "arch=" + r3, "runtime=" + Pk, "abi=" + EQ, "uv=" + Zpe, a3 ? "armv=" + a3 : "", "libc=" + Jpe, "node=" + process.versions.node, process.versions.electron ? "electron=" + process.versions.electron : "", typeof __webpack_require__ == "function" ? "webpack=true" : ""].filter(Boolean).join(" ");
throw new Error("No native build was found for " + o + ` loaded from: ` + e + `
Approach 3: Same as Approach 2 but set nodeIntegration to true and contextIsolation to false
This approach resulted in the error:
index-2a0550b8.js:312 Uncaught Error: No native build was found for platform=win32 arch=x64 runtime=electron abi=118 uv=1 libc=glibc node=18.17.1 electron=27.0.3
loaded from: C:\Users\...\Documents\...\node_modules\electron\dist\resources\electron.asar\renderer
The above approach seems to be the farthest I have made it into the jitsi-meet-electron-sdk library without crashing. But ultimately even that approach should be avoided it seems like, due to the security concerns related to nodeIntegration set to true.
How would you recommend I should approach this? @saghul
from jitsi-meet-electron-sdk.
If all you need is screen-sharing perhaps you could use this as an example and skip using the SDK: https://github.com/gabiborlea/jitsi-meet-electron-example
from jitsi-meet-electron-sdk.
You need to be running a recent jitsi meet server for it to work.
from jitsi-meet-electron-sdk.
What SDK version are you using?
from jitsi-meet-electron-sdk.
What SDK version are you using?
I simply ran
npm install @jitsi/electron-sdk
yesterday so I'm assuming it's the latest version 6.0.4. I will double check when I get home in ~3h.
I confirmed this is what's in my package.json:
"@jitsi/electron-sdk": "^6.0.17"
Is there any other context I can give that could help identify the issue?
from jitsi-meet-electron-sdk.
If all you need is screen-sharing perhaps you could use this as an example and skip using the SDK: https://github.com/gabiborlea/jitsi-meet-electron-example
This worked!
So to inform anyone else seeing this. If you had similar issues as I did, and only need the screen sharing for Electron with Jitsi, then you can do the following:
Add this to your main electron file:
const hasPermission =
systemPreferences.getMediaAccessStatus('screen') === 'granted'
if (!hasPermission) {
exec('tccutil reset ScreenCapture ' + pkgJson.build.appId)
}
ipcMain.handle('jitsi-screen-sharing-get-sources', (_event, options) =>
desktopCapturer.getSources(options).then((sources) => {
return sources.map(item => {
return {
...item,
thumbnail: {
dataUrl: item.thumbnail.toDataURL()
}
}
})
})
)
Note: This solution also allows the BrowserWindow that loads your web app to have the following safe configuration:
nodeIntegration: false,
contextIsolation: true,
webSecurity: true,
Then in your preload file, you can add something like this:
import { contextBridge, ipcRenderer } from 'electron'
contextBridge.exposeInMainWorld('electronAPI', {
getDesktopSources: (options: any) => ipcRenderer.invoke('jitsi-screen-sharing-get-sources', options)
})
Then, in your renderer, where your Jitsi Meet External API becomes available, in my case a "handleApiReady" function, you can add this, for example:
const handleApiReady = (externalApi: ExtendedJitsiMeetExternalApi) => {
if (window.electronAPI) {
externalApi.on('_requestDesktopSources', async (request, callback) => {
const { options } = request
window.electronAPI.getDesktopSources(options)
.then(sources => {
// eslint-disable-next-line n/no-callback-literal
callback({ sources })
})
// eslint-disable-next-line n/no-callback-literal
.catch((error) => callback({ error }))
})
}
Keeping the callbacks as they are i.e callback({ sources }) and callback({ error }) was necessary for it not to crash, so I disabled my own no-callback literal eslint errors.
Now it finally works! Both for screen sharing in Jitsi after loading the Vite React localhost:5173 development server in a BrowserWindow, but also for loading the statically built Vite React project in a BrowserWindow. 🎉
from jitsi-meet-electron-sdk.
externalApi.on('_requestDesktopSources', async (request, callback) => {
@saghul @wbigert HI, please tell me where I can find information about this event. It seems that it does not trigger for me
from jitsi-meet-electron-sdk.
@wbigert Has this been fixed by the following PR: #369
from jitsi-meet-electron-sdk.
Good ping, that too!
from jitsi-meet-electron-sdk.
@wbigert Have you resolved this issue? I have done the same things in the electron part , but that event is not getting fired. I have jitsi meet stable server code also, but still getting issue.
Can you help me across this issue?
from jitsi-meet-electron-sdk.
Related Issues (20)
- Release prebuilt robotjs packages HOT 6
- Turn the package into a module
- Automate publishing to NPM with GH actions
- Release 3.0.0 HOT 3
- Screen Share dialog showing loading .... HOT 1
- Missing prebuilts HOT 6
- Autopublish? HOT 5
- remote control errors
- Migrate to new getDisplayMedia API HOT 2
- Auto-Release: create a GH release too
- Electron update to v.19.X, can not get source of screen share HOT 1
- I got error with electron forge
- Screen sharing with Electron that load url
- Getting cannot read properties of undefined (reading 'setupScreenSharingRender') with react and electron
- Context Isolation error HOT 2
- Opened app with deep link and Error: Called JitsiMeetElectron.obtainDesktopStreams but it is not defined HOT 4
- Does the "alwaysOnTop" small window support setting avatar?
- ScreenShare: window.JitsiMeetElectron is undefined due to loading external Jitsi Meets domain HOT 3
- ci: unpin node version once node-gyp-build has spawn fixed HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jitsi-meet-electron-sdk.