Skip to content

Commit 439d96a

Browse files
authored
feat!: replace Mux player w/ Media Chrome + media (#303)
* feat: replace Mux player w/ Media Chrome + media * fix: slotted poster image * fix: upgrade pkgs * fix: add custom theme prop and example * fix: upgrade Media Chrome * fix: use Sutro as default * docs: add default player docs * fix: add hls-video, dash-video. src adapting types * fix: test fixture * docs: update readme * site: fix active link * docs: move change player theme to guides section * docs: make more clear it's on the Video comp * fix: use @mux/mux-video/react pkg
1 parent ed0ab4f commit 439d96a

21 files changed

+713
-235
lines changed

README.md

+72
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,22 @@ export default function Page() {
206206
```
207207
</details>
208208

209+
210+
### Change player theme ([Demo](https://next-video-demo.vercel.app/custom-theme))
211+
212+
You can change the player theme by passing the `theme` prop to the `<Video>` component.
213+
See [player.style](https://player.style/) for more themes.
214+
215+
```tsx
216+
import Video from 'next-video';
217+
import Instaplay from 'player.style/instaplay/react';
218+
import awesomeVideo from '/videos/awesome-video.mp4';
219+
220+
export default function Page() {
221+
return <Video src={awesomeVideo} theme={Instaplay} />;
222+
}
223+
```
224+
209225
### Player only ([Demo](https://next-video-demo.vercel.app/player-only))
210226

211227
Since [`v1.1.0`](https://github.com/muxinc/next-video/releases/tag/v1.1.0) you can import the player component directly and use it without any upload and processing features.
@@ -483,6 +499,62 @@ export { handler as default } from '@/next-video';
483499
```
484500

485501

502+
## Default Player
503+
504+
The default player is built with [Media Chrome](https://github.com/muxinc/media-chrome).
505+
506+
- The default theme is [Sutro](https://player.style/themes/sutro) by Mux.
507+
- The video engine changes automatically based on the source format:
508+
- Video files (like MP4, MP3, WEBM) that are progressively downloaded are played with the native `<video>` element.
509+
- Mux videos are played with [`<mux-video>`](https://github.com/muxinc/elements/tree/main/packages/mux-video).
510+
- HLS streams are played with [`<hls-video>`](https://github.com/muxinc/media-elements/tree/main/packages/hls-video-element).
511+
- DASH streams are played with [`<dash-video>`](https://github.com/muxinc/media-elements/tree/main/packages/dash-video-element).
512+
513+
### Props
514+
515+
The `<Video>` component accepts all the props of the `<video>` element and the following additional props:
516+
517+
- `src` (Asset | string): The video asset object (import) or source URL.
518+
- `poster` (StaticImageData | string): A placeholder image for the video. (Auto generated for Mux videos)
519+
- `blurDataURL` (string): A base64 image source URL that can be used as a placeholder. (Auto generated for Mux videos)
520+
- `theme` (React Component): The player theme component. See [player.style](https://player.style/) for more themes.
521+
- `as` (React Component): A custom player component. See [Custom player](#custom-player-demo).
522+
- `transform` (function): A custom function to transform the asset object (src and poster).
523+
- `loader` (function): A custom function used to resolve string based video URLs (not imports).
524+
525+
#### Mux video props
526+
527+
The `<Video>` component with a Mux video source accepts the following additional props:
528+
529+
- `startTime` (number): The start time of the video in seconds.
530+
- `streamType` ("on-demand" | "live"): The stream type of the video. Default is "on-demand".
531+
- `customDomain` (string): Assigns a custom domain to be used for Mux Video.
532+
- `beaconCollectionDomain` (string): Assigns a custom domain to be used for Mux Data collection. NOTE: Must be set before playbackId to apply to Mux Data monitoring.
533+
- `envKey` (string): This is the environment key for Mux Data. If you use Mux video this is automatically
534+
set for you. If you use a different provider you can set this to your own key.
535+
- `disableTracking` (boolean): Disables Mux data tracking of video playback.
536+
- `disableCookies` (boolean): Disables cookies used by Mux Data.
537+
- `preferPlayback` ("mse" | "native"): Specify if `<mux-video>` should try to use Media Source Extension or native playback (if available). If no value is provided, `<mux-video>` will choose based on what's deemed optimal for content and playback environment.
538+
- `maxResolution` ("720p" | "1080p" | "1440p" | "2160p"): Specify the maximum resolution you want delivered for this video.
539+
- `minResolution` ("480p" | "540p" | "720p" | "1080p" | "1440p" | "2160p"): Specify the minimum resolution you want delivered for this video.
540+
- `programStartTime` (number): Apply PDT-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the beginning of the media stream.
541+
- `programEndTime` (number): Apply PDT-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the end of the media stream.
542+
- `assetStartTime` (number): Apply media timeline-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the beginning of the media stream.
543+
- `assetEndTime` (number): Apply media timeline-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the end of the media stream.
544+
- `renditionOrder` (string): Change the order in which renditions are provided in the src playlist. Can impact initial segment loads. Currently only support "desc" for descending order.
545+
- `metadataVideoId` (string): This is an arbitrary ID sent to Mux Data that should map back to a record of this video in your database.
546+
- `metadataTitle` (string): This is an arbitrary title for your video that will be passed in as metadata into Mux Data. Adding a title will give you useful context in your Mux Data dashboard. (optional, but encouraged)
547+
- `metadataViewerUserId` (string): If you have a logged-in user, this should be an anonymized ID value that maps back to the user in your database that will be sent to Mux Data. Take care to not expose personal identifiable information like names, usernames or email addresses. (optional, but encouraged)
548+
- `metadata*` (string): This metadata* syntax can be used to pass any arbitrary Mux Data metadata fields.
549+
- `playbackToken` (string): The playback token for signing the `src` URL.
550+
- `thumbnailToken` (string): The token for signing the `poster` URL.
551+
- `storyboardToken` (string): The token for signing the storyboard URL.
552+
- `drmToken` (string): The token for signing DRM license and related URLs.
553+
- `targetLiveWindow` (number): An offset representing the seekable range for live content, where `Infinity` means the entire live content is seekable (aka "standard DVR"). Used along with `streamType` to determine what UI/controls to show.
554+
- `liveEdgeOffset` (number): The earliest playback time that will be treated as playing "at the live edge" for live content.
555+
- `debug` (boolean): Enables debug mode for the underlying playback engine (currently hls.js) and mux-embed, providing additional information in the console.
556+
557+
486558
## Required Permissions for Amazon S3
487559

488560
<details>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Metadata } from 'next';
2+
import Video from 'next-video';
3+
import Instaplay from 'player.style/instaplay/react';
4+
import getStarted from '/videos/get-started.mp4?thumbnailTime=0';
5+
6+
export const metadata: Metadata = {
7+
title: 'next-video - Custom theme',
8+
};
9+
10+
export default function Page() {
11+
return (
12+
<>
13+
<section>
14+
<Video src={getStarted} theme={Instaplay}>
15+
<track kind="captions" src="/get-started.vtt" srcLang="en" label="English" default />
16+
</Video>
17+
</section>
18+
</>
19+
);
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Metadata } from 'next';
2+
import Player from 'next-video/player';
3+
4+
export const metadata: Metadata = {
5+
title: 'next-video - DASH source',
6+
};
7+
8+
export default function Page() {
9+
return (
10+
<>
11+
<section>
12+
<Player
13+
style={{ display: 'grid', width: '100%', aspectRatio: '16/9' }}
14+
src="https://player.vimeo.com/external/648359100.mpd?s=a4419a2e2113cc24a87aef2f93ef69a8e4c8fb0c"
15+
/>
16+
</section>
17+
</>
18+
);
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Metadata } from 'next';
2+
import Player from 'next-video/player';
3+
4+
export const metadata: Metadata = {
5+
title: 'next-video - HLS source',
6+
};
7+
8+
export default function Page() {
9+
return (
10+
<>
11+
<section>
12+
<Player
13+
style={{ display: 'grid', width: '100%', aspectRatio: '16/9' }}
14+
src="https://stream.mux.com/sxY31L6Opl02RWPpm3Gro9XTe7fRHBjs92x93kiB1vpc.m3u8"
15+
/>
16+
</section>
17+
</>
18+
);
19+
}

examples/default-provider/app/(default)/player-only/page.tsx examples/default-provider/app/(default)/mp4-source/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import { Metadata } from 'next';
22
import Player from 'next-video/player';
33

44
export const metadata: Metadata = {
5-
title: 'next-video - Player only',
5+
title: 'next-video - MP4 Source',
66
};
77

88
export default function Page() {
99
return (
1010
<>
1111
<section>
1212
<Player
13-
style={{ display: 'grid', width: '100%', aspectRatio: '16/9' }}
13+
style={{ width: '100%', aspectRatio: '16/9' }}
1414
src="https://storage.googleapis.com/muxdemofiles/mux.mp4"
1515
poster="https://image.mux.com/jxEf6XiJs6JY017pSzpv8Hd6tTbdAOecHTq4FiFAn564/thumbnail.webp"
1616
blurDataURL='data:image/webp;base64,UklGRlAAAABXRUJQVlA4IEQAAACwAQCdASoQAAkAAQAcJZwAAueBHFYwAP7+sPJ01xp5AM+XuhDsRQ67ZYXXhHDkrqsIkUGjQSCMuENc5y3Qg0o9pZgAAA=='

examples/default-provider/app/(default)/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Metadata } from 'next';
22
import Video from 'next-video';
3-
import getStarted from '/videos/get-started.mp4?thumbnailTime=35';
3+
import getStarted from '/videos/get-started.mp4?thumbnailTime=37';
44

55
export const metadata: Metadata = {
66
title: 'next-video - Basic example',

examples/default-provider/app/globals.css

+16-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ aside nav li {
158158
}
159159

160160
aside nav a {
161-
display: flex;
161+
display: grid;
162+
grid-template-columns: 1.15rem auto auto;
162163
align-items: center;
163164
padding: .375rem var(--size-4) .375rem .75rem;
164165
margin: 0;
@@ -191,6 +192,20 @@ aside nav a.active::before {
191192
background-color: var(--text-1);
192193
}
193194

195+
aside nav a span {
196+
justify-self: end;
197+
background: var(--yellow-0);
198+
border: 1px solid var(--choco-1);
199+
color: var(--choco-4);
200+
font-family: var(--font-mono);
201+
text-transform: uppercase;
202+
font-size: .6em;
203+
margin-left: 7px;
204+
padding: .25em .7em;
205+
white-space: nowrap;
206+
word-spacing: -2px;
207+
}
208+
194209
.theme-toggle {
195210
transition: none;
196211
box-shadow: none;

examples/default-provider/app/sidebar-nav.tsx

+11-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export default function SidebarNav() {
1414
<li>
1515
<Link className={`link ${pathname === '/background-video' ? 'active' : ''}`} href="/background-video">Background video</Link>
1616
</li>
17+
<li>
18+
<Link className={`link ${pathname === '/custom-theme' ? 'active' : ''}`} href="/custom-theme">Custom theme</Link>
19+
</li>
1720
<li>
1821
<Link className={`link ${pathname === '/custom-player' ? 'active' : ''}`} href="/custom-player">Custom player</Link>
1922
</li>
@@ -24,10 +27,16 @@ export default function SidebarNav() {
2427
<Link className={`link ${pathname === '/string-source' ? 'active' : ''}`} href="/string-source">String video source</Link>
2528
</li>
2629
<li>
27-
<Link className={`link ${pathname === '/player-only' ? 'active' : ''}`} href="/player-only">Player only</Link>
30+
<Link className={`link ${pathname === '/hls-source' ? 'active' : ''}`} href="/hls-source">HLS source<span>player only</span></Link>
31+
</li>
32+
<li>
33+
<Link className={`link ${pathname === '/dash-source' ? 'active' : ''}`} href="/dash-source">DASH source<span>player only</span></Link>
34+
</li>
35+
<li>
36+
<Link className={`link ${pathname === '/mp4-source' ? 'active' : ''}`} href="/mp4-source">MP4 source<span>player only</span></Link>
2837
</li>
2938
<li>
30-
<Link className={`link ${pathname === '/source-tag' ? 'active' : ''}`} href="/source-tag">Source tag</Link>
39+
<Link className={`link ${pathname === '/source-tag' ? 'active' : ''}`} href="/source-tag">Source tag<span>player only</span></Link>
3140
</li>
3241
</ul>
3342
</nav>

0 commit comments

Comments
 (0)