Branchreel: branching video on a page you control

GitHub

a branchreel demo story

The Signal

Three branch points, four endings. Watch the story graph light up as you choose.

0:00 / 0:00

What Branchreel does

Branchreel is a JavaScript library for branching interactive video. You describe a story as a JSON graph, where every node is a video segment and every choice is an edge to another node, and Branchreel drives an ordinary HTML <video> element through it. When playback reaches a branch point the player raises a choice event; when the viewer picks one, it cuts straight to that segment. The demo above is the whole library doing its job: three branch points, four endings, eight clips, and the panel beside it drawing the shape of the story as you go.

It exists because interactive video normally means picking between two trades you may not want to make. Hosted platforms take your story into their editor, their file format, and their player, on their pricing. Rolling your own means writing source swapping, preloading, choice overlays, and a branch-aware scrubber from scratch, once per project. Branchreel is the small third option: a dependency you add to a page you already own.

What you get

Cuts that do not stall
Every choice target starts preloading the moment its node begins playing, and choose() sets the video's src synchronously. Nothing is awaited between the click and the new frame.
Plain JSON, no authoring tool
A graph is an array of nodes, each with a src and a list of choices. Write one by hand in a text editor, or generate it from whatever you already use.
Graphs that fail loudly
A duplicate node id, or a choice pointing at a node that is not in the graph, throws when you build the machine rather than three clicks into a playthrough.
A story graph you can draw
computeGraphLayout returns node positions and edges. The panel above is SVG built from it; the library has no opinion about what you render.
Nothing at runtime
Zero runtime dependencies, ESM and CJS builds, and TypeScript types in the package.

Install

npm install branchreel
import { PlayerController } from "branchreel";

const player = new PlayerController(document.querySelector("video"), {
  start: "intro",
  nodes: [
    { id: "intro", src: "intro.mp4", end: 8, choices: [
      { id: "brave", label: "Open the door", target: "hallway" },
    ]},
    { id: "hallway", src: "hallway.mp4" },
  ],
});

player.addEventListener("choice", (e) => {
  // render e.detail.choices as buttons, each calling player.choose(id)
});

Questions

Does Branchreel need a backend?

No. The current node and the path taken live in memory in the browser, so there is nothing to deploy beyond the page and the video files. If you want to persist a viewer's path or report on it, that stays your call to make in your own app.

What video format does it use?

Whatever a <video> element already plays. Branchreel never touches the media itself: it sets src and currentTime and listens for timeupdate. Segments can be separate files, or spans of one longer file addressed with start and end timecodes.

Can I use it with React, Vue, or Svelte?

Yes. The library is framework-agnostic and talks to a <video>-shaped host through ordinary events. Render the choice buttons however your framework prefers and call choose(id) when one is clicked.

How does it keep a branch from buffering?

Every choice from a node points at a known target, so the moment a node starts playing, each of its targets begins loading in a hidden host. By the time the viewer decides, the next segment is usually already in the browser's cache. If a preload fails, choosing that branch still works through a normal load.

Read the source, or copy the demo and swap in your own footage.

View on GitHub