Asset Management
Overview of Asset Handling
Asset management in the Agent Board ecosystem relies on Remotion's specialized components. Unlike standard web development, video rendering requires that all assets—images, videos, audio, and fonts—are fully loaded and synchronized with the frame-by-frame rendering engine.
The Public Folder and staticFile()
All local assets should be placed in the public/ folder at the root of your project. To reference these files safely across different deployment environments (like S3 or subdirectories), you must use the staticFile() function.
import { Img, staticFile } from 'remotion';
export const MyComposition = () => {
return (
<div>
{/* logo.png must be in the public/ folder */}
<Img src={staticFile('logo.png')} />
</div>
);
};
Images and Videos
Agent Board utilizes Remotion's <Img /> and <Video /> components rather than standard HTML tags. These components ensure that the renderer waits for the asset to be ready before proceeding to the next frame.
Local vs. Remote Assets
- Local: Use
staticFile('filename.ext'). - Remote: Pass the URL string directly.
import { Img, Video } from 'remotion';
import { staticFile } from 'remotion';
const MyMedia = () => {
return (
<>
<Img src="https://example.com/remote-image.png" />
<Video src={staticFile('local-video.mp4')} />
</>
);
};
Typography and Fonts
Loading fonts correctly is critical to prevent "Flash of Unstyled Text" (FOUT) in your videos.
Google Fonts
The recommended approach is using the @remotion/google-fonts package. It is type-safe and automatically handles the loading state.
import { loadFont } from '@remotion/google-fonts/Inter';
const { fontFamily } = loadFont();
const MyText = () => {
return <div style={{ fontFamily }}>Hello World</div>;
};
Local Fonts
For custom brand fonts, use the FontFace API within your root component to ensure the font is registered before rendering begins.
import { staticFile } from 'remotion';
const fontFamily = new FontFace('BrandFont', `url(${staticFile('brand-font.woff2')})`);
await fontFamily.load();
document.fonts.add(fontFamily);
Lottie Animations
Lottie files allow for high-quality vector animations. When using Lottie in Agent Board, you must use the @remotion/lottie component to ensure the animation is synchronized with the Remotion timeline.
import { Lottie } from "@remotion/lottie";
import { staticFile } from "remotion";
import animationData from "../public/animation.json";
export const MyLottie = () => {
return <Lottie animationData={animationData} />;
};
3D Content (Three.js)
For 3D scenes, use @remotion/three. All 3D content must be wrapped in a <ThreeCanvas> and must follow the "Frame-Driven Animation" rule.
Key Requirements:
- Manual Animation: You cannot use
useFrame()from React Three Fiber. Instead, use Remotion'suseCurrentFrame(). - Lighting: Include ambient and directional lights within the canvas.
- Layout: If using
<Sequence>inside<ThreeCanvas>, set thelayoutprop to"none".
import { ThreeCanvas } from "@remotion/three";
import { useCurrentFrame, useVideoConfig } from "remotion";
const Scene = () => {
const frame = useCurrentFrame();
const rotationY = frame * 0.02;
return (
<mesh rotation={[0, rotationY, 0]}>
<boxGeometry args={[2, 2, 2]} />
<meshStandardMaterial color="blue" />
</mesh>
);
};
export const My3DComposition = () => {
const { width, height } = useVideoConfig();
return (
<ThreeCanvas width={width} height={height}>
<ambientLight intensity={0.5} />
<Scene />
</ThreeCanvas>
);
};
Asset Best Practices
- Avoid CSS Transitions: Never use CSS
transitionoranimationproperties. These run on the browser's clock, not the Remotion timeline, leading to skipped frames in the final render. - Pre-calculate Metadata: For dynamic videos (e.g., varying durations based on a video file), use the
calculateMetadatafunction in your<Composition />to fetch asset dimensions or durations before the render starts. - Clean Filenames: Avoid special characters in filenames within the
public/folder. WhilestaticFile()encodes them, simple alphanumeric names reduce the risk of pathing issues.