Electron 可以很方便的創建一個窗口,然后加載指定的網頁來呈現。但如果網頁中包含了WebRTC 屏幕分享相關的邏輯,則會發現Electron會和Chrome瀏覽器表現不同。
問題在於Electron未能實現Chrome所支持的Web RTC的getDisplayMedia接口,導致本應該跳出視頻流選擇的界面未能顯示出來。
解決方法:
Electron提供了desktopCapturer.getSources用來實現類似getDisplayMedia的功能,因為我們可以在BrowserWindow的preload中重寫navigator.mediaDevices.getDisplayMedia方法
類似於:
window.navigator.mediaDevices.getDisplayMedia = () => { return new Promise(async (resolve, reject) => { try { const sources = await desktopCapturer.getSources({ types: ['screen'] }) const stream = await window.navigator.mediaDevices.getUserMedia({ audio: false, video: { mandatory: { chromeMediaSource: 'desktop', chromeMediaSourceId: sources[0].id } } }) resolve(stream) }catch(err){ reject(err) } }) }
我這里只默認獲取了第一個source,也就是主屏幕。
關鍵的地方:
Electron新版本,默認在preload中的js和網頁中的js是隔離的,也就是contextisolation的設置為true,這會導致,在preload中設置的上述方法在網頁中不起作用,因此需要將contextisolation設置為false
帶來的額外的問題就是contextBridge就沒法使用了,后者通過contextBridge.exposeInMainWorld()的方式,可以向網頁注入屬性或者方法
我自己的設置(測試可行):
mainwindow = new BrowserWindow({ show: false, title: appName, icon: 'app/assets/examclient_128.ico', webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: false, devTools: true, webSecurity:false, experimentalFeatures:true, contextIsolation:false } });