【发布时间】:2017-03-30 17:36:59
【问题描述】:
我正在开发一个electron 应用程序,该应用程序使用电子 API 每 3 秒执行一次屏幕截图捕获,并将其写入给定的目标路径。我已经设置了一个单独的 BrowserWindow,捕获代码在其中运行(参见下面的代码结构)一个 setInterval()“循环”,但是每当捕获发生时,应用程序都会冻结片刻。我认为是在文件ScreenCapturer.jshtml.js 中调用source.thumbnail.toPng() 或writeScreenshot() 方法。
我设置了这个结构,因为我认为这是要走的路,但显然不是这样。 WebWorkers 也帮不了我,因为我需要 fs、path 和 desktopCapturer 等节点模块(来自 electron)。
如何在每次间隔代码(如文件ScreenCapturer.jshtml.js 中所见)运行时不阻塞主线程的情况下执行此类任务(因为我认为渲染器进程是单独的进程?)
我的代码作为参考
main.js(主进程)
// all the imports and other
// will only show the import that matters
import ScreenCapturer from './lib/capture/ScreenCapturer';
app.on('ready', () => {
// Where I spawn my main UI
mainWindow = new BrowserWindow({...});
mainWindow.loadURL(...);
// Other startup stuff
// Hee comes the part where I call function to start capturing
initCapture();
});
function initCapture() {
const sc = new ScreenCapturer();
sc.startTakingScreenshots();
}
ScreenCapturer.js(主进程使用的模块)
'use strict';
/* ******************************************************************** */
/* IMPORTS */
import { app, BrowserWindow, ipcMain } from 'electron';
import url from 'url';
import path from 'path';
/* VARIABLES */
let rendererWindow;
/*/********************************************************************///
/*///*/
/* ******************************************************************** */
/* SCREENCAPTURER */
export default class ScreenCapturer {
constructor() {
rendererWindow = new BrowserWindow({
show: true, width: 400, height: 600,
'node-integration': true,
webPreferences: {
webSecurity: false
}
});
rendererWindow.on('close', () => {
rendererWindow = null;
});
}
startTakingScreenshots(interval) {
rendererWindow.webContents.on('did-finish-load', () => {
rendererWindow.openDevTools();
rendererWindow.webContents.send('capture-screenshot', path.join('e:', 'temp'));
});
rendererWindow.loadURL(
url.format({
pathname: path.join(__dirname, 'ScreenCapturer.jshtml.html'),
protocol: 'file:',
slashes: true
})
);
}
}
/*/********************************************************************///
/*///*/
ScreenCapturer.jshtml.js(渲染器浏览器窗口中加载的 thml 文件)
<html>
<body>
<script>require('./ScreenCapturer.jshtml.js')</script>
</body>
</html>
ScreenCapturer.jshtml.js(渲染器进程中从html文件加载的js文件)
import { ipcRenderer, desktopCapturer, screen } from 'electron';
import path from 'path';
import fs from 'fs';
import moment from 'moment';
let mainSource;
function getMainSource(mainSource, desktopCapturer, screen, done) {
if(mainSource === undefined) {
const options = {
types: ['screen'],
thumbnailSize: screen.getPrimaryDisplay().workAreaSize
};
desktopCapturer.getSources(options, (err, sources) => {
if (err) return console.log('Cannot capture screen:', err);
const isMainSource = source => source.name === 'Entire screen' || source.name === 'Screen 1';
done(sources.filter(isMainSource)[0]);
});
} else {
done(mainSource);
}
}
function writeScreenshot(png, filePath) {
fs.writeFile(filePath, png, err => {
if (err) { console.log('Cannot write file:', err); }
return;
});
}
ipcRenderer.on('capture-screenshot', (evt, targetPath) => {
setInterval(() => {
getMainSource(mainSource, desktopCapturer, screen, source => {
const png = source.thumbnail.toPng();
const filePath = path.join(targetPath, `${moment().format('yyyyMMdd_HHmmss')}.png`);
writeScreenshot(png, filePath);
});
}, 3000);
});
【问题讨论】:
-
我也有这个问题
-
@Booligoosh 确实很痛苦,但我放弃了使用它。我建议使用
desktop-screenshot包-> npmjs.com/package/desktop-screenshot。这对我来说是跨平台(linux、mac、win)。 -
@Booligoosh 请看下面我的回答,它可能对你有用stackoverflow.com/a/43113931/1155847
标签: node.js multithreading asynchronous electron