import express from 'express'; import fs from 'fs'; import path from 'path'; import { bundle } from '@remotion/bundler'; import { renderMedia, selectComposition } from '@remotion/renderer'; const app = express(); app.use(express.json()); const OUTPUT_DIR = './out'; if (!fs.existsSync(OUTPUT_DIR)) fs.mkdirSync(OUTPUT_DIR); app.post('/render', async (req, res) => { try { const inputProps = req.body || {}; // pass your script from frontend const entryPoint = './remotion/src/index.tsx'; const bundled = await bundle({ entryPoint }); const composition = await selectComposition({ serveUrl: bundled, id: 'VideoComposition', // MUST MATCH your index.tsx Composition id inputProps, onBrowserDownload: (progress) => { console.log(`Chrome download progress: ${progress.percent.toFixed(2)}%`); }, }); console.log('=== SCENES TO RENDER ===', inputProps.script?.scenes || []); const outputPath = path.join(OUTPUT_DIR, `${composition.id}.mp4`); await renderMedia({ serveUrl: bundled, composition, outputLocation: outputPath, chromiumOptions: { enableMultiProcessOnLinux: true, args: ['--no-sandbox', '--disable-setuid-sandbox'], }, inputProps, }); res.download(outputPath); } catch (err) { console.error('Render error:', err); res.status(500).json({ error: err.message }); } }); app.listen(7860, () => console.log('🚀 Server running on port 7860'));