All posts

Audio- and Video-content in ElectronJS

📅 Created 3 months ago → updated after 6 days

🏷️ #electron #js #ts

The ElectronJS provides the power of the whole web portal in a single application. The Electron app embraces the Chromium browser for the UI and the NodeJS for the backend.

The app usually contains multiple resources: HTML, JS, styles, graphics. All these resources are packed into an ASAR archive. The Electron Main process (think “NodeJS backend”) serves them to the Renderer process(es) (think “frontend”).

🐞Bug

There is an issue of serving the audio and video content By default, it won’t be available in production builds whilst working fine on development environment.

The <audio>/<video> source URL calls return 200 😲 with no content!

How to fix it? — Long story short,

import * as E from "electron"

E.protocol.registerSchemesAsPrivileged([{
  scheme: "app",
  privileges: { secure: true, standard: true, stream: true }
  //                                          ^^^^^^^^^^^^
  //                                          this does the trick
}])

// Setup the app
// considering the resources URI to start with "app://"
const win = new BrowserWindow({ ... })
win.loadURL("app://./index.html")
//           ^^^^^^

How it works?

The Main process creates a BrowserWindow. The BW behaves as a regular web page therefore it uses HTTP communication respecting the URI scheme syntax.

We ask the Main process to register a custom scheme app:// with streaming privileges. The custom scheme does not allow streaming by default and this delivers no content to <audio> and <video> elements. More on this in Electron process docs.

Similarly, works it with BrowserView-s (think BVs are the “tabs” of a BrowserWindow):

const win = new BrowserWindow({ ... })
const view = new BrowserView({ ... })
view.webContents.loadURL("app://./index.html")

Note on resource URI

Designing the web page, you don’t usually need full URI including the schema (with a very few exceptions). If a part on the left of the resource URI is omitted, it’s inherited from the caller page URI:

Page URI:     app://admin/index.html
Images:       <img src="forbidden.png" />    →   "app://admin/forbidden.png"
              <img src="/user.png" />        →   "app:///forbidden.png"

In other words, if the resource path does not start with schema://, you are safe 🙂 otherwise pay attention to the schema.

Soft vs. Hard or "Quod licet Jovi" Hello world 2.0