#Struggling to integrate desktop capturer. How do I approach the problem?

118 messages · Page 1 of 1 (latest)

opaque mirage
#

I have been referencing https://www.electronjs.org/docs/latest/api/desktop-capturer and https://stackoverflow.com/questions/72424013/electron-js-use-desktopcapture-outside-main-js.

Any tips on how to approach this as a beginner? Are there similar projects I can reference? The ones I found are out of date.

Access information about media sources that can be used to capture audio and video from the desktop using the navigator.mediaDevices.getUserMedia API.

silent zinc
#

what problem?

opaque mirage
#

when I turn nodeintegration: true and context: isolation to false, I get the error: contextBridge API can only be used when contextIsolation is enabled

#

but when I set contextIsolation to true, I get the error: preload.js:1 Uncaught ReferenceError: require is not defined
at preload.js:1:38

#

so it looks like for require to work, I need to set contextIsloation to False, but to get contextBridge to work, I need to set contextIsolation to True

silent zinc
#

you cant get this error in preload

opaque mirage
#

what do you mean?

#

Because I have this in my preload, "const {contextBridge, ipcRenderer} = require("electron");"

silent zinc
#

preload always have access to require

#

if preload correctly used

opaque mirage
#

preload: path.join(__dirname, 'preload.js'),?

silent zinc
#

yes

opaque mirage
#

I'm sure the preload is correct because when I try src/preload, the whole thing goes down

#

what do you think I'm doing wrong with preload?

silent zinc
#

I think you add it in html

#

So you load preload fine twice

opaque mirage
#

<script defer src="preload.js"></script>

#

do it twice?

#

or do I need src/preload in html?

#

Ahh, I fixed it

#

thank you!

#

Now getting the error "DOMException: Could not start video source"

#

I do not believe my browser is being claimed by anything

#

Nvm, fixed it as well!

opaque mirage
#

I currently have a video file saved as a blob and moving the blob from render.js to main.js using ipcRenderer. I am getting an error and stackoverflow says the error is from moving the blob using ipcRenderer. What is the best way for me to save the blob as a video file?

const blob = new Blob(recordedChunks, {
type: 'video/webm; codecs=vp9'
});

silent zinc
#

convert blob to buffer

#

buffer write to harddrive from preload file

opaque mirage
#

For more context, I am turning the blob into a buffer in main.js and saving the buffer as using fs

#

When I tried to turn to buffer in render.js using "const buffer = Buffer.from(await blob.arrayBuffer());"

#

The system said that Buffer did not exist

silent zinc
#

system?

opaque mirage
#

what do you mean?

#

like windows?

silent zinc
#
The system said that Buffer did not exist
#

this system

opaque mirage
#

hold on, let me recreate it

#

Uncaught ReferenceError: Buffer is not defined
at MediaRecorder.handleStop

#

// Create the Media Recorder
options = { mimeType: 'video/webm; codecs=vp9' };
mediaRecorder = new MediaRecorder(stream, options);

// Register Event Handlers
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.onstop = handleStop;

silent zinc
#

buffer is nodejs feature

#

browser use ArrayBuffer

opaque mirage
#

and I don't have access to node.js in render.js so I need to use arraybuffer correct?

silent zinc
#

yes

#

blob.arrayBuffer() do that

#

you need to send it over context bridge

#

and save it via fs module

opaque mirage
#

ok, I'll give it a shot

silent zinc
#

or you can do everyting in preload

opaque mirage
#

so instead of const buffer = Buffer.from(await blob.arrayBuffer());

#

I should have const buffer = blob.arrayBuffer(); correct?

silent zinc
#

its depends what you supposed to do with that buffer

#

if you working in preload

#

you dont need to convert it

#

if you work in renderer

#

contextBridge probably convert arraybuffer into buffer

opaque mirage
#

I'm getting this error now. I'm saving the buffer to the file in main. Uncaught (in promise) Error: An object could not be cloned.
Promise.then (async)
handleStop @ render.js:83

silent zinc
#

why you need buffer in main?

opaque mirage
#

because I'm doing this in main

#

ipcMain.on('save-video', (event, data) => {

function saveBuffer(b){

const { filePath } = dialog.showSaveDialog({
  buttonLabel: 'Save video',
  defaultPath: `vid-${Date.now()}.webm`
});

if (filePath) {
  writeFile(filePath, b, () => console.log('video saved successfully!'));
}

}

#

and calling saveBuffer(data)

silent zinc
#

you can call dialog only

#

and getting result in preload

#

ipc cloning data

#

and it have limit on data size

opaque mirage
#

and do that under contextbridge?

#

contextBridge.exposeInMainWorld('electron', {
getSources: () => ipcRenderer.invoke('get-sources'),
saveVideo: (buf) => ipcRenderer.invoke('save-video', buf),
})

#

like run it all in saveVideo?

silent zinc
#

use fs module in preload

#

instead of main

opaque mirage
#

I'll try that

silent zinc
#

so you use ipc.invoke to get dialog result

#

and use fs in preload

opaque mirage
#

I'm not understanding this. Do you mean for me to first send from render to preload, then from preload to main, the from main back to preload? I don't know what you mean by use ipc.invoke to get dialog result

silent zinc
#

you have save-video event

#

where you sending file over it

#

and where you open dialog

#

instead of it

#

send ipc.invoke with openning dialog

#

when you get result save buffer into file

#

you dont need to send file buffer to main

#

only ask dialog to open

opaque mirage
#

I'll give it a shot

opaque mirage
#

const {contextBridge, ipcRenderer, dialog} = require("electron");
const{writeFile} = require('fs');

contextBridge.exposeInMainWorld('electron', {
getSources: () => ipcRenderer.invoke('get-sources'),
saveVideo: (buf) => {
const {filePath} = dialog.showSaveDialog({
buttonLabel: 'Save video',
defaultPath: vid-${Date.now()}.webm
})
if (filePath) {
writeFile(filePath, buf, () => console.log('video saved successfully!'));
}
}
});

#

@silent zinc Do you mind editing my code? I'm stuck.

silent zinc
#

with what?

opaque mirage
#

how to write the preload file

#

do I need a then()?

silent zinc
#

where?

opaque mirage
#

so first, save video gets called, which triggers showSaveDialog.

#

I then have the file path

#

then writefile?

silent zinc
#

you dont have then

opaque mirage
#

do I need a then in there?

silent zinc
#

because you cant open dialog

#

and it throw an error

opaque mirage
#

what do you mean by this? send ipc.invoke with openning dialog

#

and by result, do you mean filepath?

silent zinc
#

i dont see ipc.invoke with dialog

opaque mirage
#

const {contextBridge, ipcRenderer, dialog} = require("electron");
const{writeFile} = require('fs');

contextBridge.exposeInMainWorld('electron', {
getSources: () => ipcRenderer.invoke('get-sources'),
saveVideo: (buf) =>
ipcRenderer.invoke(dialog.showSaveDialog({
buttonLabel: 'Save video',
defaultPath: vid-${Date.now()}.webm
}))
});

\

#

like this?

#

I'm completely lose

#

lost

silent zinc
#

lost

#

yes

#

why you dont use docs?

opaque mirage
#

I do

#

I don't understand it

silent zinc
#

then look

#

this is first

#

dialog only available in main process

#

2nd dialog api return a promise

#

use dialog and ipcRenderer.invoke example

#

not this

#

start with dialog

#

when you successfully get result from it in preload save faile with fs module

#

and read about js promises+async/await

opaque mirage
#

Will do, thanks!