HUAN 讙 · 開發者

ADR-0006:播放器使用 Electron

狀態

已採用

背景

播放器必須在 Raspberry Pi OS(arm64)、Ubuntu(x64 與 arm64)、Windows(x64 與 arm64)與 macOS(x64 與 arm64)上執行,而且要能播放影片、圖片、文字、跑馬燈、iframe 與上傳的 HTML。

決策

使用 Electron,React 負責算繪行程。

理由

要播的內容本來就是網頁內容。 影片、圖片、文字排版、CSS 動畫、iframe、HTML——這些全都是瀏覽器原生就會做的事。用原生 UI 框架重做一次等於重寫一個排版引擎。

版面引擎可以和後台共用。 @huan/layout-engine 同一份程式碼跑在 Admin 的預覽與 Device 的播放器上,這是「後台看到什麼、現場就播什麼」的保證。換一個非網頁的算繪技術就得維護兩套幾何實作,而它們一定會漂移。

上傳的 HTML 需要一個真的瀏覽器。 而且需要一個可以嚴格 sandbox 的瀏覽器。Electron 的 sandbox: true 加上巢狀 iframe 提供了這個能力。

跨平台打包是解決過的問題。 electron-builder 直接支援上面列的六個平台架構組合。

後果

  • 記憶體用量比原生播放器高。Raspberry Pi 4 的最低建議配置因此是 2GB,實際建議 4GB。
  • 應用程式體積較大(每個平台大約一百多 MB)。看板裝置一次安裝之後很少更新,這是可以接受的。
  • 必須嚴格遵守 Electron 的安全模型。nodeIntegration: falsecontextIsolation: truesandbox: true 不會為了任何功能而放寬,preload 只暴露最小介面。
  • 要盡量避免原生 Node 模組。每一個原生相依都會讓六個平台架構的打包變得更困難,因此優先選擇純 JS 或 Web API 的方案。

替代方案

Chromium kiosk 模式加一個小服務:更輕量,但排程、下載、狀態管理都得另外寫一個常駐程序,而且和瀏覽器之間的溝通要自己設計。等於用兩個行程做 Electron 一個行程做的事。

原生應用程式(Qt、Flutter):記憶體用量低很多,但要自己實作 HTML 內容的算繪與 sandbox,而且無法與後台共用版面引擎。

libmpv 加自製排版:影片播放效能最好,但文字、跑馬燈、HTML 與 iframe 全都要重做。