Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 17 additions & 2 deletions .github/release-please/.release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
{
"packages/cli": "10.0.0-beta.32",
"packages/cloudflare-video": "10.0.0-beta.32",
"packages/core": "10.0.0-beta.32",
"packages/dash-video": "10.0.0-beta.32",
"packages/element": "10.0.0-beta.32",
"packages/google-cast": "10.0.0-beta.32",
"packages/hlsjs-video": "10.0.0-beta.32",
"packages/html": "10.0.0-beta.32",
"packages/media": "10.0.0-beta.32",
"packages/icons": "10.0.0-beta.32",
"packages/media": "10.0.0-beta.32",
"packages/mux-audio": "10.0.0-beta.32",
"packages/mux-data": "10.0.0-beta.32",
"packages/mux-video": "10.0.0-beta.32",
"packages/native-hls-video": "10.0.0-beta.32",
"packages/react": "10.0.0-beta.32",
"packages/shaka-video": "10.0.0-beta.32",
"packages/skins": "10.0.0-beta.32",
"packages/spf": "10.0.0-beta.32",
"packages/spotify-audio": "10.0.0-beta.32",
"packages/store": "10.0.0-beta.32",
"packages/tiktok-video": "10.0.0-beta.32",
"packages/twitch-video": "10.0.0-beta.32",
"packages/utils": "10.0.0-beta.32",
"packages/spf": "10.0.0-beta.32"
"packages/vimeo-video": "10.0.0-beta.32",
"packages/wistia-video": "10.0.0-beta.32",
"packages/youtube-video": "10.0.0-beta.32"
}
111 changes: 108 additions & 3 deletions .github/release-please/release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,31 @@
"groupName": "videojs",
"components": [
"@videojs/cli",
"@videojs/cloudflare-video",
"@videojs/core",
"@videojs/dash-video",
"@videojs/element",
"@videojs/google-cast",
"@videojs/hlsjs-video",
"@videojs/html",
"@videojs/icons",
"@videojs/media",
"@videojs/mux-audio",
"@videojs/mux-data",
"@videojs/mux-video",
"@videojs/native-hls-video",
"@videojs/react",
"@videojs/shaka-video",
"@videojs/skins",
"@videojs/spf",
"@videojs/spotify-audio",
"@videojs/store",
"@videojs/utils"
"@videojs/tiktok-video",
"@videojs/twitch-video",
"@videojs/utils",
"@videojs/vimeo-video",
"@videojs/wistia-video",
"@videojs/youtube-video"
]
}
],
Expand All @@ -34,32 +49,80 @@
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/cloudflare-video": {
"component": "@videojs/cloudflare-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/core": {
"component": "@videojs/core",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/dash-video": {
"component": "@videojs/dash-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/element": {
"component": "@videojs/element",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/google-cast": {
"component": "@videojs/google-cast",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/hlsjs-video": {
"component": "@videojs/hlsjs-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/html": {
"component": "@videojs/html",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/icons": {
"component": "@videojs/icons",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/media": {
"component": "@videojs/media",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/icons": {
"component": "@videojs/icons",
"packages/mux-audio": {
"component": "@videojs/mux-audio",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/mux-data": {
"component": "@videojs/mux-data",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/mux-video": {
"component": "@videojs/mux-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/native-hls-video": {
"component": "@videojs/native-hls-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
Expand All @@ -70,6 +133,12 @@
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/shaka-video": {
"component": "@videojs/shaka-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/skins": {
"component": "@videojs/skins",
"prerelease": true,
Expand All @@ -82,17 +151,53 @@
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/spotify-audio": {
"component": "@videojs/spotify-audio",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/store": {
"component": "@videojs/store",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/tiktok-video": {
"component": "@videojs/tiktok-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/twitch-video": {
"component": "@videojs/twitch-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/utils": {
"component": "@videojs/utils",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/vimeo-video": {
"component": "@videojs/vimeo-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/wistia-video": {
"component": "@videojs/wistia-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/youtube-video": {
"component": "@videojs/youtube-video",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
}
}
}
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,22 @@ jobs:
- '@videojs/core'
- '@videojs/icons'
- '@videojs/media'
- '@videojs/mux'
- '@videojs/cloudflare-video'
- '@videojs/spotify-audio'
- '@videojs/tiktok-video'
- '@videojs/twitch-video'
- '@videojs/youtube-video'
- '@videojs/native-hls-video'
- '@videojs/dash-video'
- '@videojs/google-cast'
- '@videojs/hlsjs-video'
- '@videojs/mux-audio'
- '@videojs/mux-data'
- '@videojs/mux-video'
- '@videojs/shaka-video'
- '@videojs/vimeo-video'
- '@videojs/wistia-video'
- '@videojs/skins'
- '@videojs/store'
- '@videojs/utils'
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/pkg-pr-new.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ jobs:
'./packages/element'
'./packages/html'
'./packages/media'
'./packages/cloudflare-video'
'./packages/spotify-audio'
'./packages/tiktok-video'
'./packages/twitch-video'
'./packages/youtube-video'
'./packages/native-hls-video'
'./packages/dash-video'
'./packages/google-cast'
'./packages/hlsjs-video'
'./packages/mux-audio'
'./packages/mux-data'
'./packages/mux-video'
'./packages/shaka-video'
'./packages/vimeo-video'
'./packages/wistia-video'
'./packages/react'
'./packages/spf'
'./packages/store'
Expand Down
12 changes: 11 additions & 1 deletion apps/e2e/suites/registry/setup/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ const overlaysDir = resolve(suiteDir, 'overlays');
const require = createRequire(import.meta.url);
const shadcnBin = require.resolve('shadcn');
const children: ChildProcess[] = [];
/**
* Packages the overlays import beyond what the registry items declare. The validation video plays through
* `@videojs/react/media/hlsjs-video` and `@videojs/html/media/hlsjs-video`, whose adapter package is an optional peer
* of the framework packages, so a consumer installs it explicitly, exactly as a real app would.
*/
const overlayDependencies = ['@videojs/hlsjs-video'];

export default async function setup(_config: FullConfig): Promise<() => Promise<void>> {
await rm(generatedDir, { recursive: true, force: true });
Expand Down Expand Up @@ -146,6 +152,10 @@ async function configurePackage(projectDir: string, overrides: Readonly<Record<s
...manifest,
private: true,
packageManager: 'pnpm@11.17.0',
dependencies: {
...manifest.dependencies,
...Object.fromEntries(overlayDependencies.map((name) => [name, overrides[name]])),
},
},
null,
2
Expand Down Expand Up @@ -372,7 +382,7 @@ async function packRegistryPackages(): Promise<Readonly<Record<string, string>>>
}

async function registryPackageRoots(): Promise<Set<string>> {
const roots = new Set<string>();
const roots = new Set<string>(overlayDependencies);

for (const project of registryConsumerProjects) {
const directory = registryPath(project);
Expand Down
2 changes: 1 addition & 1 deletion apps/sandbox/app/shared/sources.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MuxSource } from '@videojs/media/dom/mux';
import type { MuxSource } from '@videojs/mux-video';

import { getMuxAssetId } from './mux';

Expand Down
15 changes: 15 additions & 0 deletions apps/sandbox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,29 @@
"test": "vp test run"
},
"dependencies": {
"@videojs/cloudflare-video": "workspace:*",
"@videojs/core": "workspace:*",
"@videojs/dash-video": "workspace:*",
"@videojs/google-cast": "workspace:*",
"@videojs/hlsjs-video": "workspace:*",
"@videojs/html": "workspace:*",
"@videojs/icons": "workspace:*",
"@videojs/media": "workspace:*",
"@videojs/mux-audio": "workspace:*",
"@videojs/mux-data": "workspace:*",
"@videojs/mux-video": "workspace:*",
"@videojs/native-hls-video": "workspace:*",
"@videojs/react": "workspace:*",
"@videojs/shaka-video": "workspace:*",
"@videojs/spf": "workspace:*",
"@videojs/spotify-audio": "workspace:*",
"@videojs/store": "workspace:*",
"@videojs/tiktok-video": "workspace:*",
"@videojs/twitch-video": "workspace:*",
"@videojs/utils": "workspace:*",
"@videojs/vimeo-video": "workspace:*",
"@videojs/wistia-video": "workspace:*",
"@videojs/youtube-video": "workspace:*",
"clsx": "^2.1.1",
"tailwind-merge": "^3.5.0"
},
Expand Down
16 changes: 16 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,22 @@ export default {
'icons',
'jsx',
'media',
'mux',
'cloudflare-video',
'spotify-audio',
'tiktok-video',
'twitch-video',
'youtube-video',
'native-hls-video',
'dash-video',
'google-cast',
'hlsjs-video',
'mux-audio',
'mux-data',
'mux-video',
'shaka-video',
'vimeo-video',
'wistia-video',
'packages',
'plan',
'react-native',
Expand Down
2 changes: 1 addition & 1 deletion internal/decisions/media/mux-data-monitor-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ Three properties of the contract shaped the details:
- mux-embed SDK behavior (`videochange` resets the view and arms `viewstart` on `play`; the element monitor's event list), as shipped in the `mux-embed` npm package: https://www.npmjs.com/package/mux-embed
- `playback-core` destroy-per-source and its `muxDataKeepSession` workaround: https://github.com/muxinc/elements/blob/e1a32eb3fb147fcbd42f810ecf54101f4582f868/packages/playback-core/src/index.ts#L671-L679 and https://github.com/muxinc/elements/blob/e1a32eb3fb147fcbd42f810ecf54101f4582f868/packages/playback-core/src/index.ts#L697-L740
- Bug and fix: https://github.com/videojs/v10/issues/2562, https://github.com/videojs/v10/pull/2565. Inheriting work: https://github.com/videojs/v10/issues/1845
- Implementation: [`mux-data.ts`](/packages/media/src/dom/mux/mux-data.ts), [`mux-data.test.ts`](/packages/media/src/dom/mux/tests/mux-data.test.ts)
- Implementation: [`mux-data.ts`](/packages/mux-data/src/mux-data.ts), [`mux-data.test.ts`](/packages/mux-data/src/tests/mux-data.test.ts)
4 changes: 2 additions & 2 deletions internal/design/spf/features/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ without them in view.
| Error representation + emission | The error shape (SVTA category + index, plus context: track type, URL, the constraint or tag that triggered it) and the mechanism producers emit onto. Emission is **stacked** per SVTA Principle 6 — many errors across the timeline, most non-fatal — not a single latched slot | category+index | **Implemented** | Foundation for every later phase. Landed as an append-only sequence in a slot owned by `collectErrors`, with severity decided above it |
| Capability-pruned-to-empty surfacing | Replace both `track-switching.ts` `console.error`s. When a type *has* tracks but the hard-constraint pre-pass pruned every one, emit rather than only clearing the selection. Container/TS falls out for free — it reaches this site via `canPlayTrack` asserting `NON_FMP4_CONTAINER_MIMES` unplayable | 1004 / 1005 → 2011 / 2012 | **Implemented** (one of two `console.error`s — the other is an invariant assertion) | The convergence point for two distinct causes (unsupported container, undecodable codec) and one transient one (every CDN in failover cooldown). Stacking carries the cause code before the outcome code, preserving what the replaced `console.error` string held — and the causes now also decide which code the adapter surfaces. The existing `hasTracksOfType` guard already separates "no tracks of this type" (legitimate) from "all pruned" (error) |
| DRM detection via `EXT-X-KEY` | Recognize an encrypted source and fail clearly rather than appending undecryptable segments. New parser surface — `EXT-X-KEY` is unparsed today | 4008 | **Implemented** — media-playlist detection only | The one first-cut producer needing parser work. Placement decides *when* the verdict lands: `EXT-X-KEY` in the media playlist means post-track-resolution; `EXT-X-SESSION-KEY` in the multivariant would allow pre-resolution. Detection only — actually playing encrypted content is [drm-support](./drm-support.md) |
| Fatal derivation + adapter mapping | Derive a single fatal verdict from the emitted sequence; map it to `MediaError` at the adapter and dispatch `error`. Per-source reset. Only fatal errors reach the adapter | → 99001 → `MediaError` code | **Implemented**, plus cause-driven code substitution | Direct precedent: `packages/media/src/dom/hls-js/errors.ts:46` is `if (!data.fatal) return;`, and `native-hls/errors.ts:54` hard-codes `fatal: true`. Both are mixins owning `error: MediaError \| null`, dispatching `ErrorEvent`, clearing per source. Fatality is derived here, not asserted by producers — see *Likely cross-cutting impact*. The adapter surfaces a *code*, never prose; `packages/core` maps it to localized copy |
| Fatal derivation + adapter mapping | Derive a single fatal verdict from the emitted sequence; map it to `MediaError` at the adapter and dispatch `error`. Per-source reset. Only fatal errors reach the adapter | → 99001 → `MediaError` code | **Implemented**, plus cause-driven code substitution | Direct precedent: `packages/hlsjs-video/src/errors.ts:46` is `if (!data.fatal) return;`, and `native-hls/errors.ts:54` hard-codes `fatal: true`. Both are mixins owning `error: MediaError \| null`, dispatching `ErrorEvent`, clearing per source. Fatality is derived here, not asserted by producers — see *Likely cross-cutting impact*. The adapter surfaces a *code*, never prose; `packages/core` maps it to localized copy |
| Degraded-but-playable notices | The non-fatal tier: sources that play but aren't fully supported — LL-HLS (plays as standard live), DVR/EVENT (plays as simple live). Emit without failing | 2039 | **Partially implemented** — detected and announced, to a console rather than as emitted conditions | The PRD's "feature that doesn't exist on the Media in use" case where the answer is "it plays, but not the way you asked." `parseMediaPlaylist` detects both (`lowLatency`, `playlistType === 'EVENT'`) and the adapter warns once per source. Neither reaches `errors` as a 2039, because *Non-fatal destination* is unresolved — so nothing observable carries them yet. Depends on [ll-hls-support](./ll-hls-support.md) / [dvr-event-stream-support](./dvr-event-stream-support.md) for what "not fully supported" means per source |
| Runtime producers *(later)* | The three swallowed sites: manifest fetch/parse failure, and a live media-playlist reload rejection | 2014 / 2005 / 2017 | **Not implemented** | Deferred deliberately — these are runtime, not the PRD's ask. The live-reload one forces the recoverable-vs-fatal question immediately (a single failed reload is not fatal), which is why it isn't first |
| Retry-exhaustion intake *(later)* | Receive [network-resilience](./network-resilience.md)'s retry-exhaustion verdict as an emitted error | 3008 + 5-digit HTTP | **Not implemented** | That doc's open question "retry-exhaustion error surfacing — state slot vs callback vs both" resolves against this feature's phase 1 |
Expand Down Expand Up @@ -713,7 +713,7 @@ Kept for traceability.
- `packages/media/src/core/media-error.ts` — the `MediaError` contract
phase 4 maps onto (codes 1–5 + `MEDIA_ERR_CUSTOM`, `fatal`,
`context`, `data`, default messages)
- `packages/media/src/dom/hls-js/errors.ts`,
- `packages/hlsjs-video/src/errors.ts`,
`packages/media/src/dom/native-hls/errors.ts` — the adapter mixin
precedent, including the fatal-only filter
- [clusters.md § Multi-writer state slots](./clusters.md#multi-writer-state-slots)
Expand Down
4 changes: 2 additions & 2 deletions internal/design/spf/use-cases/background-video.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ is the narrower "deliver video-only despite mixed source" use case.
Phase 1 implemented ([#1586](https://github.com/videojs/v10/issues/1586)):
`createBackgroundVideoEngine` ships under `@videojs/spf/hls`, beside the other
HLS engines; `HlsBackgroundVideoMediaElement` and the host-bound
`HlsBackgroundVideoMedia` ship under `@videojs/spf/hls-background-video`, with
`@videojs/spf/mux-background-video` re-exporting them under Mux-flavored names.
`HlsBackgroundVideoMedia` ship under `@videojs/spf/hls-background-video`; html and
react alias them as `<mux-background-video>` / `MuxBackgroundVideo`.
The adapter carries no client-side cap: it pins the largest rendition the
manifest offers, and narrowing that set is a delivery param on the URL. The
max-resolution picker primitives (`maxResolutionToPixelArea`,
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/src/site-modules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ declare module '@/utils/installation/codegen' {
cdnMediaSubpaths: readonly string[]
): Record<'cdn' | 'npm' | 'pnpm' | 'yarn' | 'bun', string>;

export function generateReactInstallCode(): Record<'npm' | 'pnpm' | 'yarn' | 'bun', string>;
export function generateReactInstallCode(
opts?: Pick<InstallationOptions, 'renderer'>
): Record<'npm' | 'pnpm' | 'yarn' | 'bun', string>;

export function generateHTMLUsageCode(
opts: Pick<InstallationOptions, 'useCase' | 'skin' | 'renderer' | 'sourceUrl' | 'installMethod'>
Expand Down
Loading
Loading