docs(spf): seed feature registry, clusters reference, and document-feature skill#1581
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
✅ Deploy Preview for vjs10-site ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Contributor
📦 Bundle Size Report🎨 @videojs/html — no changesPresets (7)
Media (8)
Players (5)
Skins (30)
UI Components (35)
Sizes are marginal over the root entry point. ⚛️ @videojs/react — no changesPresets (7)
Media (7)
Skins (27)
UI Components (29)
Sizes are marginal over the root entry point. 🧩 @videojs/core — no changesEntries (9)
🏷️ @videojs/element — no changesEntries (2)
📦 @videojs/store — no changesEntries (3)
🔧 @videojs/utils — no changesEntries (10)
📦 @videojs/spf — no changesEntries (3)
ℹ️ How to interpretAll sizes are standalone totals (minified + brotli).
Run |
…guage-audio Three feature-registry docs at varying definition depths — subtitles and video-abr at sketched (implementation grounded), multi-language-audio at coarse (candidate next-priority feature). Establishes the template structure by extracting from real work rather than designing upfront. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Heuristics doc for grouping SPF features by area of state and behavior. 9 clusters (track registry, selection policy, presentation modeling, MSE / buffer management, time normalization, manifest reload, capability probing, selection resilience, DRM) plus 5 cross-cluster patterns (gating, multi-writer state slots, constraint+filter, per-type specialization, sampling-baked-into-loading). Consumed by the spf-document-feature skill at steps 1, 3, 4, 5, and 8. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1 skill for producing or updating SPF feature-registry docs at internal/design/spf/features/. Nine steps with explicit failure-mode catalog, references features/clusters.md throughout. Structure modeled on the refactor-behavior skill. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add sketched-depth feature doc for the MSE / Managed Media Source pipeline: MediaSource lifecycle, per-type SourceBuffer + actor setup (with the Firefox mozHasAudio invariant), MMS-on-Safari attach branch, initial duration write, and end-of-stream coordination. Scope ends at the lifecycle boundary; segment-loading orchestration and buffer-flush orchestration remain sibling features. Cascade refs: - multi-language-audio.md: link the Audio SourceBuffer flush on switch bullet to mse-mms-pipeline (where the remove/flushBuffer primitives live) and add a Related features entry for the lifecycle dependency. - video-abr.md: See also link noting that setupVideoBufferActors is where createTrackedFetch is wired (sampling co-located with MSE setup, ABR is the consumer). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add sketched-depth feature doc for preload-modes: the engine's loading-semantics implementation pairing syncPreload (bidirectional state.preload <-> mediaElement.preload sync, sticky extended values) with trackLoadTriggers (DOM play/seeking flips state.loadActivated). Together these mirror native HTMLMediaElement preload behavior; the state.loadActivated slot is multi-writer with the adapter's programmatic play() path. Cascade refs: - mse-mms-pipeline.md: preload-modes gates indirectly via resolvePresentation. - subtitles.md: loadTextTrackSegments consumes the same (preload, loadActivated) gate state. - video-abr.md: See also link noting indirect gating. Engine walkthrough fix: hls-engine.md Stage 1 referenced the precursor trackPlaybackInitiated behavior writing state.playbackInitiated; the current code is trackLoadTriggers writing state.loadActivated. Updated the walkthrough to match and cross-link the new feature doc. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add sketched-depth feature doc for buffer-management: the engine's segment-level buffer policy (forward-buffer planning, back-buffer eviction, in-flight continue/preempt, quality-aware filter, seek handling, streaming append). Covers loadVideoSegments / loadAudioSegments / loadTextTrackSegments dispatchers, the v/a SegmentLoaderActor + TextTrackSegmentLoaderActor, and the forward-buffer / back-buffer policy primitives in media/buffer/. Absorbs the [per-track-segment-loading] bracketed candidate from clusters.md — that was an architectural slice, not a feature; the engine behaviors it described all live here. Captures candidate phases as What's not implemented: smarter forward-buffer sizing (playback-rate-aware, canplaythrough-equivalent, network/seek-density-aware); smarter back-buffer eviction (quota-learning that records observed QuotaExceededError thresholds for proactive use, time/size-based variants); loop-aware fetching for loop=true; changeType() codec-change transitions; buffer health observability. Cascade refs: replace 5 per-track-segment-loading references across mse-mms-pipeline.md, multi-language-audio.md, preload-modes.md, subtitles.md, video-abr.md with buffer-management. In preload-modes the per-track-segment-loading and (already-bracketed) buffer-management entries collapse to a single updated entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add sketched-depth feature doc for source-replacement: the engine's source-change capability via in-place state.presentation overwrite. resolvePresentation routes the FSM back through 'resolving' on URL change; downstream behaviors (setupMediaSource, setupVideoBufferActors, setupAudioBufferActors, endOfStream, resolveXTrack, etc.) tear down via reactor state-exit. Same engine instance survives the cascade — no destroy required. The cleanup contract is load-bearing: new behaviors that gate on isResolvedPresentation MUST honor state-exit cleanup or in-place replacement breaks silently. The canonical adapter (SimpleHlsMediaMixin) chose destroy-and-recreate instead, which bypasses the cascade entirely — so the in-place path is the engine's load-bearing capability for internal reasoning. Add a new "cleanly replaces source in place via state.presentation overwrite" test in engine.test.ts that validates the cascade end-to-end (MediaSource and bufferActor identities differ between sources A and B, proving full teardown). Pins the cleanup contract against regression. Add a new "Engine lifecycle" cluster in clusters.md grouping preload-modes + source-replacement + the [engine-adapter-integration] candidate. The cluster's Key check captures the cleanup-contract requirement for new presentation-gated behaviors. Cascade refs: cross-link source-replacement from preload-modes.md, mse-mms-pipeline.md, and buffer-management.md so future contributors working in those areas surface the contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add sketched-depth feature doc for audio-playback: today's single-rendition audio playback in the HLS engine. Covers rendition recognition, default picker (pickFirstTrackId today), media playlist resolution, SourceBuffer setup (architecturally owned by mse-mms-pipeline), and segment loading (architecturally owned by buffer-management). Sibling of subtitles, video-abr, and the future multi-language-audio. Notable finding flagged in What's not implemented + Open questions: the language-aware pickAudioTrack picker exists in media/primitives/ but isn't wired as the default in selectAudioTrack. preferredAudioLanguage is exposed on the engine config but inert with the default picker — consumers must override SelectAudioTrackConfig.picker to make it take effect. Wiring pickAudioTrack as the default would be a one-line change. Cascade refs: - multi-language-audio.md: Status sentence updated to point at audio-playback as the single-rendition baseline; Related features entry added. - clusters.md: audio-playback added to Track & variant registry's docs list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add sketched-depth feature doc for engine-adapter-integration: the engine's external-driving contract pairing the framework-level shareSignals behavior (writable + readonly signal refs via onSignalsReady) with the canonical SimpleHlsMediaMixin adapter (WHATWG HTMLMediaElement-shaped API mapping to engine writes). Documents the adapter-to-engine state/context mapping (attach/detach, src destroy-recreate, preload reflection, play with loadstart retry). Audience is adapter authors and contributors who drive the engine from outside, not end users. Downstream consumer: `SimpleHlsMedia extends SimpleHlsMediaMixin(HTMLVideoElementHost)` in packages/core. Repeats source-replacement's open question about why the canonical adapter chose destroy-recreate over the in-place source-replacement path the engine supports. This is the doc where adapter authors and new-feature contributors would look for the why. Cascade: clusters.md Engine lifecycle cluster docs list updated to drop the [engine-adapter-integration] brackets. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add internal/design/spf/presentation-modeling.md as an architectural deep-dive (peer to text-track-architecture.md) covering the format-neutral CMAF-HAM data shape, the parser interface, per-track resolution, and duration resolution. Audience: engine + parser contributors. Treats this as architecture rather than a feature doc per the "features = engine behaviors observable from outside" framing — the Presentation data shape, resolved/unresolved lifecycle, and parser contract are foundational infrastructure consumed by every feature, not an engine behavior in their own right. Surfaces a load-bearing finding for future format work: the parseMediaPlaylist parser is imported directly in resolve-track.ts (not exposed via config), while parsePresentation and resolveDuration ARE config-pluggable. When DASH/MoQ/short-form work begins, the coupling needs to either become pluggable via a new config hook or be replaced by format-specific resolve-track variants. Cascade: clusters.md "Read alongside" section gains a reference to this doc and to text-track-architecture.md. Six feature docs (source-replacement, audio-playback, subtitles, video-abr, mse-mms-pipeline, buffer-management) get See also cross-refs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add internal/design/spf/features/live-stream-support.md as a technical-depth feature doc for the manifest-reload-loop cluster (A) foundation. Covers periodic media-playlist refetch, sliding-window segment tracking, target-duration pacing, and Infinity duration semantics. Unblocks sibling features ll-hls-support, dvr-event-stream-support, live-stream-termination-detection. First instantiation of the "unimplemented feature doc" pattern: the doc is structured per the technical-depth section presence (scope + constraints + likely cross-cutting impact + open questions, no implementation surface or verification). Cites the SPF Epics Working Doc and Permutations Matrix as source material; explicitly invokes the new feature classification axes (Media-src vs Player vs Borderline). Add Feature classification axes section to clusters.md, pulling framing from the SPF Epics Working Doc: - Media-src vs Player vs Borderline (the primary cut for unimplemented work) - Naive vs Full implementation depth - "Can play" vs actual support - Tier 1 (spec-compliant) vs Tier 2 (custom behavior) - Composition vs Policy vs middle pattern (implementation mechanism) Drops [live-stream-support] brackets in the cluster A Docs list now that the doc exists. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Decomposition decision: termination detection has no use without the reload loop, modest implementation footprint, and doesn't act as a primitive other features consume. None of the Step 5 decomposition- check criteria (substantial independent footprint, independent priority/timeline, primitive other features consume) fired. Folding in as phases rather than a sibling feature doc; can split later if miss-counter heuristic grows independent design surface. Adds two phase rows to live-stream-support: termination detection (manifest signal, ENDLIST + miss-counter with naive/full depth) and terminated state transition (reload-loop exit + downstream endOfStream reachability + per-type independence). Corrections from Step 1 grounding the prior reverted draft missed: - Parser at media/hls/parse-media-playlist.ts:98 recognizes EXT-X-ENDLIST via `continue` but does NOT extract the value; MediaPlaylistInfo.endList is declared-but-orphaned. The parser- side fix is in scope for this feature. - endOfStream gate uses isLastSegmentAppended + currentTime, not presentation.duration finiteness. Prior draft's "Infinity won't pass the gate — needs review" claim was wrong. For live, the gate naturally doesn't fire (growing playlist, no permanent last segment); termination commits the last segment and the gate becomes reachable for normal reasons. Possible race if reload pacing lags playhead consumption — flagged as open question. Mux cleanup pass: rewrites unnecessary Mux/Mux Video specifics with vendor-neutral phrasing in live-stream-support and the new clusters.md classification axes. Legitimate code-reference citations to mux-background-video (in buffer-management) and the Permutations Matrix (in See also) preserved as load-bearing references. Cluster A docs list: drops [live-stream-termination-detection] entry (now subsumed into live-stream-support). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add internal/design/spf/features/capability-probing.md as a technical-depth doc for the cluster D foundation. Covers codec / container probing (isTypeSupported + canPlayType), multivariant CODECS filtering, key-system probing (requestMediaKeySystemAccess for DRM, distinct from EME setup), changeType() availability + pair-wise transition probing, and the unsupported-case error surfacing primitive. Tier 1 (spec-compliant filtering) + Tier 2 (customer overrides) layered onto specific phases. Includes a complexity phase for SourceBuffer.changeType() capability probing per the scoping discussion — the actual changeType() call lives in consumer features (HEVC variant selection, 5.1 surround, multi-language-audio Tier 2), but the "can the browser do this transition?" probe is here. Grounding finding: today's only capability check is isCodecSupported called inside createSourceBuffer — a late-failure path that fires after selection has already picked a (potentially unsupported) variant. This feature's main work is moving the check upstream so unsupported renditions never reach selection; the existing throw becomes a defensive fallback. Cascade: - clusters.md cluster D Docs list collapses [codec-capability- filtering], [multivariant-codecs-filtering], [key-system-capability- probing] into the single capability-probing doc ([container- support] open whether it folds in). Cluster F (DRM) Docs list updated to clarify that key-system probing is owned by cluster D while EME setup / license handling stay under DRM. - Related-features cross-refs added to mse-mms-pipeline (late- failure path), video-abr (filtered candidate set for ABR), audio- playback (filtered candidate set for audio selection), multi- language-audio (Tier 2 changeType dependency), and presentation- modeling (post-parse consumer). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds two catalog entries that surfaced during recent feature-doc work: - **API-as-feature inflation** — single-API invocations (MDN links, browser methods) are usually primitives consumed by an existing phase, not features in their own right. Pairs with a new Step 1 decomposition check that defaults to extending an existing doc unless the standalone rubric clearly fires. Step 2 now leads with the recommendation per AskUserQuestion guidance. - **Composition-variant logic in always-on behaviors** — when a mechanism only applies under one composition variant (live, audio- only, DRM-required), it lives as a new behavior composed into that variant, not as a runtime conditional in an always-on behavior. Worked example: setLiveSeekableRange initially proposed as an extension to updateMediaSourceDuration "under Infinity duration"; corrected to a separate live-only behavior. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extends live-stream-support.md's Live edge tracking + Terminated state transition phase rows to name setLiveSeekableRange / clearLiveSeekableRange as the DOM-exposure mechanism for the live seekable window. Adds a cross-cutting-impact bullet on mediaSource.* as a third-writer surface (structurally distinct from updateMediaSourceDuration + endOfStream) and an open question on within-live-variant placement (separate reactor vs. baked into the polling behavior; current lean: separate reactor). mse-mms-pipeline.md gains a sibling "What's not implemented" bullet and drops the stale `[live-stream-support]` candidate marker now that the doc exists. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously, every anticipated future feature appeared as a bracketed name in each cluster's Docs line, conflating documented features with unscoped sibling-feature placeholders. The bracket-as-candidate convention biased the registry toward "every candidate is a future feature doc," which short-circuits /spf-document-feature's Step 1 decomposition rubric that decides feature-vs-phase-vs-primitive at invocation time. Each cluster's Docs line now lists only documented features; clusters without any documented features show "None yet." Side fixes that fell out of the pass: stale [mse-mms-pipeline] bracket dropped (it's documented) and buffer-management added to the MSE / Buffer management cluster Docs line (was authored omission). The Notation section now points out that the unscoped candidates have been pulled out, and the "How this doc grows" trigger for cluster-list updates was rewritten to match. The candidates list itself lives in project memory rather than a checked-in doc. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…bles Same conflation as the prior Docs-list cleanup: bracketed candidates in the Feature classification axes tables (Media-src/Player/Borderline, Naive/Full depth, Tier 1/Tier 2, Composition/Policy/middle pattern) pre-classified unscoped items into axis categories. The mechanism- category assignment is exactly what /spf-document-feature should resolve at invocation time, not what cluster docs should assert upfront. Each table now keeps documented examples where they exist and replaces bracketed-candidate examples with descriptive category shapes — the teaching value (what does each axis category LOOK like?) survives, without committing specific named candidates to specific categories before they're scoped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First documented member of the Selection policy cluster. Umbrella feature unifying the billing-driven max-height cap (e.g., 1080p+), viewport-driven cap (screen-size / player-size), max-bitrate cap, and max-FPS cap as motivation phases of a shared constraint+filter mechanism — `selectQuality` reads per-cap constraint slots and filters `presentation.videoTracks` before bandwidth-based selection runs. Builds directly on the constraint+filter pattern that `video-abr`'s `userVideoTrackSelection` already exercises. Definition depth technical; not implemented. Source material: SPF Epics Working Doc cluster E entries #13 (1080p+ Resolution Cap) and NEW-C (Screen-Size / Player-Size Resolution Cap), unified per that doc's "Resolution-cap unification" open question. Decomposition rubric confirmed the umbrella framing — no per-phase criterion (independent footprint, independent priority, consumed primitive) fires for 1080p-alone scope. Cascade: video-abr.md "What's not implemented" + Related features entries updated to plain links; clusters.md Selection policy cluster Docs line now lists `rendition-selection-caps`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a fifth phase to rendition-selection-caps.md modeled on Mux Player's MinCapLevelController: a "minimum effective cap" floor that counters other caps (primarily viewport-driven) when their combination would narrow effective candidates below a configured threshold (e.g., 720p). Structurally distinct from the first four phases — meta-policy on cap combination, not an upper-bound cap of its own. Also refines the billing-driven phase Notes with the total-pixel matching nuance from the same reference (matching by total pixels ensures exact alignment with resolution-based pricing tiers; height- based matching is simpler default). Adds cap-combination semantics bullet to Likely cross-cutting impact, and two new Open questions (cap-floor scope vs capability-filter; cap-floor default value). Decomposition rubric confirmed phase-row scope: no independent implementation footprint (shares the constraint+filter primitive), no independent timeline, no consumed primitive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the network-resilience feature doc at coarse depth as the cluster G foundation. Borderline / response-error handling: retry/backoff, error classification, VRLT-aware response handling, playback-token- expiry refresh, customer-policy hooks. Tier 1 / Tier 2 framing with Naive vs Full depth distinctions per phase. Reframes cluster G: previously framed as "selection resilience" with multi-CDN as the primary feature. The cluster splits along two axes now — response-error handling (network-resilience covers this) and selection-side resilience (multi-cdn-failover / content-steering as sister consumer features yet to land). Absorbs: - selection-retry-backoff candidate (now Tier 1 phase: Generic retry with backoff + Error classification + retry budget/circuit-breaker in Tier 2) - Notion epic #12 VRLT (Viewer Rate Limiting Token) as Tier 2 phase - Notion epic #14 Playback Token Expiry as Tier 2 phase Six phases total: Generic retry (Tier 1) + Error classification (Tier 1) + Retry budget/circuit breaker (Tier 2) + VRLT-aware response (Tier 2) + Playback-token-expiry (Tier 2) + Customer-policy hooks (Tier 2). Cross-cutting impact captures: createTrackedFetch composition (sibling wrapper vs extension), bandwidth-sample exclusion for retry attempts, retry-policy slot vs per-site config, composition with multi-cdn-failover (retry vs rotation boundary), circuit-breaker state ownership, token-refresh hook convergence with DRM license- refresh, per-fetch-site config (manifest/segment/license/text- segment), live-stream reload-loop retry semantics. Open questions left explicit: retry-policy slot, default retry counts per site, VRLT detection signature shape, token-refresh hook, bandwidth-sample filtering, circuit-breaker ownership, composition order with multi-cdn-failover, retry-exhaustion error surfacing, composition with DRM, composition with content-steering. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rewrites cluster G description to reflect the new two-axis framing: response-error handling (network-resilience covers this) and selection-side resilience (multi-cdn-failover / content-steering as sister consumer features yet to land). - Cluster G description: split along two axes; explicit Borderline- flavored framing for response-error handling - Signals: add VRLT, playback-token-expiry, circuit-breaker per host - Docs: network-resilience now the cluster G foundation - Foundational primitives: retry/backoff + circuit-breaker primitive lives in network-resilience; alternate-URI rotation primitive remains for sister consumer features Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the multi-cdn-failover feature doc at coarse depth as the selection-side resilience sister to network-resilience (response-error handling). Five phases (Tier 1 / Tier 2 framing): - Tier 1: alternate-URI parsing + presentation surfacing - Tier 1: active-URI state + initial selection - Tier 2: rotation on retry-exhaustion (consumes network-resilience's retry-exhaustion signal) - Tier 2: per-URI health tracking (consumes network-resilience's circuit-breaker state) - Tier 2: customer-policy hooks for rotation override Hard prerequisite on network-resilience. Mux Video convention noted (?redundant_streams=true playback URL param). Content-steering kept as a parallel sister feature (sister-feature framing per user call, not absorbed) for the dynamic-host-pool case. Cross-cutting impact captures per-rendition vs per-presentation active URI, parser surface extension (HLS spec vs Mux convention), live + multi-CDN composition with reload-loop failover, composition with content-steering when it lands, rotation state across source changes, per-stream-type rotation coordination. Open questions left explicit: manifest syntax (HLS spec vs Mux), per-rendition vs per-presentation active URI, default rotation policy, content-steering composition, rotation-state preservation, customer-hook contract, DRM license-fetch interaction, per-type rotation coordination. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- network-resilience.md: drop brackets on [multi-cdn-failover] in three sites (opening paragraph, Out of scope consumer entry, Related features). All now plain-link the new doc. - clusters.md: cluster G Docs line adds multi-cdn-failover; Foundational primitives note updated to clarify alternate-URI rotation primitive lives in multi-cdn-failover (consumed by content-steering when it lands). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the content-steering feature doc at coarse depth as the dynamic- host-pool sister to multi-cdn-failover. HLS content-steering protocol implementation: server advertises pathway-priority via EXT-X-CONTENT-STEERING; client periodically fetches the steering manifest and biases URI selection. Six phases (Tier 1 / Tier 2 framing): - Tier 1: parse EXT-X-CONTENT-STEERING tag - Tier 1: initial steering-manifest fetch - Tier 1: apply pathway-priority to URI selection (composes with multi-cdn-failover's rotation) - Tier 2: periodic steering-manifest refresh (TTL-driven reload loop) - Tier 2: CDN-RESET-SECONDS handling (server-initiated reset of multi-cdn-failover + network-resilience state) - Tier 2: customer-policy hooks for pathway override Hard prerequisites on network-resilience (steering-manifest fetch retries) and multi-cdn-failover (rotation primitive being composed with). Pathway-priority shape: sort-key bias on multi-cdn-failover's candidate set (option a from the cross-cutting impact). Cross-cutting impact captures composition shape with multi-cdn-failover, reload-loop primitive sharing with live-stream-support, CDN-RESET-SECONDS state coordination across three features, per-rendition vs presentation-wide pathway-id, PATHWAY-CLONES extension scope, steering-manifest authorization, source-replacement cascade. Open questions left explicit: composition shape, reload-loop sharing, per-rendition pathway-id, PATHWAY-CLONES scope, CDN-RESET-SECONDS write coordination, steering-manifest authorization, customer-hook contract, mid-stream pathway changes during live + LL-HLS. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- network-resilience.md: drop brackets on [content-steering] in three sites (opening paragraph, Out of scope consumer, Related features). All plain-link the new doc. - multi-cdn-failover.md: drop brackets in Out of scope + Related features. Composition note in Out of scope refined: pathway-priority is a sort-key bias on the rotation primitive (option a from the composition open question), not a separate candidate-narrowing slot. - clusters.md: cluster G Docs line adds content-steering; Foundational primitives note updated — alternate-URI rotation primitive lives in multi-cdn-failover and is consumed by content-steering's pathway- priority bias. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the cluster B foundation doc at technical depth. Time-mapping primitive for sources where media-segment PTS doesn't start at zero. Three source-type phases (content-phase framing per user call): - Non-zero-PTS VOD: re-mastered / processed content retaining original PTS rather than zero-rebasing - Instant clips: deliberate offset for clipping use cases (clip starts at original PTS, user-visible currentTime starts at 0) - Live streams with non-zero PTS: encoder PTS counts from broadcast start; sliding-window updates roll segments off the start All three share the same mechanism: detect first-segment baseMedia- DecodeTime from MP4 tfdt box, compute presentationTimeOffset, apply via SourceBuffer.timestampOffset before initial segment append. currentTime and seekable range are offset-corrected naturally. Combines Notion epic #6 ("Non-zero PTS / Instant Clip Support") scope per the prior session-level absorption of instant-clip-support into non-zero-pts-support. Carves out discontinuity-handling as a new sister candidate (mid-stream PTS jumps via EXT-X-DISCONTINUITY, encoder restart, 33-bit PTS rollover). Cross-cutting impact captures: PTS-detection location (parser vs MSE-side), timestampOffset write timing in mse-mms-pipeline's setup sequence, per-type offset (video vs audio), seekable-range semantics composition with live-stream-support's setLiveSeekableRange, live + encoder-restart boundary with the carved-out sister feature, init-segment vs first-media-segment PTS detection. Open questions left explicit: parser depth, EXT-X-PROGRAM-DATE-TIME consumption, EXT-X-START parsing, per-type offset, discontinuity boundary, telemetry exposure, currentTime-near-zero browser quirks, composition with capability-probing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- live-stream-support.md: drop brackets on [non-zero-pts-support] in 2 sites (Out of scope, Related features); update wording to reflect non-zero-pts-support is now the documented cluster B foundation rather than a candidate. - dvr-event-stream-support.md: drop brackets in Related features. - ll-hls-support.md: drop brackets in Related features. - clusters.md: cluster B description gains Docs line (non-zero- pts-support); Foundational primitives note updated — primitive lives in non-zero-pts-support, consumed by every cluster A feature. Sub-cluster note for Borderline content compensation updated to reflect non-zero-pts-support is now the foundation (not foundation candidate). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…simulated)
User feedback: the doc pre-decided SourceBuffer.timestampOffset as
THE mechanism for applying the time offset. timestampOffset has
known A/V sync risks (per-SourceBuffer write means video and audio
buffers have separate offset values; sub-millisecond detection-time
precision differences can cause A/V drift that compounds; mid-source
offset changes require coordinated multi-buffer writes; browser
quirks especially on Safari). The alternative — simulate the offset
via adapter + math in behaviors/compositions — keeps the MSE buffer
"pure" with original PTS and translates at consumer boundaries
(translation surface trade-off but no A/V drift risk).
Changes:
- Opening paragraph: mechanism is now explicitly flagged as an open
question; both approaches summarized.
- Phase rows: Notes mechanism-neutral ("apply via the chosen
mechanism") rather than baking in timestampOffset.
- Cross-cutting impact: renamed "timestampOffset write timing" bullet
to "Mechanism choice: timestampOffset vs simulated translation
(load-bearing)". Walks through (a) timestampOffset trade-offs and
(b) simulated-translation trade-offs. Notes (b) is more SPF-natural
(behavior-driven translation fits the composition model); (a) is
more browser-API-natural.
- "currentTime semantics" bullet: rewritten as depends-on-mechanism.
- Open questions: new entry "Mechanism choice" capturing the
load-bearing decision; no lean yet (needs empirical A/V sync
testing under (a) + scoping translation surface under (b)).
- Related features (mse-mms-pipeline): depends-on-mechanism note.
- See also: timestampOffset reference annotated as "one of the two
candidate mechanisms."
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the first cluster B Borderline content-compensation feature doc. Heuristically detect "pseudo-ended" state — playback stalls near duration boundary on sources with mismatched manifest-duration vs actual segment data (canonically Safari) — and trigger termination cleanly so ended fires correctly. Two phases (detection + action), Naive vs Full depth per row matching Notion epic #10's framing: - Detection: Naive = don't (status quo). Full = heuristic monitor of playhead approaching duration + non-progressing + buffer doesn't reach duration. - Action: Naive = passive (browser stalls). Full = trigger clean termination via MediaSource.endOfStream() OR mediaSource.duration adjustment (mechanism choice open). Composition: VOD-engine variant only. Live engine variants don't carry this behavior (live has Infinity duration, no boundary to approach). Per the failure-mode catalog's composition-variant entry — variant-specific behavior, not runtime branch. Cross-cutting impact captures: action-mechanism choice trade-offs (endOfStream caller coordination with mse-mms-pipeline's existing gate vs duration multi-writer), distinction from buffer-stall-recovery (both detect "not progressing"; discriminator is "near duration boundary"), composition-variant placement, threshold tuning, false-positive avoidance, browser-specificity. Open questions: action-mechanism choice, detection thresholds, coordination with buffer-stall-recovery, live→VOD transition shape, browser detection gate, composition with edit-list-compensation, duration-undefined defensive case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
clusters.md cluster B sub-cluster note updated: pseudo-ended-detection moves from "candidate" to "Docs" with brief description. Edit-list- compensation and buffer-stall-recovery remain as "remaining candidates" (both about to land in this session). The earlier "Whether the three land as separate feature docs or a single umbrella doc is open" line removed — decision was made (separate features). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the second cluster B Borderline content-compensation feature. Parse MP4 init-segment edit-list (elst) boxes; extract implied presentation-time offsets; compensate engine-side for the shift. The canonical "middle pattern" example per clusters.md classification: initPTS detection -> offset state -> append behavior. Three phases: - Edit-list parsing (Naive: don't parse; Full: parse elst from init segment via shared targeted MP4 box extractor with non-zero-pts- support's tfdt parser) - Offset application (Naive: rely on browser; Full: engine-side compensation. Shares mechanism choice with non-zero-pts-support — timestampOffset vs simulated translation) - Multi-entry edit lists (Naive default: single-entry only; Full: multi-entry with loops/freeze-frames/speed changes — deferred until customer demand) Foundation dependency on non-zero-pts-support: shared offset- application mechanism question must resolve jointly. Composition of the two offsets (non-zero-PTS + edit-list) is the load-bearing open question; lean additive with debug exposure. Cross-cutting impact captures: offset composition shape, shared mechanism with non-zero-pts-support, browser-variance gate (Safari honors elst; Chrome/Firefox don't always — risk of double-shift), elst parser shape (shared with tfdt), per-track edit lists (video vs audio independent), mid-source edit-list changes (discontinuity territory), backend-fix exit condition (Notion epic flagged). Open questions left explicit: offset composition, joint mechanism choice, browser-variance gate, multi-entry support trigger, per- track semantics, elst parser depth, backend-fix exit condition, Mux Video relevance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- clusters.md cluster B sub-cluster note: edit-list-compensation added to Docs; only buffer-stall-recovery remains as candidate. - pseudo-ended-detection.md: drop brackets on [edit-list-compensation] Related features entry. - non-zero-pts-support.md: drop brackets on edit-list-compensation in the Borderline sister cross-ref list (alongside pseudo-ended- detection which already had brackets dropped). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the third and final cluster B Borderline content-compensation feature, completing the sub-cluster trio. Detect mid-stream playback stalls (playhead non-progressing despite buffer not at end, source not pseudo-ended, no in-flight retry) and trigger recovery actions in escalation order: seek-nudge -> buffer flush + refetch -> source reset. Two phases (detection + recovery action) with Naive/Full per row: - Detection: Naive = don't (status quo, browser handles or hangs). Full = heuristic monitor with stall threshold + coordination gates with pseudo-ended-detection (composition order) and network-resilience (don't fire during in-flight retry). - Recovery action: Naive = passive. Full = three-action escalation with per-step success-detection thresholds. Lightest first (seek-nudge -> flush+refetch -> source-reset). Composition: always-on (applies to both VOD and live). Unlike pseudo-ended-detection (VOD variant only), buffer-stall-recovery applies uniformly; live just triggers it more often. Cross-cutting impact captures: coordination with pseudo-ended- detection (mutually-exclusive triggers via near-boundary discriminator), coordination with network-resilience (gate on "no retry in flight"), recovery escalation order + thresholds, recovery-action implementation surfaces (mse-mms-pipeline, buffer-management, source-replacement-like reset), false-positive avoidance (paused / seeking / initial-load / background tabs), live vs VOD threshold differences, multi-signal-abr visibility coordination. Open questions left explicit: escalation order, detection threshold, pseudo-ended coordination shape, network-resilience gate slot, source-reset implementation, customer-policy hooks, page visibility coordination, backend exit condition, Notion- flagged deterministic testing challenge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Completes the cluster B Borderline content-compensation sub-cluster trio (pseudo-ended + edit-list + buffer-stall). - clusters.md: cluster B sub-cluster note adds buffer-stall-recovery to Docs; no remaining candidates in the sub-cluster. - pseudo-ended-detection.md: drop brackets on [buffer-stall-recovery] Related features entry. - edit-list-compensation.md: drop brackets on [buffer-stall-recovery] Related features entry. - non-zero-pts-support.md: drop brackets on buffer-stall-recovery in the Borderline sister cross-ref list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n-scope) Adds container-support as a standalone (cluster-less) coarse feature doc. Documents the strategic posture: Mux Video uses fMP4 across its delivery infrastructure; legacy MPEG-TS support is not on the roadmap for the foreseeable future. Notion epic #5 explicitly flags this as "Possibly an RFC, not an epic." Standalone cluster placement (not cluster D) because MSE doesn't accept non-fMP4 containers per spec — the concern is structurally different from capability-probing's "what can the browser decode within MSE-accepted containers?" framing. Two brief phases: - Container-format detection (signal-driven; HLS CODECS attribute + segment magic-byte sniffing; small parser extension) - Transmuxer integration (the major code footprint; reference implementations mux.js / hls.js; ~10kloc range) Cross-cutting impact captures: transmuxer-as-dependency-vs-inline, detection-vs-probing distinction, composition-variant placement, codec data routing (PMT vs stsd), bandwidth-sampling adjustment, performance considerations for live + MPEG-TS, MPEG-TS edge cases. Open questions: revisit conditions (when does fMP4-only posture change?), container-detection-without-transmuxer as a lower-cost intermediate option, transmuxer dependency choice if built, HLS mixed-container support, RFC route per Notion guidance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- capability-probing.md: resolve the "Container-detection scope" open question — container-support is documented as standalone (cluster-less; MSE doesn't accept non-fMP4 containers per spec). Container-detection-without-transmuxer remains a possible cross- feature integration point. - Related features entry: drop brackets on [container-support]; expanded note clarifies the cluster-D boundary distinction. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds audio-only-composition as a coarse Media-src feature doc. Engine support for HLS sources containing only audio renditions (no video tracks declared in manifest). Notion's "Composition cases per mode" Case 1: default composition handles a manifest that is genuinely audio-only. Status: partially supported today. The HLS engine tolerates audio- only sources per engine.test.ts "handles audio-only stream" test. Tolerance derives from video-side behaviors no-op-ing when presentation.videoTracks is empty. This feature makes that tolerance explicit via composition-variant subtraction. Three phases: audio-only manifest recognition (works today), audio-only engine variant (explicit composition-variant subtracting video-side behaviors), audio-only-optimized buffer/playback (Tier-2 optimizations: shorter buffer targets, no display work). Out of scope: audio-only mode override (Case-2 Player feature; the "use case composition" doc-type not yet formalized) which produces audio-only delivery even from mixed-manifest sources. Falls under parallel concepts like background-video / audio-podcast mode. Cross-cutting impact captures: engine composition shape for variants (matches live vs VoD precedent), behavior composition subtraction, variant-decision signal source (shared question across all variant features), endOfStream gate composition (variant-agnostic), audio-only ABR pairing with audio-abr, DOM exposure semantics. Open questions: engine variant factory shape, variant-decision signal source, audio-only buffer-target tuning, coordination with audio-abr, live + audio-only intersection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds video-only-composition as a coarse Media-src feature doc. Mirror of audio-only-composition on the inverse axis. Engine support for HLS sources containing only video renditions (no audio tracks). Notion NEW-A: "Default composition handles a manifest that is genuinely video-only." Status: not explicitly implemented. Engine tolerance for missing audio is less established than for missing video — empirical verification needed (does setupAudioBufferActors / loadAudioSegments fail / no-op consistently when audioTracks is empty?). Test fixture work is a prerequisite for scoping implementation. Three phases mirror audio-only-composition: manifest recognition, engine variant (subtractive composition of audio-side behaviors), optimized buffer / playback (muted-playback assumption, loop integration, no Firefox mozHasAudio quirk consideration). Mux relevance: mux-background-video (GitHub #873) is the canonical prior-art consumer. Cross-link for product context — the engine- support baseline (this feature) intersects with the background-video product use case (Case-2 use-case-composition concern). Boundary: this feature handles "source is video-only"; use-case-composition handles "deliver video-only from any source." Out of scope: video-only mode override (Case-2 Player feature, "use case composition" type) — Notion epic NEW-B, cross-referenced with mux-background-video #873's placement question. Cross-cutting impact captures: engine composition shape (matches audio-only-composition's pattern; resolves jointly), Firefox mozHasAudio quirk verification, background-video product intersection, autoplay-muted considerations, loop behavior coordination with buffer-management. Open questions: empirical video-only tolerance verification, engine variant factory shape (shared question), variant-decision signal source, loop integration scope, Firefox + video-only verification, mux-background-video placement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…oss-refs audio-playback.md: drop brackets on [audio-only-composition] in three sites (What's not implemented, open question, Related features). All now plain-link audio-only-composition.md. No corresponding cross-refs to update for video-only-composition (the candidate wasn't bracketed in any existing feature doc beyond clusters.md's Composition cases per mode table, which is already descriptive and doesn't need updating). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ca2f700 to
e1eeebb
Compare
luwes
pushed a commit
that referenced
this pull request
May 27, 2026
…ature skill (#1581) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
SPF design context has lived in PR descriptions, Notion working docs, and code comments — fine when one person needed to find it, brittle as more features and more contributors land. This PR seeds a permanent registry for that context, plus the skill that maintains it.
The primary reader is an LLM, with a human in the loop. These docs are written to be consumed by and updated by LLMs (via
/spf-document-featuretoday, and the upcoming implementation skills) while doing SPF feature and use-case development. Humans are a secondary audience — code review, design review, and onboarding still benefit, but the shape is optimized for grounding agent work: structured frontmatter, predictable section ordering, explicit cluster + classification-axis tagging, heavy cross-refs intoconventions/*and siblingfeatures/*, and a narrow-cascade rule so cross-doc context doesn't drift.What this enables:
spf-implement-feature,spf-create-behavior,spf-document-use-case,spf-implement-use-casewill read this registry as their scoping/grounding layer. Today's docs are forward enablement, not just retrospective documentation.clusters.md+ classification axes (Media-src/Player/Borderline, Naive/Full) give us shared vocabulary for the feature-vs-phase call instead of re-litigating it each invocation. The skill applies these heuristics consistently, triangulates across Notion / GitHub / code, and surfaces alternative framings when criteria fire weakly.Workflow change going forward — new SPF features route through
/spf-document-featurefirst (registry entry or a deepening of an existing one), so the cluster + cross-cutting concern checks run at scoping time before code lands.What's in this PR
internal/design/spf/features/covering clusters A–G:live-stream-support,multi-language-audio,container-support,non-zero-pts-support,capability-probing,engine-adapter-integration,mse-mms-pipeline,source-replacement,buffer-management,preload-modes,audio-playback,subtitles,dvr-event-stream-support,ll-hls-supportvideo-abr,audio-abr,multi-signal-abr,rendition-selection-caps,hevc-variant-selection,5.1-surround-selectionedit-list-compensation,pseudo-ended-detection,buffer-stall-recoverynetwork-resilience,multi-cdn-failover,content-steering,drm-supportaudio-only-composition,video-only-compositionfeatures/clusters.md— cluster heuristics, cross-cluster patterns, classification axespresentation-modeling.md— architectural deep-dive on the presentation slot lifecycle.claude/skills/spf-document-feature/drives source gathering, weak-criterion decomposition checks, cross-cutting concern checks, definition-depth selection, and narrow cross-doc cascadeSmall code-adjacent updates that landed alongside the docs:
packages/spf/docs/hls-engine.md— refreshtrackPlaybackInitiated→trackLoadTriggersand cross-reffeatures/preload-modes.mdpackages/spf/src/playback/behaviors/dom/setup-buffer-actors.ts— JSDoc cross-ref intofeatures/audio-abr.md(comment-only)packages/spf/src/playback/engines/hls/tests/engine.test.ts— initial-state-seeding coverage forcreateSimpleHlsEngineTest plan
internal/design/spf/features/clusters.mdrenders correctly on GitHub (tables, headings)conventions/*, siblingfeatures/*)pnpm -F @videojs/spf test src/playback/engines/hls/tests/engine.test.tspassespnpm typecheckandpnpm lintclean🤖 Generated with Claude Code
Note
Low Risk
Primarily adds/updates internal design documentation and a Claude skill; functional runtime risk is minimal aside from potential reviewer time and link/consistency drift across many new docs.
Overview
Seeds an SPF feature registry under
internal/design/spf/features/with new/updated feature docs (including selection/ABR, capability probing, buffer management, DRM, steering, and composition modes) and a newclusters.mdreference that defines cluster heuristics, classification axes, and cross-cluster patterns.Adds a new Claude skill,
spf-document-feature(.claude/skills/spf-document-feature/SKILL.md), that prescribes a structured workflow to create/update feature-registry entries (source triangulation, decomposition checks, code grounding, cross-cutting concern checks, and narrow cross-doc cascades).Reviewed by Cursor Bugbot for commit e1eeebb. Bugbot is set up for automated code reviews on this repo. Configure here.