本文主要介绍 Electron 中使用 TRTC Web SDK 时,如何进行屏幕分享。
简介
Electron 可以方便的创建窗口,加载网页进行使用。因为 Electron 未实现浏览器支持的 WebRTC 标准的 getDisplayMedia 接口,所以如果网页中包含了 WebRTC 屏幕分享相关的逻辑,将无法在 Electron 中像普通浏览器一样正常使用 TRTC Web SDK 进行屏幕分享。
问题在于 Electron 未实现浏览器支持的 WebRTC 的 getDisplayMedia
接口,导致无法直接在 Electron 中使用 TRTC Web SDK 进行屏幕分享。
在 Electron 中使用 TRTC Web SDK 如何进行屏幕分享呢?
方案
优先建议使用 TRTC Electron SDK,如果只想使用 TRTC Web SDK,方案如下。
实现屏幕分享,需要使用到 Electron 的 API:desktopCapturer.getSources({ types: ['window', 'screen'] })
- 主进程
main.js
监听页面加载完成后,通过desktopCapturer.getSources
获取屏幕分享源列表,并将屏幕分享源列表发送给渲染进程 - 渲染进程监听主进程事件,从而获取屏幕分享源列表
- 创建屏幕分享流并通过 TRTC Web SDK 进行推流
- 通过
navigator.mediaDevices.getUserMedia()
从系统 API 获取屏幕分享的MediaStream
- 通过
TRTC.createStream()
的自定义采集功能,从屏幕流拿到的 videoTrack 创建要发布的屏幕分享流 - 推屏幕分享流
- 通过
// 【1】main.js 主进程获取屏幕分享源列表
const { app, BrowserWindow, desktopCapturer, systemPreferences } = require('electron');
function createWindow () {
const win = new BrowserWindow({
// ……
});
win.loadFile('./src/index.html');
win.webContents.on('did-finish-load', async () => {
if (win) {
desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
win.webContents.send('SEND_SCREEN_SHARE_SOURCES', sources);
});
}
});
}
// 【2】渲染进程监听主进程事件拿到屏幕分享源列表
const { ipcRenderer } = require('electron');
let shareSourceList = [];
ipcRenderer.on('SEND_SCREEN_SHARE_SOURCES', async (event, sources) => {
const selectContainer = window.document.getElementById('screen-share-select');
shareSourceList = sources;
sources.forEach(obj => {
const optionElement = document.createElement('option');
optionElement.innerText = `${obj.name}`;
selectContainer.appendChild(optionElement);
});
})
// 【3】渲染进程推屏幕分享
async function startScreenShare() {
const selectContainer = document.getElementById('screen-share-select');
const selectValue = selectContainer.options[selectContainer.selectedIndex].value;
const [ source ] = shareSourceList.filter(obj => obj.name === `${selectValue}`);
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: source.id, // 屏幕分享源 id
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
});
const shareClient = TRTC.create({
// ……
});
const shareStream = TRTC.createStream({
videoSource: stream.getVideoTracks()[0]
});
await shareStream.initialize();
await shareClient.join({ roomId: parseInt(roomId) });
shareStream && await shareClient.publish(shareStream);
} catch (error) {
console.error('start screen share error = ', error)
}
}
常见问题
- macOS Monterey(12.2.1), 需在主进程中请求设备权限
async function checkAndApplyDeviceAccessPrivilege() { const cameraPrivilege = systemPreferences.getMediaAccessStatus('camera'); console.log( `checkAndApplyDeviceAccessPrivilege before apply cameraPrivilege: ${cameraPrivilege}` ); if (cameraPrivilege !== 'granted') { await systemPreferences.askForMediaAccess('camera'); } const micPrivilege = systemPreferences.getMediaAccessStatus('microphone'); console.log( `checkAndApplyDeviceAccessPrivilege before apply micPrivilege: ${micPrivilege}` ); if (micPrivilege !== 'granted') { await systemPreferences.askForMediaAccess('microphone'); } const screenPrivilege = systemPreferences.getMediaAccessStatus('screen'); console.log( `checkAndApplyDeviceAccessPrivilege before apply screenPrivilege: ${screenPrivilege}` ); }