Skip to content

docs(site): add MuxData and GoogleCast API references; document status announcer and mux-video source API - #1902

Merged
decepulis merged 4 commits into
mainfrom
claude/mux-data-cast-api-refs
Jul 31, 2026
Merged

docs(site): add MuxData and GoogleCast API references; document status announcer and mux-video source API#1902
decepulis merged 4 commits into
mainfrom
claude/mux-data-cast-api-refs

Conversation

@decepulis

@decepulis decepulis commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Requested by Darius Cepulis · Slack thread

Before — mux-data and google-cast were documented only as concept guides, with their config options buried in the explanation and no API-reference pages, so they never appeared in the reference sidebar. The mux-video reference embedded the generated props table but had no prose for the new src vs source loading modes, thumbnails/storyboards, or signed playback. The accessibility guide didn't mention the screen-reader status announcer.

After — mux-data and google-cast each get a dedicated API-reference page (anatomy + options tables), listed under Components in the sidebar. The concept guides keep the "how it works" narrative and link out to the references for options. The mux-video reference explains src/source, sourcechange, derived thumbnails/storyboards, and signed-playback token rules. The accessibility guide documents the live-region status announcer and the accessible player-container attributes.

How — mux-data/google-cast are non-rendering MediaComponentElements that the api-docs builder doesn't scan, so their options tables are hand-authored from the prop definitions (a follow-up issue tracks replacing them post-GA). Concept edits move options into the references and tighten prose to Diátaxis explanation mode. mux-video and accessibility additions are drawn from #1850 and #1659 and verified against source.


Note

Low Risk
Documentation and navigation changes only; no application or player runtime code in the diff.

Overview
Adds dedicated API reference pages for GoogleCast and MuxData (anatomy + hand-authored options tables) and registers them under Components in the docs sidebar. The Google Cast and Mux Data concept guides keep the narrative but drop inlined option tables, pointing readers to those references instead; Cast configuration is consolidated into fewer examples.

The accessibility concept guide now documents the focusable, labeled player container (role="group") and a new Status announcements section describing the role="status" live region (confirmed store state, debouncing, quiet while sliders are focused).

The MuxVideo reference gains prose for src vs source, sourcechange, derived thumbnail/storyboard URLs, and signed playback token rules. Minor copy tweaks and DocsLinkCard description props appear across related pages.

Reviewed by Cursor Bugbot for commit 6450531. Bugbot is set up for automated code reviews on this repo. Configure here.

claude added 2 commits July 31, 2026 21:26
…ouncer + mux-video source

Add hand-authored reference pages for the mux-data and google-cast media
components (both non-rendering MediaComponentElement components the api-docs
builder does not scan), move their option/configuration tables out of the
concept guides into the references, and wire both into the Media Elements
sidebar. Give the Mux Data and Google Cast concept guides an editorial pass so
they stay in Diataxis explanation mode and point to the new references.

Also document the #1659 status announcer and accessible container attrs in the
accessibility concept guide, and the #1850 mux-video src/source/thumbnail/
storyboard/signed-playback API in the mux-video reference.
Move the reference/google-cast and reference/mux-data sidebar entries
from the Media Elements section to the Components section, preserving
alphabetical ordering.
@netlify

netlify Bot commented Jul 31, 2026

Copy link
Copy Markdown

Deploy Preview for vjs10-site ready!

Name Link
🔨 Latest commit 6450531
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/6a6d215c1ba2a1000815d8ab
😎 Deploy Preview https://deploy-preview-1902--vjs10-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v10-sandbox Ready Ready Preview Jul 31, 2026 10:27pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

