Spout
Zero-copy Electron → Syphon output for macOS
Publish an Electron app's rendered GPU frames to Syphon on macOS — zero-copy, from the main process, behind a single call.
Spout publishes an Electron app’s rendered GPU frames to Syphon on macOS — zero-copy, straight from the main process. Any Syphon client (Resolume, MadMapper, VDMX, TouchDesigner, Syphon Recorder) can then receive your app’s output as live video.
import { SyphonOutput } from 'electron-syphon'
const win = new BrowserWindow({
show: false,
webPreferences: { offscreen: { useSharedTexture: true }, backgroundThrottling: false },
})
win.webContents.setFrameRate(60)
const syphon = new SyphonOutput('My App')
syphon.attach(win.webContents) // publishes every frame to Syphon — that's it
win.loadURL(myVisualsUrl)
The whole interface is one call: attach(webContents). You point it at an offscreen window’s webContents and it publishes every frame that window renders. It never looks at what you draw — canvas2D, WebGL, WebGPU, plain DOM, a <video>, or your whole React app all work identically. Multiple outputs just means calling attach on multiple webContents. The only requirement is that the window is offscreen with useSharedTexture — that’s what makes its paint event hand you a GPU frame.
How it works
- Zero-copy. Electron’s offscreen
paintevent hands the main process a GPU IOSurface handle; Spout wraps it as a Metal texture and publishes it viaSyphonMetalServer. No pixel ever crosses IPC and nothing is read back to the CPU. - Prebuilt. Ships an N-API prebuilt binary (ABI-stable across Electron versions) and a vendored
Syphon.framework, sonpm installneeds no Xcode. - Fast. ~0.13 ms/frame to publish at 1080p (≈40× real-time at 60 fps) — 3–5× faster than the usual CPU-readback approach.
The common alternative — shipping pixel buffers renderer→main over IPC every frame — forces a GPU→CPU readback on the hot path. Spout instead runs the Syphon server in the main process through SyphonMetalServer and keeps the frame on the GPU the entire way.
Requirements
macOS 11+. Electron is a peer dependency; Electron 33+ for the zero-copy path (it falls back to a CPU bitmap on older or unsupported setups).