mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(videos): add render-all script for dual-format batch rendering
This commit is contained in:
@@ -1,49 +1,93 @@
|
||||
import { bundle } from "@remotion/bundler";
|
||||
import { renderMedia, selectComposition } from "@remotion/renderer";
|
||||
import { renderMedia, renderStill, selectComposition } from "@remotion/renderer";
|
||||
import { enableTailwind } from "@remotion/tailwind";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const COMPOSITIONS = [
|
||||
{ id: "XLaunchVideo", slug: "x-launch" },
|
||||
{ id: "ProductDemo", slug: "product-demo" },
|
||||
{ id: "PromoTeaser", slug: "promo-teaser-square" },
|
||||
{ id: "PromoTeaserVertical", slug: "promo-teaser-vertical" },
|
||||
{ id: "PrivacyPromise", slug: "privacy-promise", posterFrame: 140 },
|
||||
{ id: "ToolGalaxy", slug: "tool-galaxy", posterFrame: 450 },
|
||||
{ id: "OneCommand", slug: "one-command", posterFrame: 300 },
|
||||
{ id: "AiMagicReel", slug: "ai-magic-reel", posterFrame: 190 },
|
||||
{ id: "FormatUniverse", slug: "format-universe", posterFrame: 90 },
|
||||
{ id: "PipelineFlow", slug: "pipeline-flow", posterFrame: 260 },
|
||||
{ id: "FloatingTools", slug: "floating-tools", posterFrame: 60 },
|
||||
{ id: "BrandGradient", slug: "brand-gradient", posterFrame: 0 },
|
||||
{ id: "The48", slug: "the-48", posterFrame: 420 },
|
||||
{ id: "CloudVsLocal", slug: "cloud-vs-local", posterFrame: 380 },
|
||||
];
|
||||
|
||||
const OUTPUT_DIR = path.resolve("./out");
|
||||
const OUTPUT_DIR = path.resolve(__dirname, "../../landing/public/videos");
|
||||
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||
|
||||
console.log("Bundling...");
|
||||
console.log("Bundling Remotion project...");
|
||||
const bundleLocation = await bundle({
|
||||
entryPoint: "./src/index.ts",
|
||||
entryPoint: path.resolve(__dirname, "../src/index.ts"),
|
||||
webpackOverride: (config) => enableTailwind(config),
|
||||
});
|
||||
console.log("Bundle complete.\n");
|
||||
|
||||
for (const comp of COMPOSITIONS) {
|
||||
console.log(`Rendering ${comp.id}...`);
|
||||
const total = COMPOSITIONS.length;
|
||||
|
||||
for (let i = 0; i < total; i++) {
|
||||
const comp = COMPOSITIONS[i];
|
||||
console.log(`[${i + 1}/${total}] ${comp.id}`);
|
||||
|
||||
const composition = await selectComposition({
|
||||
serveUrl: bundleLocation,
|
||||
id: comp.id,
|
||||
});
|
||||
|
||||
// MP4 (H.264, CRF 22)
|
||||
console.log(" Rendering MP4 (H.264)...");
|
||||
await renderMedia({
|
||||
composition,
|
||||
serveUrl: bundleLocation,
|
||||
codec: "h264",
|
||||
crf: 20,
|
||||
crf: 22,
|
||||
pixelFormat: "yuv420p",
|
||||
imageFormat: "jpeg",
|
||||
concurrency: 4,
|
||||
outputLocation: path.join(OUTPUT_DIR, `${comp.slug}.mp4`),
|
||||
onProgress: ({ progress }) => {
|
||||
const pct = Math.round(progress * 100);
|
||||
if (pct % 10 === 0) process.stdout.write(`\r ${pct}%`);
|
||||
if (pct % 10 === 0) process.stdout.write(`\r MP4: ${pct}%`);
|
||||
},
|
||||
});
|
||||
console.log(`\r MP4: done`);
|
||||
|
||||
console.log(`\r Done: ${comp.slug}.mp4`);
|
||||
// WebM (VP9, CRF 31)
|
||||
console.log(" Rendering WebM (VP9)...");
|
||||
await renderMedia({
|
||||
composition,
|
||||
serveUrl: bundleLocation,
|
||||
codec: "vp9",
|
||||
crf: 31,
|
||||
imageFormat: "jpeg",
|
||||
concurrency: 4,
|
||||
outputLocation: path.join(OUTPUT_DIR, `${comp.slug}.webm`),
|
||||
onProgress: ({ progress }) => {
|
||||
const pct = Math.round(progress * 100);
|
||||
if (pct % 10 === 0) process.stdout.write(`\r WebM: ${pct}%`);
|
||||
},
|
||||
});
|
||||
console.log(`\r WebM: done`);
|
||||
|
||||
// Poster frame (WebP still)
|
||||
console.log(" Rendering poster frame...");
|
||||
await renderStill({
|
||||
composition,
|
||||
serveUrl: bundleLocation,
|
||||
frame: comp.posterFrame,
|
||||
imageFormat: "webp",
|
||||
output: path.join(OUTPUT_DIR, `${comp.slug}-poster.webp`),
|
||||
});
|
||||
console.log(" Poster: done\n");
|
||||
}
|
||||
|
||||
console.log(`\nAll ${COMPOSITIONS.length} videos rendered to ${OUTPUT_DIR}`);
|
||||
console.log(
|
||||
`All ${total} compositions rendered (MP4 + WebM + poster) to ${OUTPUT_DIR}`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user