/** * RenderableComposition - Composition for Client-Side Rendering * * This composition uses @remotion/media components which are required for CSR. * The standard remotion components (OffthreadVideo, Audio) are used in Player preview, * but CSR requires @remotion/media versions. * * Key difference from editor Composition: * - Uses Video/Audio from @remotion/media (CSR compatible) * - Gets design data from props instead of store * - No editing features */ import { AbsoluteFill, useCurrentFrame, Sequence, useVideoConfig } from "remotion"; import { Video as CSRVideo, Audio as CSRAudio } from "@remotion/media"; import type { IDesign, ITrackItem, IVideo, IAudio, IImage, IText } from "@designcombo/types"; import { Img } from "remotion"; interface RenderableCompositionProps { design: IDesign; } // CSR-compatible Video component const CSRVideoItem = ({ item, fps }: { item: IVideo; fps: number }) => { const { details } = item; const playbackRate = item.playbackRate || 1; return (
); }; // CSR-compatible Audio component const CSRAudioItem = ({ item, fps }: { item: IAudio; fps: number }) => { const { details } = item; const playbackRate = item.playbackRate || 1; return ( ); }; // CSR-compatible Image component const CSRImageItem = ({ item }: { item: IImage }) => { const { details } = item; return (
); }; // CSR-compatible Text component const CSRTextItem = ({ item }: { item: IText }) => { const { details } = item; return (
); }; /** * Render a single track item based on its type */ const renderItem = (item: ITrackItem, fps: number) => { switch (item.type) { case 'video': return ; case 'audio': return ; case 'image': return ; case 'text': return ; default: return null; } }; /** * RenderableComposition for CSR (renderMediaOnWeb) */ export const RenderableComposition: React.FC = ({ design }) => { const { width: renderWidth, height: renderHeight } = useVideoConfig(); // Output resolution const fps = 30; const trackItemIds = design.trackItemIds || []; const trackItemsMap = design.trackItemsMap || {}; // Calculate scale factor matches the output resolution const designWidth = design.size.width; const designHeight = design.size.height; // Determine scale based on width ratio (assuming aspect ratio is maintained) const scale = renderWidth / designWidth; return (
{trackItemIds.map((id) => { const item = trackItemsMap[id] as ITrackItem; if (!item) return null; const startFrame = Math.round((item.display.from / 1000) * fps); const durationFrames = Math.round(((item.display.to - item.display.from) / 1000) * fps); return ( {renderItem(item, fps)} ); })}
); }; export default RenderableComposition;