🎨 @videojs/html — no changes
Presets (7)
Entry Initial Lazy
/video (default) 53.68 kB 51.74 kB
/video (default + hls) 189.59 kB 51.74 kB
/video (minimal) 53.58 kB 51.74 kB
/video (minimal + hls) 189.52 kB 51.74 kB
/audio (default) 45.94 kB 51.74 kB
/audio (minimal) 42.39 kB 51.74 kB
/background 5.00 kB 51.74 kB
Media (12)
Entry Initial Lazy
/media/background-video 1.14 kB
/media/container 2.58 kB 51.74 kB
/media/dash-video 211.14 kB
/media/google-cast 6.46 kB
/media/hlsjs-video 137.92 kB
/media/mux-audio 138.88 kB
/media/mux-data 153.85 kB
/media/mux-video 139.06 kB
/media/native-hls-video 5.34 kB
/media/simple-hls-audio-only 19.92 kB
/media/simple-hls-video 24.27 kB
/media/vimeo-video 12.31 kB
Players (5)
Entry Initial Lazy
/video/player 8.98 kB 51.74 kB
/audio/player 6.20 kB 51.74 kB
/background/player 4.73 kB 51.74 kB
/live-video/player 8.39 kB 51.74 kB
/live-audio/player 6.22 kB 51.74 kB
Skins (30)
Entry Type Initial Lazy
/video/minimal-skin.css css 5.93 kB
/video/skin.css css 5.93 kB
/video/minimal-skin js 53.53 kB 51.74 kB
/video/minimal-skin.tailwind js 54.16 kB 51.74 kB
/video/skin js 53.69 kB 51.74 kB
/video/skin.tailwind js 54.31 kB 51.74 kB
/audio/minimal-skin.css css 4.12 kB
/audio/skin.css css 4.06 kB
/audio/minimal-skin js 42.33 kB 51.74 kB
/audio/minimal-skin.tailwind js 42.91 kB 51.74 kB
/audio/skin js 45.89 kB 51.74 kB
/audio/skin.tailwind js 46.46 kB 51.74 kB
/background/skin.css css 133 B
/background/skin js 1.14 kB
/live-video/minimal-skin.css css 5.93 kB
/live-video/skin.css css 5.93 kB
/live-video/minimal-skin js 49.88 kB 51.74 kB
/live-video/minimal-skin.tailwind js 50.51 kB 51.74 kB
/live-video/skin js 52.21 kB 51.74 kB
/live-video/skin.tailwind js 52.74 kB 51.74 kB
/live-audio/minimal-skin.css css 4.12 kB
/live-audio/skin.css css 4.06 kB
/live-audio/minimal-skin js 34.57 kB 51.74 kB
/live-audio/minimal-skin.tailwind js 33.99 kB 51.74 kB
/live-audio/skin js 38.23 kB 51.74 kB
/live-audio/skin.tailwind js 37.83 kB 51.74 kB
/global.css css 183 B
/shared.css css 104 B
/tailwind.css css 161 B
/skin-element js 1.46 kB
UI Components (39)
Entry Initial
/ui/airplay-button 2.59 kB
/ui/alert-dialog 3.00 kB
/ui/alert-dialog-close 2.57 kB
/ui/alert-dialog-description 2.50 kB
/ui/alert-dialog-title 2.54 kB
/ui/audio-track-radio-group 3.12 kB
/ui/buffering-indicator 2.86 kB
/ui/captions-button 2.66 kB
/ui/captions-radio-group 3.11 kB
/ui/cast-button 2.57 kB
/ui/compounds 3.42 kB
/ui/controls 3.08 kB
/ui/error-dialog 3.11 kB
/ui/fullscreen-button 2.67 kB
/ui/hotkey 2.64 kB
/ui/menu 3.12 kB
/ui/mute-button 2.61 kB
/ui/pip-button 2.63 kB
/ui/play-button 2.64 kB
/ui/playback-rate-button 2.71 kB
/ui/playback-rate-radio-group 2.91 kB
/ui/popover 3.25 kB
/ui/poster 2.51 kB
/ui/quality-radio-group 3.09 kB
/ui/seek-button 2.66 kB
/ui/seek-indicator 2.90 kB
/ui/seek-indicator-value 415 B
/ui/slider 3.10 kB
/ui/status-announcer 2.51 kB
/ui/status-indicator 2.61 kB
/ui/status-indicator-value 499 B
/ui/thumbnail 2.76 kB
/ui/time 3.09 kB
/ui/time-slider 3.12 kB
/ui/tooltip 3.05 kB
/ui/volume-indicator 2.64 kB
/ui/volume-indicator-fill 555 B
/ui/volume-indicator-value 430 B
/ui/volume-slider 3.10 kB

Sizes are marginal over the root entry point.

