A complete automation script to set up a Remotion-based video generation API server on Ubuntu. Generate professional videos programmatically with hardware acceleration support.
# Download and run the setup script
curl -o setup-remotion.sh https://gist.githubusercontent.com/your-script-url
# Or create the file locally
nano setup-remotion.sh
# (paste the script content)
# Make it executable and run
chmod +x setup-remotion.sh
./setup-remotion.sh- β Updates Ubuntu packages
- β Installs Node.js 18+
- β Installs FFmpeg for video processing
- β Installs build tools and dependencies
- β Configures firewall for port 3001
- β Creates complete Remotion project with animated particle effects
- β Installs all required dependencies (@remotion/cli, @remotion/renderer, etc.)
- β Sets up TypeScript configuration
- β Creates animated components with 150+ particles and visual effects
- β Express.js HTTP API wrapper around Remotion
- β RESTful endpoints for video generation
- β Job management and file download system
- β Systemd service for production deployment
- β Test render script to verify setup
- β cURL examples for API usage
- β Monitoring and debugging tools
- OS: Ubuntu 18.04+ (or compatible Linux distribution)
- CPU: 4+ cores recommended
- RAM: 8GB minimum, 16GB recommended
- Storage: 10GB free space
- Network: Internet connection for dependencies
- CPU: 8+ cores (AMD Ryzen 7/Intel i7 or better)
- RAM: 32GB for complex videos
- Hardware: Modern hardware with hardware video encoding support
- Storage: SSD for faster I/O operations
After installation, you'll have:
~/remotion-api-server/
βββ src/ # Remotion source files
β βββ HelloWorld/ # Video components
β β βββ Logo.tsx
β β βββ Title.tsx
β β βββ Subtitle.tsx
β βββ HelloWorld.tsx # Main video component with particle effects
β βββ Root.tsx # Composition configuration
β βββ index.ts # Entry point
βββ out/ # Rendered video output
βββ api-server.js # HTTP API server
βββ test-render.js # Test script
βββ curl-examples.sh # API usage examples
βββ package.json # Node.js dependencies
βββ tsconfig.json # TypeScript configuration
GET /healthReturns server status and bundle information.
GET /compositionsReturns available video templates.
POST /renderStarts a new video render job.
Request Body:
{
"compositionId": "HelloWorld",
"props": {
"titleText": "Your Custom Title",
"titleColor": "#FF6B6B",
"logoColor1": "#4ECDC4",
"logoColor2": "#45B7D1"
},
"codec": "h264",
"crf": 23,
"concurrency": 8
}GET /download/:filenameDownloads the rendered video file.
# Step 1: Check server health
curl -s http://your-server:3001/health
# Step 2: Start a render and capture response
RESPONSE=$(curl -s -X POST http://your-server:3001/render \
-H "Content-Type: application/json" \
-d '{
"compositionId": "HelloWorld",
"props": {
"titleText": "My Epic Video",
"titleColor": "#00FFFF",
"logoColor1": "#FF6B6B",
"logoColor2": "#4ECDC4"
},
"codec": "h264",
"crf": 23,
"concurrency": 4
}')
# Step 3: Extract filename from response
echo "$RESPONSE"
FILENAME=$(echo "$RESPONSE" | grep -o '"filename":"[^"]*"' | cut -d'"' -f4)
echo "Render started: $FILENAME"
# Step 4: Wait for render to complete (2-5 minutes)
echo "Waiting for render to complete..."
sleep 180
# Step 5: Download the video
curl -O http://your-server:3001/download/$FILENAME
ls -la *.mp4# Simple test with minimal props
curl -X POST http://your-server:3001/render \
-H "Content-Type: application/json" \
-d '{"compositionId":"HelloWorld","props":{"titleText":"Test Video"}}' \
-s | jq '.'# Epic cinematic render with orchestral music
curl -X POST http://your-server:3001/render \
-H "Content-Type: application/json" \
-d '{
"compositionId": "HelloWorld",
"props": {
"titleText": "CONSCIOUSNESS AWAKENS",
"titleColor": "#FFD700",
"logoColor1": "#FF6B35",
"logoColor2": "#F7931E"
},
"codec": "h264",
"crf": 12,
"concurrency": 8
}' | jq '.'
# Wait 3-5 minutes, then download using filename from response# Check if server is running and bundled
curl -s http://your-server:3001/health | jq '.'
# List available compositions
curl -s http://your-server:3001/compositions | jq '.'
# Test render with verbose output to see errors
curl -X POST http://your-server:3001/render \
-H "Content-Type: application/json" \
-d '{"compositionId":"HelloWorld"}' \
-v
# Check if file exists before downloading
curl -I http://your-server:3001/download/render_TIMESTAMP.mp4
# Server logs (if running as service)
sudo journalctl -u remotion-api -f#!/bin/bash
SERVER="http://your-server:3001"
echo "π Checking server..."
curl -s "$SERVER/health" | jq '.'
echo "π¬ Starting render..."
RESPONSE=$(curl -s -X POST "$SERVER/render" \
-H "Content-Type: application/json" \
-d '{
"compositionId": "HelloWorld",
"props": {
"titleText": "Amazing Video",
"titleColor": "#FF4081"
},
"crf": 18
}')
echo "$RESPONSE" | jq '.'
# Extract filename
FILENAME=$(echo "$RESPONSE" | jq -r '.filename')
if [ "$FILENAME" != "null" ]; then
echo "β³ Waiting for render: $FILENAME"
# Wait and check until file is ready
while true; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$SERVER/download/$FILENAME")
if [ "$HTTP_CODE" = "200" ]; then
echo "β
Render complete! Downloading..."
curl -O "$SERVER/download/$FILENAME"
break
elif [ "$HTTP_CODE" = "404" ]; then
echo "β³ Still rendering..."
sleep 30
else
echo "β Error: HTTP $HTTP_CODE"
break
fi
done
else
echo "β Render failed"
ficd ~/remotion-api-server
# Start API server
npm run api
# Start Remotion Studio (preview)
npm run dev
# Test render locally
npm run test-render# Enable systemd service
sudo systemctl enable remotion-api
sudo systemctl start remotion-api
# Check service status
sudo systemctl status remotion-api
# View logs
sudo journalctl -u remotion-api -f- CRF 10-15: Highest quality, larger files
- CRF 18-23: Good quality, balanced size (recommended)
- CRF 28-35: Lower quality, smaller files
- Concurrency: Number of parallel render processes (usually CPU cores)
- Resolution: 1920x1080 (default), 3840x2160 (4K), etc.
- FPS: 30fps (default), 60fps for smooth motion
While Remotion is primarily CPU-bound, you can enable hardware video encoding:
// In api-server.js, add to renderMedia options:
ffmpegOverride: ({ args }) => [
...args.filter(arg => !arg.includes('libx264')),
'-c:v', 'h264_nvenc',
'-preset', 'fast'
]Port 3001 already in use:
sudo lsof -ti:3001 | xargs kill -9Node.js version too old:
# Update to Node.js 18+
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejsFFmpeg not found:
sudo apt update
sudo apt install ffmpeg -yPermission denied errors:
# Fix ownership
sudo chown -R $USER:$USER ~/remotion-api-serverSlow renders:
- Increase concurrency in render requests
- Use SSD storage for better I/O
- Add more RAM for complex compositions
- Monitor CPU usage during renders
High memory usage:
- Reduce concurrency if running out of RAM
- Close unnecessary applications
- Consider upgrading to 32GB+ RAM for heavy workloads
# Monitor hardware during renders
watch -n 1 nvidia-smi # For NVIDIA hardware
# or
watch -n 1 intel_gpu_top # For Intel hardware# Monitor CPU and memory
htop
# Monitor disk usage
df -h# Check render times
curl -s http://your-server:3001/health
# Monitor server logs
tail -f /var/log/syslog | grep remotion- Enable firewall and restrict access to port 3001
- Use reverse proxy (nginx) with SSL
- Implement API authentication
- Rate limit requests to prevent abuse
- Monitor disk usage (rendered videos can accumulate)
# Restrict access to specific IPs
sudo ufw allow from YOUR_IP to any port 3001
# Or use nginx reverse proxy with authentication- Deploy on multiple machines
- Use load balancer (nginx, HAProxy)
- Shared storage for video output (NFS, S3)
- Implement Redis/Bull queue for job management
- Handle multiple concurrent render requests
- Add retry logic for failed renders
// Generate video in your application
const response = await fetch('http://render-server:3001/render', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
compositionId: 'HelloWorld',
props: {
titleText: claudeGeneratedText,
titleColor: userBrandColor
}
})
});
const { filename } = await response.json();
// Handle download and upload to social platforms// Add webhook notifications to api-server.js
const webhookUrl = process.env.WEBHOOK_URL;
if (webhookUrl) {
await fetch(webhookUrl, {
method: 'POST',
body: JSON.stringify({
event: 'render_complete',
filename,
downloadUrl
})
});
}This setup script and configuration is provided as-is for educational and development purposes. Please ensure you comply with all relevant licenses for the included software:
- Remotion: Check their licensing terms
- FFmpeg: LGPL license
- Node.js: MIT license
For issues with this setup:
- Check the logs:
sudo journalctl -u remotion-api -f - Verify dependencies: Run
npm run test-render - System resources: Monitor CPU/RAM usage during renders
- Network connectivity: Ensure port 3001 is accessible
- Add custom compositions: Create your own video templates
- Integrate TTS: Add text-to-speech for voiceovers
- Audio support: Add background music and sound effects
- Advanced effects: Implement WebGL shaders for hardware acceleration
- Cloud deployment: Deploy to AWS/GCP with auto-scaling
Happy video rendering! π