docs/spf fundamental concepts (#1396)

Feedback from @decepulis treated as a fast follow/incremental improvement effort for expediency.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christian Pillsbury
2026-04-28 11:16:56 -07:00
committed by GitHub
parent c388dd35a9
commit 69852ddeb0
82 changed files with 2289 additions and 465 deletions
+6 -6
View File
@@ -40,7 +40,7 @@ Internal structure of SPF.
└─────────────────────────────────────────────────────────┘
```
The `core/` layer is runtime-agnostic no DOM APIs, no fetch. The `dom/` layer wires browser platform APIs (MSE, fetch, HTMLMediaElement) into the core abstractions.
The `core/` layer holds SPF's framework primitives (composition, signals, tasks, actors, reactors) — runtime-agnostic, with no DOM or network dependencies. The `media/` layer holds runtime-agnostic HAS-domain logic (ABR, buffer math, HLS parsing, CMAF-HAM types). The `dom/` layer wires browser platform APIs (MSE, fetch, HTMLMediaElement) into both.
---
@@ -64,7 +64,7 @@ interface State<S> {
- `flush()` drains the pending patch immediately. Call when downstream subscribers need to react before the next tick (e.g., ABR sampling).
- Selector subscriptions fire only when the selected slice changes, using a custom equality function.
### Actor (`core/actor.ts` + `core/task.ts`)
### Actor (`core/actors/actor.ts` + `core/tasks/task.ts`)
An actor owns a `snapshot` (status + context) and serializes its own work via a runner.
@@ -81,11 +81,11 @@ interface Actor<Context> {
**ConcurrentRunner** — deduplicates by ID. Used where parallel work is safe but duplicate tasks are wasteful.
### HLS Parsing (`core/hls/`)
### HLS Parsing (`media/hls/`)
Parses multivariant and media playlists into typed structures (`Presentation`, `Track`, `Segment`). URL resolution is handled separately in `resolve-url.ts`, making the parsers pure functions of text input.
### ABR (`core/abr/`)
### ABR (`media/abr/`)
Two components:
@@ -95,7 +95,7 @@ Two components:
> **Zero-factor correction:** Raw EWMA starts near zero. The displayed/used estimate must apply `estimate / (1 - α^totalWeight)` to correct for the initialization bias.
### Buffer Math (`core/buffer/`)
### Buffer Math (`media/buffer/`)
**Forward buffer** (`forward-buffer.ts`) — computes the target load window: `[currentTime, currentTime + forwardBufferDuration]`. Also computes the flush point (segments behind `currentTime - backBufferDuration`).
@@ -105,7 +105,7 @@ Two components:
## DOM Layer
### PlaybackEngine (`dom/playback-engine/engine.ts`)
### PlaybackEngine (`dom/playback-engine/hls-engine.ts`, built on `core/composition/create-composition.ts`)
The orchestration hub. Initializes all features in a fixed order, wiring shared state, owners, and a single event stream.
+4 -4
View File
@@ -43,7 +43,7 @@ A Task is the unit of work *inside* an Actor or Reactor. Actors plan and execute
### Current approach
`core/task.ts` — thin wrapper around a function with an `AbortController`. The shape is approximately right; the question is how much structure to add.
`core/tasks/task.ts` — thin wrapper around a function with an `AbortController`. The shape is approximately right; the question is how much structure to add.
> **See also:** [actor-reactor-factories.md](actor-reactor-factories.md) — decided design for `createMachineActor` / `createMachineReactor`, including how runners are declared and lifecycle-managed.
@@ -75,7 +75,7 @@ Runners are internal to Actors and Reactors. An Actor may own one or more Runner
### Current approach
`SerialRunner` and `ConcurrentRunner` in `core/task.ts`. The core abstraction is right.
`SerialRunner` and `ConcurrentRunner` in `core/tasks/task.ts`. The core abstraction is right.
### Open questions
@@ -107,7 +107,7 @@ An Actor does not know about state outside itself. It receives messages and prod
### Current approach
`createMachineActor` in `core/create-machine-actor.ts` — a declarative factory replacing bespoke closures.
`createMachineActor` in `core/actors/create-machine-actor.ts` — a declarative factory replacing bespoke closures.
Actors define state, context, message handlers per state, and an optional runner factory in
a definition object. The factory manages the snapshot signal, runner lifecycle, and
`'destroyed'` terminal state. See [actor-reactor-factories.md](actor-reactor-factories.md).
@@ -154,7 +154,7 @@ A Reactor is typically the bridge between reactive state and one or more Actors.
### Current approach
`createMachineReactor` in `core/create-machine-reactor.ts` — a declarative factory. The first Reactor
`createMachineReactor` in `core/reactors/create-machine-reactor.ts` — a declarative factory. The first Reactor
implementations are in `dom/features/` as part of the text track spike (videojs/v10#1158):
`syncTextTracks` and `loadTextTrackCues`. See [text-track-architecture.md](text-track-architecture.md)
for the reference implementation.