Loading snippets...
/*
* pixpunk-remove-bg
* Base: https://pixpunk.ai
* Sumber: https://whatsapp.com/channel/0029VbB4Kw8EFeXfeExaXc3Q
* Note: remove background image
* ESM | axios + form-data
*
* Usage:
* node pixpunk.js <url-atau-path> [output-path]
*/
import axios from 'axios';
import FormData from 'form-data';
import fs from 'fs';
import path from 'path';
import { Readable } from 'stream';
const API_URL = 'https://api.pixpunk.ai/api/remove-background';
const HEADERS = {
'Origin': 'https://pixpunk.ai',
'Referer': 'https://pixpunk.ai/',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0',
'Accept': 'application/json',
};
function guessContentType(filename) {
const map = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.webp': 'image/webp', '.gif': 'image/gif' };
return map[path.extname(filename).toLowerCase()] || 'image/jpeg';
}
function resolveOutputPath(inputName, outputPath) {
if (outputPath) return outputPath;
const base = path.basename(inputName, path.extname(inputName));
return `${base}_no_bg.png`;
}
async function fetchImageFromUrl(url) {
const res = await axios.get(url, { responseType: 'arraybuffer', headers: { 'User-Agent': HEADERS['User-Agent'] } });
const contentType = res.headers['content-type'] || 'image/jpeg';
const ext = contentType.split('/')[1]?.split(';')[0] || 'jpg';
const urlPath = new URL(url).pathname;
const basename = path.basename(urlPath) || `image.${ext}`;
const filename = basename.includes('.') ? basename : `${basename}.${ext}`;
return { buffer: Buffer.from(res.data), contentType, filename };
}
async function callApi(form) {
const res = await axios.post(API_URL, form, {
headers: { ...HEADERS, ...form.getHeaders() },
responseType: 'arraybuffer',
maxBodyLength: Infinity,
maxContentLength: Infinity,
});
if (res.status !== 200) throw new Error(`API error: ${res.status} ${res.statusText}`);
return Buffer.from(res.data);
}
async function removeBackground(input, outputPath = '') {
let resultBuffer, outPath;
if (/^https?:\/\//i.test(input)) {
const { buffer, contentType, filename } = await fetchImageFromUrl(input);
const form = new FormData();
form.append('image', Readable.from(buffer), { filename, contentType, knownLength: buffer.length });
resultBuffer = await callApi(form);
outPath = resolveOutputPath(filename, outputPath);
} else {
if (!fs.existsSync(input)) throw new Error(`File tidak ditemukan: ${input}`);
const filename = path.basename(input);
const form = new FormData();
form.append('image', fs.createReadStream(input), { filename, contentType: guessContentType(filename) });
resultBuffer = await callApi(form);
outPath = resolveOutputPath(input, outputPath);
}
const dir = path.dirname(outPath);
if (dir && dir !== '.' && !fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(outPath, resultBuffer);
console.log(JSON.stringify({
status: 'success',
input,
output: outPath,
size_bytes: resultBuffer.length,
}, null, 2));
return outPath;
}
// ── Run ─────────────────────────────────────────────────────
const [,, input, output] = process.argv;
if (!input) {
console.log(JSON.stringify({ status: 'error', message: 'Usage: node index.js <url-atau-path> [output-path]' }, null, 2));
process.exit(1);
}
removeBackground(input, output).catch(err => {
console.log(JSON.stringify({ status: 'error', message: err.message }, null, 2));
process.exit(1);
});