【发布时间】:2021-01-16 14:29:46
【问题描述】:
我正在使用 Electron 创建一个创建全屏透明覆盖窗口的 Windows 应用程序。此叠加层的目的是:
- 截取整个屏幕的屏幕截图(不是透明的覆盖层本身,而是屏幕“下方”),
- 通过将图像作为字节流发送到我的 python 服务器来处理此图像,并且
- 在叠加层上画一些东西
我卡在第一步,即截图捕获过程。
我尝试了选项1,也就是使用capturePage():
this.electronService.remote.getCurrentWindow().webContents.capturePage()
.then((img: Electron.NativeImage) => { ... }
但这仅捕获我的覆盖窗口(而不是桌面屏幕)。这将是一个空白图像,对我来说毫无用处。
选项2是使用desktopCapturer:
this.electronService.remote.desktopCapturer.getSources({types: ['screen']}).then(sources => {
for (const source of sources) {
if (source.name === 'Screen 1') {
try {
const mediaDevices = navigator.mediaDevices as any;
mediaDevices.getUserMedia({
audio: false,
video: { // this specification is only available for Chrome -> Electron runs on Chromium browser
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: source.id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
}).then((stream: MediaStream) => { // stream.getVideoTracks()[0] contains the video track I need
this.handleStream(stream);
});
} catch (e) {
}
}
}
});
下一步对我来说变得模糊。我如何处理获得的MediaStream 以从屏幕截图中获取字节流?我看到很多如何在网页上显示此流的示例,但我希望将其发送到我的后端。 This StackOverflow post 提到了如何做到这一点,但我没有让它正常工作。这就是我实现handleStream()的方式:
import * as MediaStreamRecorder from 'msr';
private handleStream(stream: MediaStream): void {
recorder.stop()
const recorder = new MediaStreamRecorder(stream);
recorder.ondataavailable = (blob: Blob) => { // I immediately get a blob, while the linked SO page got an event and had to get a blob through event.data
this.http.post<Result>('http://localhost:5050', blob);
};
// make data available event fire every one second
recorder.start(1000);
}
blob 未被 Python 服务器接受。检查Blob的内容后,我怀疑这是一个视频。我用以下代码验证了这一点:
let url = URL.createObjectURL(blob);
window.open(url, '_blank')
在新窗口中打开 blob。它显示可能半秒的视频,但我想要一个静态图像。那么如何从中获取特定的快照呢?我也不确定是否只需在 POST 正文中发送 Javascript blob 格式就可以让 Python 正确解释它。在 Java 中,它只需发送图像的 byte[] 即可工作,因此我验证了 Python 服务器实现按预期工作。
除了使用desktopCapturer 之外的任何建议也可以。这个实现也捕获了我的鼠标,我宁愿没有。我必须承认,我没想到这个功能会这么难实现。
【问题讨论】:
标签: javascript angular electron