Working with video
Learn how to handle video content in Sanity's Media Library.
Media Library's video streaming capabilities let you present high-quality, adaptive video content directly from your centralized asset storage. Videos uploaded to your Media Library are automatically processed and optimized for streaming through Mux, providing reliable video delivery with adaptive quality and global CDN distribution.
This guide explains how to effectively present videos from your Media Library in your front-end applications. For information about uploading videos or configuring Media Library, see the Media Library documentation.
Prerequisites
This is a paid feature
This feature is available on certain Enterprise plans. Talk to sales to learn more.
- A Sanity project with Media Library enabled and Studio v4.0.1 or later.
- Video addon enabled for your project. Video is an addon feature of Media Library and is not enabled by default. Contact sales to learn more.
- Video assets uploaded to your Media Library.
Understanding video representation in Media Library
Before implementing videos in your front-end, it's important to understand how Media Library handles videos:
- Video fields are created using the
defineVideoField
helper fromsanity/media-library
- Videos are processed to generate playback IDs for streaming
- Each video asset contains metadata, including aspect ratio, duration, and framerate
Note: Currently, only public videos are supported. Signed URLs for video are coming in a future release.
Supported formats and limitations
Media Library accepts most common video formats for upload:
Supported formats:
- MP4 (recommended)
- MOV
- AVI
- MKV
- WebM
- And most other standard video formats
Considerations:
- Processing time varies based on video length and resolution
- Higher resolution videos (4K+) may take longer to process
For best performance and compatibility, we recommend uploading videos in MP4 format with H.264 encoding. To minimize processing time, follow Mux's standard input specifications.
Video asset structure
Video assets in your Media Library have a nested structure:
{
"_id": "2yg9Un9RMsQjuf3WDqEo70ggi8D",
"_type": "sanity.asset",
"assetType": "sanity.videoAsset",
"title": "video-filename.mp4",
"versions": [
{
"instance": {
"_id": "2yg9UGEpG8H4xjgMj8YSstwpfVh",
"_type": "sanity.videoAsset",
"originalFilename": "video-filename.mp4",
"metadata": {
"_type": "sanity.videoMetadata",
"aspectRatio": 0.5625,
"duration": 8.86,
"playbacks": [
{
"_id": "V5uFaHghtnzgV6lYlBkrbehGkvd5KNGHYU7w2Eo7HoQ", // Mux playback ID
"_type": "sanity.videoMetadata.playback",
"policy": "public" // Only public videos are currently supported
}
]
},
"mimeType": "video/mp4",
"originalFilename": "video-filename.mp4"
}
}
]
}
Setting up video fields in Studio
Use the defineVideoField
helper to create video fields in your studio schemas:
import { defineVideoField } from 'sanity/media-library'
export default {
name: 'videoDocument',
title: 'Video Document',
type: 'document',
fields: [
defineVideoField({
title: 'Featured Video',
name: 'video',
}),
// ... other fields
]
}
Get the video data
The first step is to query for the video data you need to present the video. Here's how to query for the essential video information:
*[_type == 'videoDocument'] {
title,
"video": {
"playbackId": video.asset->metadata.playbacks[policy == "public"][0]._id,
"aspectRatio": video.asset->metadata.aspectRatio,
}
}
This returns:
{
"title": "My Video Document",
"video": {
"playbackId": "V5uFaHghtnzgV6lYlBkrbehGkvd5KNGHYU7w2Eo7HoQ",
"aspectRatio": 0.5625
}
}
For more comprehensive video information, you can query additional metadata:
*[_type == 'videoDocument'] {
title,
"video": {
"playbackId": video.asset->metadata.playbacks[policy == "public"][0]._id,
"aspectRatio": video.asset->metadata.aspectRatio,
"originalFilename": video.asset->originalFilename,
"duration": video.asset->metadata.duration,
"assetId": video.asset->_id
}
}
Display videos with Mux Player
To present videos from Media Library in your frontend, we'll use the Mux video player.
Install the Mux React player component:
pnpm install @mux/mux-player-react
Basic implementation
Here's the simplest way to display a video from your Media Library:
import MuxPlayer from '@mux/mux-player-react'
type VideoPlayerProps = {
playbackId: string
aspectRatio: number
}
export default function VideoPlayer({ playbackId, aspectRatio }: VideoPlayerProps) {
return (
<MuxPlayer
playbackId={playbackId}
style={{
width: '100%',
height: '100%',
aspectRatio: aspectRatio
}}
/>
)
}
Using with queried data
Integrate with your GROQ query results:
import MuxPlayer from '@mux/mux-player-react'
type VideoData = {
playbackId: string
aspectRatio: number
originalFilename: string
}
type DocumentWithVideoProps = {
video: VideoData
}
export default function DocumentWithVideo({ video }: DocumentWithVideoProps) {
if (!video?.playbackId) {
return <div>No video available</div>
}
return (
<div className="video-container">
<MuxPlayer
playbackId={video.playbackId}
style={{
width: '100%',
height: '100%',
aspectRatio: video.aspectRatio
}}
/>
</div>
)
}
Displaying thumbnails
Thumbnail images are automatically generated for your videos. You can use these as poster images:
import MuxPlayer from '@mux/mux-player-react'
export default function VideoWithPoster({ video }: { video: VideoData }) {
const posterUrl = `https://image.mux.com/${video.playbackId}/thumbnail.jpg`
return (
<MuxPlayer
playbackId={video.playbackId}
poster={posterUrl}
style={{
width: '100%',
height: '100%',
aspectRatio: video.aspectRatio
}}
/>
)
}
You can also customize the poster image size and format:
// Custom poster with specific dimensions
const posterUrl = `https://image.mux.com/${video.playbackId}/thumbnail.jpg?width=800&height=${Math.round(800 / video.aspectRatio)}&fit_mode=crop`
// Use WebP format for better compression
const optimizedPoster = `https://image.mux.com/${video.playbackId}/thumbnail.webp?width=800&fit_mode=preserve`
Understanding streaming and thumbnail URLs
Media Library provides video streaming and thumbnail generation through Mux. Understanding the URL structure helps you optimize video delivery:
Streaming URLs
Videos are delivered via HLS (HTTP Live Streaming) using this URL pattern:
https://stream.mux.com/{playbackId}.m3u8
The Mux Player handles this automatically, but you can access the raw streaming URL if needed:
const hlsUrl = `https://stream.mux.com/${video.playbackId}.m3u8`
Thumbnail URLs
Thumbnails are automatically generated using this URL pattern:
https://image.mux.com/{playbackId}/thumbnail.{format}
You can customize thumbnails with query parameters, similar to Sanity's image pipeline:
// Basic thumbnail
const thumbnail = `https://image.mux.com/${video.playbackId}/thumbnail.jpg`
// Specific size and format
const customThumb = `https://image.mux.com/${video.playbackId}/thumbnail.webp?width=400&height=300`
// Crop and fit options
const croppedThumb = `https://image.mux.com/${video.playbackId}/thumbnail.jpg?width=200&height=200&fit_mode=crop`
// Thumbnail from specific time (in seconds)
const timeThumb = `https://image.mux.com/${video.playbackId}/thumbnail.jpg?time=30`
Available thumbnail parameters:
width
andheight
- Resize the thumbnailfit_mode
- How to fit within dimensions (crop
,preserve
,stretch
,pad
)time
- Extract thumbnail from specific video timestamp (in seconds)- Format options:
.jpg
,.png
,.webp
For the complete list of thumbnail transformation options, see the Mux thumbnail documentation.
Advanced player configuration
Configure additional player features:
import MuxPlayer from '@mux/mux-player-react'
type AdvancedVideoProps = {
video: {
playbackId: string
aspectRatio: number
originalFilename: string
}
autoPlay?: boolean
muted?: boolean
onPlay?: () => void
onEnded?: () => void
}
export default function AdvancedVideo({
video,
autoPlay = false,
muted = false,
onPlay,
onEnded
}: AdvancedVideoProps) {
return (
<MuxPlayer
playbackId={video.playbackId}
autoPlay={autoPlay}
muted={muted}
loop={false}
preload="metadata"
style={{
width: '100%',
height: '100%',
aspectRatio: video.aspectRatio
}}
onPlay={onPlay}
onEnded={onEnded}
/>
)
}
Customizing player appearance
For styling and theming options, see the Mux Player customization guide. The player supports:
- Custom accent colors
- CSS custom properties for extensive styling
- Multiple built-in themes
- Custom CSS for complete control over appearance
Performance considerations
To maximize performance when displaying videos:
Use appropriate preload settings:
preload="none"
- Don't preload anything (best for pages with many videos)preload="metadata"
- Preload video metadata only (recommended default)preload="auto"
- Preload the entire video (use sparingly)
Common issues
Video not loading
- Check that the playback ID exists in your query:
video.asset->metadata.playbacks[policy == "public"][0]._id
- Ensure your Media Library integration is properly configured
- Verify the GROQ query is returning the expected data structure
Player not displaying
- Confirm
@mux/mux-player-react
is properly installed - Check browser console for JavaScript errors
- Verify the container element has appropriate dimensions
Aspect ratio issues
- Ensure you're using the correct aspect ratio from
video.asset->metadata.aspectRatio
- Note that aspect ratio is width/height (e.g., 0.5625 for 9:16 vertical video)
- Set proper container styles to maintain aspect ratio
Additional resources
Complete guide to Mux Player features and customization options.
Learn more about configuring and using Media Library.
Add custom metadata fields to your video assets.
Was this page helpful?