Media Validation
Media validation ensures that video and audio assets are compatible with the user's browser before rendering or processing begins. This prevents runtime errors and visual flickering in Remotion compositions.
Browser Decoding Compatibility
The canDecode() utility determines if the current browser environment supports the specific codecs and containers of a media file. This check should be performed before passing a source to <Video> or <Audio> components.
Usage with URLs
Use UrlSource to validate remote assets. This is particularly useful when working with user-provided links or external APIs.
import { Input, ALL_FORMATS, UrlSource } from "mediabunny";
/**
* Checks if a video URL is decodable by the current browser.
* Returns true if both video and audio tracks are supported.
*/
export const canDecode = async (src: string): Promise<boolean> => {
const input = new Input({
formats: ALL_FORMATS,
source: new UrlSource(src, {
getRetryDelay: () => null, // Disable retries for validation
}),
});
try {
// Validate container format
await input.getFormat();
// Check video track compatibility
const videoTrack = await input.getPrimaryVideoTrack();
if (videoTrack && !(await videoTrack.canDecode())) {
return false;
}
// Check audio track compatibility
const audioTrack = await input.getPrimaryAudioTrack();
if (audioTrack && !(await audioTrack.canDecode())) {
return false;
}
return true;
} catch (error) {
return false;
}
};
Usage with Blobs (File Uploads)
When handling local file selection or drag-and-drop actions, use BlobSource to validate the file before it is uploaded or processed.
import { Input, ALL_FORMATS, BlobSource } from "mediabunny";
export const canDecodeBlob = async (blob: Blob): Promise<boolean> => {
const input = new Input({
formats: ALL_FORMATS,
source: new BlobSource(blob),
});
const videoTrack = await input.getPrimaryVideoTrack();
return videoTrack ? await videoTrack.canDecode() : false;
};
Extracting Media Metadata
Retrieving the dimensions and duration of a video is essential for dynamically sizing compositions or setting the durationInFrames.
Retrieving Dimensions and Duration
Use mediabunny to inspect the video track properties. This allows you to match the Remotion composition size to the source material.
import { Input, ALL_FORMATS, UrlSource } from "mediabunny";
export const getMediaMetadata = async (src: string) => {
const input = new Input({
formats: ALL_FORMATS,
source: new UrlSource(src),
});
const [duration, videoTrack] = await Promise.all([
input.computeDuration(),
input.getPrimaryVideoTrack(),
]);
return {
durationInSeconds: duration,
width: videoTrack?.displayWidth ?? 0,
height: videoTrack?.displayHeight ?? 0,
};
};
Dynamic Composition Integration
Integrate validation and metadata extraction within the calculateMetadata function of a <Composition>. This ensures the composition properties are set correctly before the first frame renders.
import { CalculateMetadataFunction } from 'remotion';
const calculateMetadata: CalculateMetadataFunction<Props> = async ({ props }) => {
const meta = await getMediaMetadata(props.videoSrc);
return {
durationInFrames: Math.ceil(meta.durationInSeconds * 30),
width: meta.width || 1920,
height: meta.height || 1080,
};
};
Validation Error Handling
When validation fails, it is recommended to:
- Fallback to Placeholder: Provide a default visual (e.g., a "Codec Not Supported" message) instead of a broken
<Video>element. - User Feedback: Prompt the user to provide an H.264 MP4 file, which offers the highest compatibility across browsers.
- Prevent Render: If used in a server-side rendering pipeline, abort the render early to save compute resources.