From 310fb08da8859b23ed37e2c8f41c80ef93fe5de6 Mon Sep 17 00:00:00 2001 From: Saahil Date: Thu, 19 Dec 2024 19:02:50 -0500 Subject: [PATCH] feat: dice (part 1/2) --- scripts/remove_bg.ts | 57 ++++++++++++++++++++++++++++++++ scripts/remove_bg_from_splits.ts | 15 +++++++++ 2 files changed, 72 insertions(+) create mode 100644 scripts/remove_bg.ts create mode 100644 scripts/remove_bg_from_splits.ts diff --git a/scripts/remove_bg.ts b/scripts/remove_bg.ts new file mode 100644 index 0000000..ec81a1a --- /dev/null +++ b/scripts/remove_bg.ts @@ -0,0 +1,57 @@ +// convert video to frames +// remove bg from frames +// compile frames into video +// must have ffmpeg installed + +import canvas from "canvas"; +import { execSync } from "child_process"; +const { createCanvas, loadImage } = canvas +import fs, { existsSync, readdirSync } from "fs" +// rmrif frames and remake +execSync(`rm -rf assets/dice/frames`, { stdio: 'inherit' }) +execSync(`mkdir assets/dice/frames`, { stdio: 'inherit' }) +if(!process.env.VIDEO_FILE) process.env.VIDEO_FILE=`assets/dice/green_screen_dice.mp4` +if(!process.env.OUT_FILE) process.env.OUT_FILE=`assets/dice/no_green_screen_dice.mp4` +const removeGreenScreen = async (inputPath, outputPath) => { + const image = await loadImage(inputPath); + + const canvas = createCanvas(image.width, image.height); + const ctx = canvas.getContext('2d'); + + ctx.drawImage(image, 0, 0, image.width, image.height); + + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const data = imageData.data; + + for (let i = 0; i < data.length; i += 4) { + const red = data[i]; + const green = data[i + 1]; + const blue = data[i + 2]; + + if (green > 150 && red < 100 && blue < 100) { + data[i + 3] = 0; // Set alpha to 0 (transparent) + } + } + + ctx.putImageData(imageData, 0, 0); + + const buffer = canvas.toBuffer('image/png'); + fs.writeFileSync(outputPath, buffer); + + console.log(`Green screen removed and saved to ${outputPath}`); +}; +execSync(`ffmpeg -i ${process.env.VIDEO_FILE} assets/dice/frames/frame_%04d.png`, { stdio: 'inherit' }) +// Usage +let frames = readdirSync("assets/dice/frames"); +;(async () => { + for(const frame of frames){ + if(!existsSync(`assets/dice/frames/cleaned_${frame}`)){ + await removeGreenScreen(`assets/dice/frames/${frame}`, `assets/dice/frames/cleaned_${frame}`) + } else { + console.log(`Skipping ${frame}`) + } + } + console.log(`Compiling frames into video`) + execSync(`ffmpeg -framerate 30 -i assets/dice/frames/cleaned_frame_%04d.png -c:v libx264 -pix_fmt yuva420p ${process.env.OUT_FILE}`, { stdio: 'inherit' }) + console.log(`Done`) +})() \ No newline at end of file diff --git a/scripts/remove_bg_from_splits.ts b/scripts/remove_bg_from_splits.ts new file mode 100644 index 0000000..68e9d49 --- /dev/null +++ b/scripts/remove_bg_from_splits.ts @@ -0,0 +1,15 @@ +import { execSync } from "child_process" +import fs from "fs" + +const splittedVideos = fs.readdirSync("assets/dice/splits") + +for(const video of splittedVideos){ + console.log(`Removing bg from ${video}`) + const cmd = `ts-node scripts/remove_bg.ts` + console.log(cmd) + execSync (cmd, { stdio: 'inherit', env: { + ...process.env, + VIDEO_FILE: `assets/dice/splits/${video}`, + OUT_FILE: `assets/dice/splits/c/${video}` + } }) +} \ No newline at end of file