Skip to content

Instantly share code, notes, and snippets.

@aiddya
Created October 5, 2023 02:20
Show Gist options
  • Save aiddya/cfd89d040661e0553425e4203ce4512b to your computer and use it in GitHub Desktop.
Save aiddya/cfd89d040661e0553425e4203ce4512b to your computer and use it in GitHub Desktop.
Electron Fiddle Gist
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="img-src 'self' data:; default-src 'self'; script-src 'self'">
<title>Hello World!</title>
</head>
<body>
<h1>Desktop Capture</h1>
<button type="button" id="both-btn">Get screens and windows</button>
<button type="button" id="screens-btn">Get screens</button>
<button type="button" id="windows-btn">Get windows</button>
<button type="button" id="stop-stream">Stop stream</button>
<h1>Sources</h1>
<div id="sources"></div>
<h1>Preview</h1>
<video width="640" height="480"></video>
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, desktopCapturer } = require('electron')
const path = require('path')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 1300,
height: 1000,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
async function getDesktopSources(source_types) {
return desktopCapturer.getSources({types: source_types}).then(sources => {
return sources.map(item => ({
id: item.id,
name: item.name,
image: item.thumbnail.toDataURL()
}))
}).catch(error => console.log(error))
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
ipcMain.handle('main:list:all', () => getDesktopSources(['screen', 'window']))
ipcMain.handle('main:list:windows', () => getDesktopSources(['window']))
ipcMain.handle('main:list:screens', () => getDesktopSources(['screen']))
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
{
"name": "desktop-capture-preview",
"productName": "desktop-capture-preview",
"description": "My Electron application description",
"keywords": [],
"main": "./main.js",
"version": "1.0.0",
"author": "athul",
"scripts": {
"start": "electron ."
},
"dependencies": {},
"devDependencies": {
"electron": "27.0.0-beta.9"
}
}
/**
* The preload script runs before. It has access to web APIs
* as well as Electron's renderer process modules and some
* polyfilled Node.js functions.
*
* https://www.electronjs.org/docs/latest/tutorial/sandbox
*/
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electron', {
listAll: () => ipcRenderer.invoke('main:list:all'),
listScreens: () => ipcRenderer.invoke('main:list:screens'),
listWindows: () => ipcRenderer.invoke('main:list:windows'),
})
/**
* This file is loaded via the <script> tag in the index.html file and will
* be executed in the renderer process for that window. No Node.js APIs are
* available in this process because `nodeIntegration` is turned off and
* `contextIsolation` is turned on. Use the contextBridge API in `preload.js`
* to expose Node.js functionality from the main process.
*/
const both_btn = document.getElementById("both-btn")
both_btn.addEventListener('click', async () => {
displaySources(await window.electron.listAll())
})
const screens_btn = document.getElementById("screens-btn")
screens_btn.addEventListener('click', async () => {
displaySources(await window.electron.listScreens())
})
const windows_btn = document.getElementById("windows-btn")
windows_btn.addEventListener('click', async () => {
displaySources(await window.electron.listWindows())
})
async function displaySources(desktop_sources) {
const sources_element = document.getElementById("sources")
sources_element.replaceChildren()
for (i = 0; i < desktop_sources.length; i++) {
const source_div = document.createElement("div")
const source_thumb = document.createElement("img")
source_thumb.src = desktop_sources[i].image
source_div.appendChild(source_thumb)
const source_btn = document.createElement("button")
const source_id = desktop_sources[i].id
source_btn.innerHTML = source_id
source_btn.addEventListener('click', () => startDisplayMedia(source_id))
source_div.appendChild(source_btn)
sources_element.appendChild(source_div)
}
}
async function startDisplayMedia(source_id) {
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: source_id
}
}
})
handleStream(stream)
setupStopStream(stream)
setTimeout(function(){startDisplayMedia(source_id)}, 10000)
} catch (e) {
handleError(e)
}
}
function setupStopStream(stream) {
const both_btn = document.getElementById("stop-stream")
both_btn.addEventListener('click', async () => {
stream.getTracks().forEach(track => track.stop())
})
}
function handleStream(stream) {
const video = document.querySelector("video")
video.srcObject = stream
video.onloadedmetadata = (e) => video.play()
}
function handleError(e) {
console.log(e)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment