Unified rendering package for UGC Inc - shared types, components, and compositions for pixel-perfect client/server rendering
npm install ugcinc-renderUnified Remotion rendering package for UGC Inc. Provides shared types, components, and compositions for pixel-perfect client/server rendering using the same Chromium engine.
Traditional canvas-based rendering has a fundamental problem: different canvas implementations (browser Canvas API vs server-side libraries like skia-canvas) produce subtly different results. This leads to:
- Text positioned differently between preview and final render
- Font metrics varying between engines
- Antialiasing and rendering differences
This package solves that by using Remotion, which renders everything through Chromium. The same browser engine runs on both:
- Client preview: @remotion/player - React component for preview
- Server render: @remotion/renderer - Headless Chromium for final output
Result: 100% pixel-perfect consistency between preview and render.
``bash`
npm install @ugcinc/remotion remotion @remotion/player react
`tsx
import { Player } from '@remotion/player';
import { ImageEditorComposition, type ImageEditorConfig } from '@ugcinc/remotion';
function ImageEditorPreview({ config }: { config: ImageEditorConfig }) {
const sources = {
background: 'https://example.com/bg.jpg',
'image-1': 'https://example.com/image1.jpg',
};
return (
inputProps={{ config, sources }}
durationInFrames={1}
fps={1}
compositionWidth={config.width}
compositionHeight={config.height}
style={{ width: '100%', height: 'auto' }}
/>
);
}
`
`ts
import { bundle } from '@remotion/bundler';
import { renderStill } from '@remotion/renderer';
import { ImageEditorComposition } from '@ugcinc/remotion';
async function renderImage(config: ImageEditorConfig) {
const bundled = await bundle({
entryPoint: './remotion/index.ts',
});
const output = await renderStill({
composition: {
id: 'ImageEditor',
component: ImageEditorComposition,
width: config.width,
height: config.height,
fps: 1,
durationInFrames: 1,
defaultProps: { config, sources },
},
serveUrl: bundled,
output: 'output.png',
chromiumOptions: {
gl: 'angle', // GPU acceleration
},
});
return output;
}
`
All types are exported from the main package:
`ts
import type {
// Editor configs
ImageEditorConfig,
VideoEditorConfig,
EditorConfig,
Channel,
// Segments
TextSegment,
ImageSegment,
VideoSegment,
AudioSegment,
StaticSegment,
// Base types
TimeValue,
BorderRadiusConfig,
FitMode,
FontType,
FontWeight,
// Position types
RelativePositionConfigX,
RelativePositionConfigY,
// Crop types
DynamicCropConfig,
CropAxisConfig,
} from '@ugcinc/remotion';
`
Individual element components for building custom compositions:
`tsx
import { TextElement, ImageElement, VideoElement } from '@ugcinc/remotion/components';
// Text with all styling options
id: 'title',
type: 'text',
text: 'Hello World',
xOffset: 100,
yOffset: 100,
width: 800,
height: 200,
fontSize: 72,
fontType: 'tiktok',
fontWeight: 'bold',
color: '#ffffff',
strokeWidth: 4,
strokeColor: '#000000',
alignment: 'center',
verticalAlign: 'middle',
}}
/>
// Image with fit mode and border radius
id: 'photo',
type: 'image',
xOffset: 50,
yOffset: 50,
width: 400,
height: 400,
fit: 'cover',
borderRadius: 20,
rotation: 5,
}}
src="https://example.com/photo.jpg"
/>
`
Pre-built compositions for complete editor rendering:
Renders a static image from an ImageEditorConfig.
`tsx
import { ImageEditorComposition } from '@ugcinc/remotion/compositions';
sources={{
background: 'https://...',
'image-1': 'https://...',
}}
scale={2} // 2x resolution for retina
/>
`
Renders a video from a VideoEditorConfig with timeline support.
`tsx
import { VideoEditorComposition } from '@ugcinc/remotion/compositions';
sources={{
'video-1': 'https://...',
'audio-1': 'https://...',
}}
textContent={{
'text-1': 'Dynamic text content',
}}
/>
`
Helper functions for font loading and calculations:
`ts`
import {
preloadFonts,
areFontsLoaded,
getFontFamily,
calculateFitDimensions,
wrapText,
getBorderRadii,
} from '@ugcinc/remotion/utils';
React hooks for common operations:
`ts
import { useFontsLoaded, useImageLoader, useImagePreloader } from '@ugcinc/remotion/hooks';
function MyComponent() {
const fontsReady = useFontsLoaded();
const { loaded, images } = useImagePreloader(sources);
if (!fontsReady || !loaded) {
return
return
}
`
When rendering on a server with GPU, use the --gl=angle flag for faster frame rendering:
`ts``
await renderMedia({
// ...
chromiumOptions: {
gl: 'angle', // Enable GPU acceleration
},
});
MIT