Registering Compositions in Remotion Root.tsx
Remotion requires all compositions to be registered in Root.tsx using the <Composition> component.
Manual Registration
// src/Root.tsx
import { Composition } from 'remotion';
import { Article6564191 } from './compositions/6564191';
import { Article6564192 } from './compositions/6564192';
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="Article6564191"
component={Article6564191}
durationInFrames={1446}
fps={30}
size={{ width: 1080, height: 1920 }}
/>
<Composition
id="Article6564192"
component={Article6564192}
durationInFrames={1200}
fps={30}
size={{ width: 1080, height: 1920 }}
/>
</>
);
};
Auto-Generation (Recommended)
Scan for all composition files and generate Root.tsx automatically:
import fs from 'fs';
import path from 'path';
interface ArticleMetadata {
id: string;
compositionPath: string;
durationInFrames: number;
}
function findAllCompositionFiles(): ArticleMetadata[] {
const compositionsDir = 'src/compositions';
const files = fs.readdirSync(compositionsDir);
return files
.filter(file => file.endsWith('.tsx'))
.map(file => {
const articleId = path.basename(file, '.tsx');
const filePath = path.join(compositionsDir, file);
const content = fs.readFileSync(filePath, 'utf-8');
// Extract duration from config export
const durationMatch = content.match(/durationInFrames:\s*(\d+)/);
const durationInFrames = durationMatch ? parseInt(durationMatch[1], 10) : 0;
return {
id: articleId,
compositionPath: `./compositions/${file}`,
durationInFrames,
};
});
}
Generate Root.tsx
export function generateRootFile(): void {
const articles = findAllCompositionFiles();
const imports = articles.map(a =>
`import { Article${a.id} } from './compositions/${a.id}';`
).join('\n');
const compositions = articles.map(a =>
` <Composition
id="Article${a.id}"
component={Article${a.id}}
durationInFrames={a.durationInFrames}
fps={30}
size={{ width: 1080, height: 1920 }}
/>`
).join('\n');
const rootContent = `
import { Composition } from 'remotion';
${imports}
export const RemotionRoot: React.FC = () => {
return (
<>
${compositions}
</>
);
};
`;
fs.writeFileSync('src/Root.tsx', rootContent);
}
Complete Root Generator
export class RootGenerator {
generateRoot(articles: Array<{ id: string; durationInFrames: number }>): void {
const imports = articles.map(article =>
`import { Article${article.id} } from './compositions/${article.id}';`
).join('\n');
const compositions = articles.map(article =>
` <Composition
id="Article${article.id}"
component={Article${article.id}}
durationInFrames={article.durationInFrames}
fps={30}
size={{ width: 1080, height: 1920 }}
/>`
).join('\n');
const content = `
import { Composition } from 'remotion';
${imports}
export const RemotionRoot: React.FC = () => {
return (
<>
${compositions}
</>
);
};
`;
fs.writeFileSync('src/Root.tsx', content);
}
}
Usage
const rootGenerator = new RootGenerator();
// After generating a new composition
rootGenerator.generateRoot([
{ id: '6564191', durationInFrames: 1446 },
{ id: '6564192', durationInFrames: 1200 },
// ... all articles with compositions
]);
Video Format
Standard configuration for vertical video (YouTube Shorts):
{
fps: 30,
size: { width: 1080, height: 1920 }, // 9:16 aspect ratio
}