Aug 20, 2026•Breaking changes

# v10.0.0-beta.30

[Compare changes on GitHub](https://github.com/videojs/v10/compare/@videojs/core@10.0.0-beta.29...@videojs/core@10.0.0-beta.30)

Shaka Player joins the lineup, and it landed twice in one release: first as a working element, then again with everything the hls.js media already had. Around it, two APIs move to where they belong — orientation lock onto the provider, poster placeholders out of the player entirely.

## Breaking changes

*   **Orientation lock is provider configuration** ([#1999](https://github.com/videojs/v10/pull/1999)). `features.orientationLock({ type })` is gone. Select the feature as a value — `features.orientationLock` — and set the type on the provider: the `orientation-lock-type` attribute in HTML, the `orientationLockType` prop in React. Clearing the value restores `landscape`. Read it with `selectOrientationLock`, or set it imperatively with `setOrientationLockType`. The factory-configured feature form goes with it: `ConfigurablePlayerFeature`, `ConfigurablePlayerFeatureConfig`, `OrientationLockFeatureConfig`, `forConfig`, `definePlayerSlice`, and `definePlayerFeature`’s two-argument overload are all removed.
*   **Built-in poster placeholders are removed** ([#2063](https://github.com/videojs/v10/pull/2063)). The React `posterPlaceholder` input, the HTML `poster-placeholder` attribute, the skin `placeholder` prop and `placeholdersrc` attribute, and `--media-poster-placeholder` with its blur layers are all gone. Supply the placeholder yourself: pass `renderPoster` to a React skin, or slot an `<img slot="poster">` carrying a CSS background in HTML. Nothing needs a replacement API — both customization points already existed.

## Shaka Player, twice

`<shaka-video>` for HTML and `<ShakaVideo>` for React play DASH and HLS from one engine, with Shaka’s DRM stack behind the standardized `source.drm` API ([#2276](https://github.com/videojs/v10/pull/2276)). `source.type` is handed to Shaka as the type to parse the manifest as, which is what makes an extensionless URL playable. `source.drm` — the same engine-neutral shape hls.js and native HLS read — becomes Shaka’s license servers and certificate URIs, with `engine.shaka` as the escape hatch for the richer config. Video renditions and audio tracks mirror into `videoRenditions` and `audioTracks`; pinning a rendition turns ABR off and hands adaptation back when the selection clears. Errors are reported only when Shaka gives up: a failure it means to retry warns in development instead, and a load superseded by a newer one is never announced at all.

A fast follow brought it level with the hls.js media ([#2285](https://github.com/videojs/v10/pull/2285)). Importing the media used to crash any server runtime, because every `shaka-player` dist reads a bare `self` while its UMD wrapper evaluates; a shim lends it one and takes it back, and the constructor bails before the browser-support probe when there is no DOM. The element now ships Shaka’s es2021 bundle instead of the ES5 default, taking `@videojs/html/media/shaka-video` from 225.3 kB to 204.2 kB. On top of that: `streamType` detection with a user override, `targetLiveWindow` and a read-time `liveEdgeStart` with the same seek-to-live on first play the hls.js media performs, `preload` mapped onto when and how `load()` runs, and ABR restricted to element size by default. There’s no reference page for it yet.

## Titles, metadata, and configuration

Drop `<media-title>` or `<Title>` into a skin and it renders the title the store resolved ([#1997](https://github.com/videojs/v10/pull/1997)). Set it on the player with the `content-title` attribute in HTML or the `title` prop in React; the component reads `metadata` and nothing else. With no title to show, HTML sets the native `hidden` attribute plus `data-hidden` and React renders nothing, so an empty title takes itself out of the layout. Registration is opt-in through `@videojs/html/ui/title` until a skin renders one, so no skin pays for bytes it doesn’t use. See the reference for [HTML](/docs/framework/html/reference/title/) and [React](/docs/framework/react/reference/title/).

The metadata feature is documented now, and the feature reference builder grew a Configuration section to do it ([#2000](https://github.com/videojs/v10/pull/2000)). Generated pages describe the inputs a selected feature adds to the provider — type, default, React prop, and HTML attribute — rather than state and actions alone. Read it for [HTML](/docs/framework/html/reference/feature-metadata/) and [React](/docs/framework/react/reference/feature-metadata/).

Orientation lock is the first feature to use that table, having moved to provider configuration in the same stack ([#1999](https://github.com/videojs/v10/pull/1999)); see [Breaking changes](#breaking-changes). Making the type responsive exposed three ways the lock could desync from the screen, all from one variable standing for both “last requested” and “type we hold”. The primitive tracks `desired` and `held` separately now and reconciles one request at a time, so a rejected lock no longer suppresses every later request for the same type, overlapping requests can’t leave the screen describing one type while the store reports another, and a platform that always rejects stops getting re-asked several times a second during playback. Details in the orientation lock feature for [HTML](/docs/framework/html/reference/feature-orientation-lock/) and [React](/docs/framework/react/reference/feature-orientation-lock/).

## Posters, previews, and menus

With placeholders out of the player, the skins render the poster and stop there — and they leave it visible while it loads, so a background you supplied can be seen instead of being hidden behind a transparent image. The new guide covers React image components, bare `Poster`, packaged HTML skins, and ejected ones: [HTML](/docs/framework/html/how-to/add-a-poster-and-loading-placeholder) and [React](/docs/framework/react/how-to/add-a-poster-and-loading-placeholder), with the component itself for [HTML](/docs/framework/html/reference/poster/) and [React](/docs/framework/react/reference/poster/).

Storyboard hover previews never loaded on a cross-origin-isolated page ([#2273](https://github.com/videojs/v10/pull/2273)). Under `Cross-Origin-Embedder-Policy: require-corp` a cross-origin subresource is blocked unless it’s CORS-enabled, and the thumbnail image was always fetched no-CORS with no way to configure it through the skins. It inherits the media element’s CORS mode now when `crossOrigin` is unset, which is safe because a cross-origin thumbnail track only loads on a CORS-enabled media element in the first place — reaching the inherit path means the author already opted in. `null` opts back out; thumbnails supplied directly through the `thumbnails` prop never inherit. The skins needed no change. See the thumbnail reference for [HTML](/docs/framework/html/reference/thumbnail/) and [React](/docs/framework/react/reference/thumbnail/).

Settings submenus sized themselves wrong because child layout offsets counted the container’s leading padding twice, so the synced menu height didn’t match the rendered content ([#2283](https://github.com/videojs/v10/pull/2283)). The same pass drops persistent `will-change` hints from menu panels and control transitions, which could contribute to animation stutter in Safari, while keeping the transient indicator and button hints that earn their place. Covered in the menu reference for [HTML](/docs/framework/html/reference/menu/) and [React](/docs/framework/react/reference/menu/).

## Under the hood: SPF

SPF caps rendition selection to the player’s rendered size, on by default ([#2242](https://github.com/videojs/v10/pull/2242)). A small embed stops pulling renditions larger than it can show. The cap is the smallest ladder tier that still covers the player plus everything below it, not a hard at-or-below-area cut, which would underserve a player sitting between tiers. `playerResolutionCap` slots into the video switch chain after the user filter, so a manual pick still wins, and before the ranker, which then chooses within the cap. Measurement goes through a resize observer composed with a device-pixel-ratio watcher, since browser zoom or a move to another display changes the ratio without resizing the element. `capRenditionToPlayerSize` gates the measurement and `useDevicePixelRatio` gates whether the cap scales to device pixels. Renditions declaring no resolution are never capped out, and picture-in-picture and iOS native fullscreen aren’t handled yet — the element keeps its layout box while the viewer watches a different surface.

Background video with an undecodable ladder no longer stalls in silence ([#2286](https://github.com/videojs/v10/pull/2286)). An HEVC or AV1 source the environment can’t decode leaves `HTMLMediaElement.error` null at `readyState 0`, and it was the one cause the unplayable-source reporting couldn’t reach: codecs live in the multivariant playlist, so the whole ladder gets pruned before anything resolves and no cause is ever produced. Moving `reportAbsentTrackType` to the tail of the constraint chain fixes it, where an empty input means “nothing playable here” whether the renditions were pruned or never offered. First-fatal-wins is unchanged, so `media.error` still surfaces the real cause when there is one; only the logged sequence grows. Read the background video reference for [HTML](/docs/framework/html/reference/background-video/) and [React](/docs/framework/react/reference/background-video/).

---

All documentation: https://videojs.org/llms.txt