⚛️ @videojs/react — no changes
Presets (7)
Entry Initial Lazy
/video (default) 42.35 kB 51.74 kB
/video (default + hls) 177.00 kB 51.74 kB
/video (minimal) 42.70 kB 51.74 kB
/video (minimal + hls) 177.37 kB 51.74 kB
/audio (default) 34.57 kB 51.74 kB
/audio (minimal) 34.71 kB 51.74 kB
/background 581 B
Media (11)
Entry Initial
/media/background-video 394 B
/media/dash-video 209.54 kB
/media/google-cast 5.35 kB
/media/hlsjs-video 136.40 kB
/media/mux-audio 137.23 kB
/media/mux-data 152.83 kB
/media/mux-video 137.38 kB
/media/native-hls-video 3.54 kB
/media/simple-hls-audio-only 18.18 kB
/media/simple-hls-video 22.64 kB
/media/vimeo-video 10.46 kB
Skins (27)
Entry Type Initial Lazy
/tailwind.css css 161 B
/video/minimal-skin.css css 5.82 kB
/video/skin.css css 5.82 kB
/video/minimal-skin js 42.59 kB 51.74 kB
/video/minimal-skin.tailwind js 48.80 kB 51.74 kB
/video/skin js 42.30 kB 51.74 kB
/video/skin.tailwind js 48.54 kB 51.74 kB
/audio/minimal-skin.css css 3.98 kB
/audio/skin.css css 3.92 kB
/audio/minimal-skin js 34.57 kB 51.74 kB
/audio/minimal-skin.tailwind js 37.05 kB 51.74 kB
/audio/skin js 34.46 kB 51.74 kB
/audio/skin.tailwind js 38.86 kB 51.74 kB
/background/skin.css css 90 B
/background/skin js 272 B
/live-video/minimal-skin.css css 5.82 kB
/live-video/skin.css css 5.82 kB
/live-video/minimal-skin js 37.60 kB 51.74 kB
/live-video/minimal-skin.tailwind js 43.76 kB 51.74 kB
/live-video/skin js 37.54 kB 51.74 kB
/live-video/skin.tailwind js 43.82 kB 51.74 kB
/live-audio/minimal-skin.css css 3.98 kB
/live-audio/skin.css css 3.92 kB
/live-audio/minimal-skin js 25.02 kB 51.74 kB
/live-audio/minimal-skin.tailwind js 28.31 kB 51.74 kB
/live-audio/skin js 25.09 kB 51.74 kB
/live-audio/skin.tailwind js 28.49 kB 51.74 kB
UI Components (33)
Entry Initial
/ui/airplay-button 2.59 kB
/ui/alert-dialog 2.82 kB
/ui/audio-track 2.50 kB
/ui/buffering-indicator 2.70 kB
/ui/captions-button 2.61 kB
/ui/captions-radio-group 2.52 kB
/ui/cast-button 2.66 kB
/ui/controls 2.69 kB
/ui/error-dialog 2.69 kB
/ui/fullscreen-button 2.64 kB
/ui/gesture 2.60 kB
/ui/hotkey 2.68 kB
/ui/live-button 2.58 kB
/ui/menu 2.83 kB
/ui/mute-button 2.58 kB
/ui/pip-button 2.70 kB
/ui/play-button 2.61 kB
/ui/playback-rate 2.64 kB
/ui/playback-rate-button 2.60 kB
/ui/popover 3.36 kB
/ui/poster 2.64 kB
/ui/quality 2.44 kB
/ui/seek-button 2.70 kB
/ui/seek-indicator 2.81 kB
/ui/slider 2.62 kB
/ui/status-announcer 2.51 kB
/ui/status-indicator 2.53 kB
/ui/thumbnail 2.61 kB
/ui/time 2.52 kB
/ui/time-slider 2.71 kB
/ui/tooltip 3.32 kB
/ui/volume-indicator 2.49 kB
/ui/volume-slider 2.69 kB

Sizes are marginal over the root entry point.

