Add a poster placeholder
Show a lightweight placeholder while the poster image loads
To show something while your video’s poster loads, customize the image drawn by the skin or the Poster component.
The examples keep the placeholder aligned with the poster position. Change contain to cover if your poster fills its container.
Use a framework image component
Many frameworks have image components that render both an image and a placeholder while it loads. Pass one to renderPoster; it receives src from Video.js when the media provides a poster.
import NextImage from 'next/image';
import type { ComponentProps } from 'react';
import { MuxVideo } from '@videojs/react/media/mux-video';
import { VideoPlayer, VideoSkin } from '@videojs/react/video';
export function MyPlayer() {
return (
<VideoPlayer>
<VideoSkin
renderPoster={({ src, ...props }: ComponentProps<'img'>) =>
src ? (
<NextImage
{...props}
src={src}
alt=""
fill
placeholder="blur"
blurDataURL="data:image/webp;base64,…"
/>
) : null
}
>
<MuxVideo
source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }}
playsInline
/>
</VideoSkin>
</VideoPlayer>
);
}Next.js generates blur data for static imports. Because this poster URL arrives at runtime, pass blurDataURL yourself.
Use a plain image
A background image on the poster works well for a lightweight placeholder:
import { MuxVideo } from '@videojs/react/media/mux-video';
import { VideoPlayer, VideoSkin } from '@videojs/react/video';
export function MyPlayer() {
return (
<VideoPlayer>
<VideoSkin
renderPoster={(props) => (
<img
{...props}
style={{
...props.style,
background:
"url('data:image/webp;base64,…') var(--media-object-position, center) / contain no-repeat",
}}
/>
)}
>
<MuxVideo
source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }}
playsInline
/>
</VideoSkin>
</VideoPlayer>
);
}Use the Poster component
If you built your own UI, use the same render prop directly on Poster:
import { Container, Poster } from '@videojs/react';
import { MuxVideo } from '@videojs/react/media/mux-video';
import { VideoPlayer } from '@videojs/react/video';
export function MyPlayer() {
return (
<VideoPlayer>
<Container style={{ position: 'relative', aspectRatio: '16 / 9' }}>
<MuxVideo
source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }}
playsInline
/>
<Poster
render={(props) => (
<img
{...props}
style={{
...props.style,
position: 'absolute',
inset: 0,
width: '100%',
height: '100%',
background:
"url('data:image/webp;base64,…') var(--media-object-position, center) / contain no-repeat",
objectFit: 'contain',
}}
/>
)}
/>
</Container>
</VideoPlayer>
);
}Use a packaged skin
Put your image in the skin’s poster slot. If you leave off src, the poster component fills it from the player while your background shows underneath:
<video-player>
<video-skin>
<mux-video
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
playsinline
></mux-video>
<img
slot="poster"
alt=""
style="background: url('data:image/webp;base64,…') var(--media-object-position, center) / contain no-repeat"
>
</video-skin>
</video-player>Use an ejected skin
When you own the skin template, put the placeholder on its fallback poster image instead:
<media-poster>
<img
alt=""
style="background: url('data:image/webp;base64,…') var(--media-object-position, center) / contain no-repeat"
>
</media-poster>