由于electron环境下无法直接调用webrtc来获取屏幕流,因此需要调用者自己稍作处理,具体做法如下。
获取设备窗口
调用相关的API获取设备的窗口,主线程发送一个IPC消息handle。
// electron主线程
import { desktopCapturer, webContents } from "electron";
// 修复electron18.0.0-beta.5 之后版本的BUG: 无法获取当前程序页面视频流
const selfWindws = async () =>
await Promise.all(
webContents
.getAllWebContents()
.filter(item => {
const win = BrowserWindow.fromWebContents(item);
return win && win.isVisible();
})
.map(async item => {
const win = BrowserWindow.fromWebContents(item);
const thumbnail = await win?.capturePage();
// 当程序窗口打开DevTool的时候 也会计入
return {
name:
win?.getTitle() + (item.devToolsWebContents === null ? "" : "-dev"), // 给dev窗口加上后缀
id: win?.getMediaSourceId(),
thumbnail,
display_id: "",
appIcon: null
};
})
);
// 获取设备窗口信息
ipcMain.handle("IPC消息名称", async (_event, _args) => {
return [
...(await desktopCapturer.getSources({ types: ["window", "screen"] })),
...(await selfWindws())
];
});
渲染线程
渲染线程(前端)发送消息封装处理(相应写法自己调整)。
// xxx.ts
export const getDesktopCapturerSource = async () => {
return await window.electron.ipcRenderer.invoke<Electron.DesktopCapturerSource[]>("IPC消息名称", []);
}
获取媒体流
获取指定窗口的媒体流。
// yyy.ts
export function getInitStream(source: any): Promise<MediaStream | null> {
return new Promise((resolve, _reject) => {
// 获取指定窗口的媒体流
// 此处遵循的是webRTC的接口类型 暂时TS类型没有支持 只能断言成any
(navigator.mediaDevices as any).getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: source.id
},
}
}).then((stream: MediaStream) => {
resolve(stream);
}).catch((error: any) => {
console.log(error);
resolve(null);
})
});
}
获取设备窗口信息
前端调用设备窗口信息。
import { getDesktopCapturerSource } from "xxx.ts";
import { getInitStream } from "yyy.ts";
import ScreenShot from "js-web-screen-shot";
export const doScreenShot = async ()=>{
// 下面这两块自己考虑
const sources = await getDesktopCapturerSource(); // 这里返回的是设备上的所有窗口信息
// 这里可以对`sources`数组下面id进行判断 找到当前的electron窗口 这里为了简单直接拿了第一个
const stream = await getInitStream(sources[0]);
new ScreenShot({
enableWebRtc: true, // 启用webrtc
screenFlow: stream!, // 传入屏幕流数据
level: 999,
});
}
示例代码
如果你看完本页的使用方法,依然不是很理解的话,这里准备了一份在electron环境下使用本插件的demo,请移步electron-js-web-screen-shot-demo。