🧩 @videojs/core — no changes
Entries (73)
Entry Initial Lazy
. 11.38 kB
/dom 18.32 kB
/i18n 3.03 kB 51.74 kB
/i18n/locales/all 31.40 kB
/i18n/locales/ar 1.14 kB
/i18n/locales/az 1.04 kB
/i18n/locales/bg 1.21 kB
/i18n/locales/bn 1.23 kB
/i18n/locales/bs 951 B
/i18n/locales/ca 1.00 kB
/i18n/locales/cs 1022 B
/i18n/locales/cy 977 B
/i18n/locales/da 943 B
/i18n/locales/de 1.02 kB
/i18n/locales/el 1.40 kB
/i18n/locales/en 732 B
/i18n/locales/es 959 B
/i18n/locales/et 1019 B
/i18n/locales/eu 983 B
/i18n/locales/fa 1.14 kB
/i18n/locales/fi 997 B
/i18n/locales/fr 1.01 kB
/i18n/locales/gd 1.03 kB
/i18n/locales/gl 960 B
/i18n/locales/he 1.06 kB
/i18n/locales/hi 1.24 kB
/i18n/locales/hr 986 B
/i18n/locales/hu 1.02 kB
/i18n/locales/it 997 B
/i18n/locales/ja 1.13 kB
/i18n/locales/ko 1.08 kB
/i18n/locales/lv 1.02 kB
/i18n/locales/mr 1.24 kB
/i18n/locales/nb 928 B
/i18n/locales/ne 1.23 kB
/i18n/locales/nl 967 B
/i18n/locales/nn 931 B
/i18n/locales/oc 1.01 kB
/i18n/locales/pl 1.06 kB
/i18n/locales/pt 988 B
/i18n/locales/pt-BR 988 B
/i18n/locales/pt-PT 953 B
/i18n/locales/ro 1.01 kB
/i18n/locales/ru 1.29 kB
/i18n/locales/sk 1.03 kB
/i18n/locales/sl 987 B
/i18n/locales/sr 1018 B
/i18n/locales/sv 962 B
/i18n/locales/te 1.26 kB
/i18n/locales/th 1.22 kB
/i18n/locales/tr 1.01 kB
/i18n/locales/uk 1.32 kB
/i18n/locales/vi 1.03 kB
/i18n/locales/zh 977 B
/i18n/locales/zh-CN 977 B
/i18n/locales/zh-TW 972 B
/i18n/text/airplay 101 B
/i18n/text/buttons 137 B
/i18n/text/captions 93 B
/i18n/text/cast 114 B
/i18n/text/common 90 B
/i18n/text/container 75 B
/i18n/text/errors 277 B
/i18n/text/fullscreen 98 B
/i18n/text/live 126 B
/i18n/text/menu 249 B
/i18n/text/pip 101 B
/i18n/text/playback 80 B
/i18n/text/seek 105 B
/i18n/text/slider 65 B
/i18n/text/status 222 B
/i18n/text/time 214 B
/i18n/text/volume 133 B
🏷️ @videojs/element — no changes
Entries (2)
Entry Initial
. 996 B
/context 943 B
📦 @videojs/store — no changes
Entries (3)
Entry Initial
. 1.39 kB
/html 696 B
/react 361 B
🔧 @videojs/utils — no changes
Entries (12)
Entry Initial
/array 104 B
/dom 3.16 kB
/events 319 B
/function 327 B
/jwt 176 B
/object 505 B
/predicate 265 B
/percent 281 B
/string 239 B
/style 190 B
/time 813 B
/number 158 B
📦 @videojs/media — no changes
Entries (14)
Entry Initial
. 959 B
/dom/audio-host 1.11 kB
/dom/custom-media-element 2.09 kB
/dom/dash 208.99 kB
/dom/google-cast 4.06 kB
/dom/hls-js 136.00 kB
/dom/media-host 1.21 kB
/dom/media-played-ranges 576 B
/dom/mux 159.41 kB
/dom/native-hls 3.02 kB
/dom/simple-hls 22.09 kB
/dom/simple-hls-audio-only 17.73 kB
/dom/video-host 1.40 kB
/dom/vimeo 9.88 kB
📦 @videojs/spf — no changes
Entries (5)
Entry Initial
. 4.46 kB
/dom 6.50 kB
/hls 18.74 kB
/media-tracks 504 B
/background-video 13.42 kB

ℹ️ How to interpret

JS sizes are initial static graph totals (minified + brotli). Lazy dynamic chunks are shown separately when present.

Icon Meaning
No change
🔺 Increased ≤ 10%
🔴 Increased > 10%
🔽 Decreased
🆕 New (no baseline)

Run pnpm size locally to check current initial sizes.

@decepulis decepulis left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting a few changes!

Comment thread site/src/content/docs/concepts/cast.mdx Outdated

## See also

<DocsLinkCard slug="reference/google-cast">GoogleCast reference — every option</DocsLinkCard>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<DocsLinkCard slug="reference/google-cast">GoogleCast reference — every option</DocsLinkCard>
<DocsLinkCard slug="reference/google-cast">GoogleCast reference</DocsLinkCard>

### Cast a different source

By default the receiver loads the same URL the browser plays. Set `src` (and optionally `contentType`) to send the receiver a different one — for example, cast an HLS stream while the browser plays an MP4:
By default, the receiver loads the same source the browser plays through Google's [Default Media Receiver](https://developers.google.com/cast/docs/web_sender/integrate#default_media_web_receiver). Point Cast at your own receiver app, send a different source, attach custom data to the load request, or override the stream type through the component's options:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of removed copy here. I'm trusting that you made sure that useful information was preserved through this rewrite.


## See also

<DocsLinkCard slug="reference/mux-data">MuxData reference — every option</DocsLinkCard>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<DocsLinkCard slug="reference/mux-data">MuxData reference — every option</DocsLinkCard>
<DocsLinkCard slug="reference/mux-data">MuxData reference</DocsLinkCard>

import DocsLink from '@/components/docs/DocsLink.astro';
import DocsLinkCard from '@/components/docs/DocsLinkCard.astro';

Adds Google Cast support to the player's media. It renders nothing — place it inside the player as a sibling of the media element, and pair it with a <DocsLink slug="reference/cast-button">CastButton</DocsLink>. See <DocsLink slug="concepts/cast">Google Cast</DocsLink> for how casting works.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not morally opposed to dashes -- in fact, I like using them in my own writing!
But your use of dashes does make me wonder if you adhered to writing-style.md which, iirc, asks authors to be judicious with them. If you did, disregard this comment! If you didn't, take a pass.


## See also

