Using Static Files in Remotion
Remotion provides the staticFile() function to reference assets stored in the public/ directory.
Directory Structure
project/
├── public/
│ ├── image1.png
│ ├── audio1.wav
│ └── assets/
│ └── background.jpg
├── src/
│ └── compositions/
│ └── MyComp.tsx
Basic Usage
import { staticFile } from 'remotion';
// Reference files in public/
const imagePath = staticFile('image1.png');
// Returns: /public/image1.png
const audioPath = staticFile('audio1.wav');
// Returns: /public/audio1.wav
In Components
import { staticFile } from 'remotion';
import { useCurrentFrame } from 'remotion';
export const MyComponent: React.FC = () => {
return (
<div>
<img src={staticFile('image1.png')} alt="Background" />
<audio src={staticFile('audio1.wav')} />
</div>
);
};
With UUID-Based Naming
const scene = {
imageUuid: 'a3b4c5d6e7f8',
audioUuid: '123456789abc',
};
export const SceneComponent: React.FC = () => {
return (
<>
<img src={staticFile(`${scene.imageUuid}.png`)} alt="" />
<audio src={staticFile(`${scene.audioUuid}.wav`)} />
</>
);
};
Subdirectories
// Files in public/assets/
const assetPath = staticFile('assets/background.jpg');
Dynamic Paths
function getAssetPath(uuid: string, type: 'image' | 'audio'): string {
const extension = type === 'image' ? 'png' : 'wav';
return staticFile(`${uuid}.${extension}`);
}
Type Safety
interface SceneAssets {
imageUuid: string;
audioUuid: string;
}
function useSceneAssets(assets: SceneAssets) {
return {
image: staticFile(`${assets.imageUuid}.png`),
audio: staticFile(`${assets.audioUuid}.wav`),
};
}
Asset Management Best Practices
Store Assets in public/
// ❌ Don't store in src/
import image from './assets/image.png';
// ✅ Use staticFile()
import { staticFile } from 'remotion';
const image = staticFile('image.png');
Use Consistent Naming
// UUID-based naming prevents conflicts
const assetId = generateShortUuid();
await saveImage(buffer, `public/${assetId}.png`);
Clean Up Unused Assets
// Track used assets
const usedAssets = new Set<string>();
function registerAsset(uuid: string) {
usedAssets.add(uuid);
}
// Periodically clean unused files
async function cleanupUnusedAssets() {
const files = await fs.promises.readdir('public');
for (const file of files) {
const uuid = file.split('.')[0];
if (!usedAssets.has(uuid)) {
await fs.promises.unlink(`public/${file}`);
}
}
}
Complete Example
import { AbsoluteFill, staticFile, useCurrentFrame } from 'remotion';
interface Scene {
sceneNumber: number;
imageUuid: string;
audioUuid: string;
durationInFrames: number;
}
export const Slide: React.FC<{ scene: Scene }> = ({ scene }) => {
const frame = useCurrentFrame();
const progress = frame / scene.durationInFrames;
return (
<AbsoluteFill style={{ backgroundColor: '#000' }}>
{/* Background Image */}
<img
src={staticFile(`${scene.imageUuid}.png`)}
alt=""
style={{
position: 'absolute',
width: '100%',
height: '100%',
objectFit: 'cover',
opacity: calculateOpacity(progress),
}}
/>
{/* Audio */}
<audio
src={staticFile(`${scene.audioUuid}.wav`)}
autoPlay
/>
</AbsoluteFill>
);
};
File Paths Resolution
| Input | Resolved To |
|---|---|
staticFile('image.png') |
/public/image.png |
staticFile('assets/bg.jpg') |
/public/assets/bg.jpg |
staticFile('../image.png') |
❌ Not allowed |
staticFile('/absolute/path') |
❌ Not allowed |
Rules:
- Paths must be relative to
public/ - No parent directory traversal (
../) - No absolute paths
- Forward slashes only (even on Windows)
Performance Tips
- Optimize images: Use PNG for quality, JPEG for photos
- Compress audio: Use appropriate bitrates (e.g., 128kbps for speech)
- Limit file sizes: Remotion loads entire file into memory
- Use consistent formats: All PNG or all JPEG for images
- Clean up: Remove unused assets to keep
public/manageable