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.
choose() sets the video's src synchronously. Nothing is
awaited between the click and the new frame.
src and a list of choices.
Write one by hand in a text editor, or generate it from whatever you already use.
computeGraphLayout returns node positions and edges. The panel above is
SVG built from it; the library has no opinion about what you render.
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)
});
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.
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.
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.
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