<DocsLinkCard slug="concepts/cast">Google Cast — how casting works</DocsLinkCard>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you MUST have both a title and additional information in a docslinkcard, consider using the dedicated title prop. (I think it's called that)

import DocsLink from '@/components/docs/DocsLink.astro';
import DocsLinkCard from '@/components/docs/DocsLinkCard.astro';

Adds [Mux Data](https://www.mux.com/data) monitoring to the player's media. It renders nothing — place it inside the player as a sibling of the media element. See <DocsLink slug="concepts/mux-data">Mux Data</DocsLink> for how monitoring works.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Adds [Mux Data](https://www.mux.com/data) monitoring to the player's media. It renders nothing — place it inside the player as a sibling of the media element. See <DocsLink slug="concepts/mux-data">Mux Data</DocsLink> for how monitoring works.
Adds [Mux Data](https://data.mux.com) monitoring to the player's media. It renders nothing — place it inside the player as a sibling of the media element. See <DocsLink slug="concepts/mux-data">Mux Data</DocsLink> for how monitoring works.


## See also

<DocsLinkCard slug="concepts/mux-data">Mux Data — how monitoring works</DocsLinkCard>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See title comment earlier


## Load a source

Point MuxVideo at Mux content two ways: a stream URL through `src`, or a structured `source` object.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In React, prefer source and treat src as an escape hatch. In HTML, it's acceptable to name them as peers like you do here.

```
</FrameworkCase>

MuxVideo fires a `sourcechange` event whenever the effective source changes structurally, whether you set `source` directly or assign a new `src`. Setting an equivalent source, such as a fresh object with the same values on a React re-render, doesn't re-fire it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Borderline too jargony for me. Take a jargon pass at all your guides according to writing-style.md

- Use DocsLinkCard description prop for card supporting text instead of
  cramming title and body into the slot
- Reframe MuxVideo src vs source: source preferred in React, src an
  escape hatch; keep them as peers in HTML
- Plainer language for the sourcechange note and accessibility status
  announcer copy
- Apply writing-style dash guidance: colons/commas for lists and
  examples, keep em-dashes where warranted
- Verbatim reviewer-suggested lines for the cast/mux-data cards and the
  MuxData reference intro

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012cpFELzH6kxpPnG95VirsA

@decepulis decepulis left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one last change

Comment on lines +28 to +73
## Load a source

MuxVideo takes Mux content two ways: a structured `source` object, or a stream URL through `src`.

<FrameworkCase frameworks={["react"]}>
Prefer `source`. It's typed, so you get autocomplete and type checking on the playback ID and playback params, and MuxVideo builds the URL for you. Reach for `src` as an escape hatch when you already have a Mux HLS URL as a string.
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
`src` and `source` are peers. Use `src` when you have a Mux HLS URL, or `source` to build one from its parts.
</FrameworkCase>

`src` takes a Mux HLS URL. MuxVideo parses the playback ID and query params out of it into `source`; a non-Mux URL passes through unchanged.

<FrameworkCase frameworks={["react"]}>
```tsx
<MuxVideo src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" />
```
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
```html
<mux-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"></mux-video>
```
</FrameworkCase>

`source` builds the URL for you from a playback ID, an optional custom domain, and typed `playback` params (serialized to `snake_case` query params). Setting `source` derives `src`; setting `src` re-derives `source`. It's an object, so in HTML it's a property with no matching attribute.

<FrameworkCase frameworks={["react"]}>
```tsx
<MuxVideo source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM', playback: { maxResolution: '1080p' } }} />
```
</FrameworkCase>

<FrameworkCase frameworks={["html"]}>
```ts
const video = document.querySelector('mux-video');
video.source = {
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
customDomain: 'media.example.com',
playback: { maxResolution: '1080p' },
};
```
</FrameworkCase>

MuxVideo fires a `sourcechange` event when the source actually changes, whether you set `source` directly or assign a new `src`. Setting the same values again, like a fresh object on a React re-render, doesn't fire it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Github isn't the best IDE, so I might've made a mistake, but, here. Let me just write this for you the way I'd write it.

Suggested change
## Load a source
MuxVideo takes Mux content two ways: a structured `source` object, or a stream URL through `src`.
<FrameworkCase frameworks={["react"]}>
Prefer `source`. It's typed, so you get autocomplete and type checking on the playback ID and playback params, and MuxVideo builds the URL for you. Reach for `src` as an escape hatch when you already have a Mux HLS URL as a string.
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
`src` and `source` are peers. Use `src` when you have a Mux HLS URL, or `source` to build one from its parts.
</FrameworkCase>
`src` takes a Mux HLS URL. MuxVideo parses the playback ID and query params out of it into `source`; a non-Mux URL passes through unchanged.
<FrameworkCase frameworks={["react"]}>
```tsx
<MuxVideo src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" />
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```html
<mux-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"></mux-video>
```
</FrameworkCase>
`source` builds the URL for you from a playback ID, an optional custom domain, and typed `playback` params (serialized to `snake_case` query params). Setting `source` derives `src`; setting `src` re-derives `source`. It's an object, so in HTML it's a property with no matching attribute.
<FrameworkCase frameworks={["react"]}>
```tsx
<MuxVideo source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM', playback: { maxResolution: '1080p' } }} />
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```ts
const video = document.querySelector('mux-video');
video.source = {
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
customDomain: 'media.example.com',
playback: { maxResolution: '1080p' },
};
```
</FrameworkCase>
MuxVideo fires a `sourcechange` event when the source actually changes, whether you set `source` directly or assign a new `src`. Setting the same values again, like a fresh object on a React re-render, doesn't fire it.
## Load a source
<FrameworkCase frameworks={["react"]}>
The `source` param builds the URL for you from a playback ID, an optional custom domain, and `playback` params. Playback params are just camelCased [Mux playback query params](https://www.mux.com/docs/api-reference/stream/streaming/get-hls-manifest); for example, `max_resolution` becomes `maxResolution`.
```tsx
<MuxVideo
source={{
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
customDomain: 'media.example.com',
playback: { maxResolution: '1080p' }
}}
/>
```
If for some reason you need a bit more control, you can use the `src` param with a plain 'ol URL, too:
```tsx
<MuxVideo
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
/>
```
MuxVideo fires a `sourcechange` event when the source actually changes. Setting the same values again, like a fresh object on a React re-render, doesn't fire it.
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
MuxVideo takes Mux content two ways: a stream URL through `src`, or a structured `source` object.
```html
<mux-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"></mux-video>
```
The `source` object builds the URL for you from a playback ID, an optional custom domain, and `playback` params. Playback params are just camelCased [Mux playback query params](https://www.mux.com/docs/api-reference/stream/streaming/get-hls-manifest); for example, `max_resolution` becomes `maxResolution`.
```ts
const video = document.querySelector('mux-video');
video.source = {
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
customDomain: 'media.example.com',
playback: { maxResolution: '1080p' },
};
```
MuxVideo fires a `sourcechange` event when the source actually changes. Setting the same values again doesn't fire it.
</FrameworkCase>

Apply reviewer suggestion to split source/src guidance per framework,
leading with source in React and treating src/source as peers in HTML.
@decepulis
decepulis merged commit 72936af into main Jul 31, 2026
27 checks passed
@decepulis
decepulis deleted the claude/mux-data-cast-api-refs branch July 31, 2026 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants