@xuda.io/account_module 1.2.272 → 1.2.274
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/download_model.js +56 -0
- package/index.mjs +114 -42
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// download-models.js
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const models = ['u2net.onnx', 'u2net.onnx.bin', 'u2net.onnx.wasm'];
|
|
7
|
+
|
|
8
|
+
const baseUrl = 'https://static.imgly.com/background-removal/models/medium/';
|
|
9
|
+
const outputDir = '/var/xuda/assets/imgly-bg';
|
|
10
|
+
|
|
11
|
+
// Create directory if it doesn't exist
|
|
12
|
+
if (!fs.existsSync(outputDir)) {
|
|
13
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function downloadFile(url, filepath) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const file = fs.createWriteStream(filepath);
|
|
19
|
+
https
|
|
20
|
+
.get(url, (response) => {
|
|
21
|
+
if (response.statusCode === 200) {
|
|
22
|
+
response.pipe(file);
|
|
23
|
+
file.on('finish', () => {
|
|
24
|
+
file.close();
|
|
25
|
+
console.log(`Downloaded: ${path.basename(filepath)}`);
|
|
26
|
+
resolve();
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
reject(new Error(`HTTP ${response.statusCode}: ${url}`));
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
.on('error', (err) => {
|
|
33
|
+
fs.unlink(filepath, () => {}); // Delete partial file
|
|
34
|
+
reject(err);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function downloadAll() {
|
|
40
|
+
console.log('Downloading models to:', outputDir);
|
|
41
|
+
|
|
42
|
+
for (const model of models) {
|
|
43
|
+
const url = baseUrl + model;
|
|
44
|
+
const filepath = path.join(outputDir, model);
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
await downloadFile(url, filepath);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error(`Failed to download ${model}:`, error.message);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log('Download complete!');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
downloadAll();
|
package/index.mjs
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import _ from 'lodash';
|
|
3
|
-
import { removeBackground } from '@imgly/background-removal-node';
|
|
3
|
+
// import { removeBackground } from '@imgly/background-removal-node';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
|
|
6
|
+
import os from 'os';
|
|
7
|
+
import { exec } from 'child_process';
|
|
8
|
+
import util from 'util';
|
|
9
|
+
|
|
10
|
+
// Convert exec to a promise for cleaner async/await usage
|
|
11
|
+
const execAsync = util.promisify(exec);
|
|
12
|
+
|
|
6
13
|
global._conf = (
|
|
7
14
|
await import(path.join(process.env.XUDA_HOME, process.env.XUDA_CONFIG), {
|
|
8
15
|
with: { type: 'json' },
|
|
@@ -1554,61 +1561,126 @@ export const get_user_name = async function (uid) {
|
|
|
1554
1561
|
}
|
|
1555
1562
|
};
|
|
1556
1563
|
|
|
1557
|
-
const removeBg = async function (req, job_id, headers) {
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1564
|
+
// const removeBg = async function (req, job_id, headers) {
|
|
1565
|
+
// // const ASSET_PATH = path.join(process.cwd(), 'assets/imgly-bg');
|
|
1566
|
+
// // const config = {
|
|
1567
|
+
// // publicPath: `file://${ASSET_PATH}/`, // Points to your local folder
|
|
1568
|
+
// // debug: true, // Optional: Logs fetch attempts for debugging
|
|
1569
|
+
// // };
|
|
1563
1570
|
|
|
1564
|
-
|
|
1571
|
+
// const ASSET_PATH = '/var/xuda/assets/imgly-bg'; // <-- your folder
|
|
1565
1572
|
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1573
|
+
// const config = {
|
|
1574
|
+
// publicPath: `file://${ASSET_PATH}/`, // ← this fixes everything
|
|
1575
|
+
// debug: false,
|
|
1576
|
+
// model: 'medium', // or "small" if you want faster/smaller
|
|
1577
|
+
// };
|
|
1578
|
+
// debugger;
|
|
1579
|
+
// const drive_module = await import(`${module_path}/drive_module/index.mjs`);
|
|
1580
|
+
// const { url } = req;
|
|
1581
|
+
// try {
|
|
1582
|
+
// let imageBuffer;
|
|
1583
|
+
// // if (inputPath) {
|
|
1584
|
+
// // imageBuffer = fs.readFileSync(inputPath);
|
|
1585
|
+
// // }
|
|
1586
|
+
|
|
1587
|
+
// if (url) {
|
|
1588
|
+
// const res = await fetch(url);
|
|
1589
|
+
// if (!res.ok) {
|
|
1590
|
+
// throw new Error(`Failed to fetch image URL: ${res.status} ${res.statusText}`);
|
|
1591
|
+
// }
|
|
1592
|
+
// const arrayBuffer = await res.arrayBuffer();
|
|
1593
|
+
// imageBuffer = Buffer.from(arrayBuffer);
|
|
1594
|
+
// }
|
|
1595
|
+
// const blob = await removeBackground(imageBuffer, config);
|
|
1596
|
+
|
|
1597
|
+
// // Convert to buffer and save
|
|
1598
|
+
// const outputBuffer = Buffer.from(await blob.arrayBuffer());
|
|
1599
|
+
|
|
1600
|
+
// const originalname = 'avatar_' + path.basename(url);
|
|
1601
|
+
// const tempPath = path.join(os.tmpdir(), originalname + Date.now());
|
|
1602
|
+
// fs.writeFileSync(tempPath, outputBuffer);
|
|
1603
|
+
|
|
1604
|
+
// const ext = drive_module.getExtensionFromUrl(url);
|
|
1605
|
+
|
|
1606
|
+
// const file_obj = {
|
|
1607
|
+
// originalname,
|
|
1608
|
+
// path: tempPath,
|
|
1609
|
+
// mimetype: `image/${ext}`,
|
|
1610
|
+
// };
|
|
1611
|
+
|
|
1612
|
+
// const drive_ret = await drive_module.upload_drive_file_user({ uid, path: '/Profile Images' }, job_id, headers, file_obj);
|
|
1613
|
+
// console.log(`Background removed! `, drive_ret);
|
|
1614
|
+
// } catch (error) {
|
|
1615
|
+
// console.error('Error:', error);
|
|
1616
|
+
// }
|
|
1617
|
+
// };
|
|
1618
|
+
|
|
1619
|
+
const removeBg = async function (req, job_id, headers) {
|
|
1620
|
+
// 1. Load your drive module
|
|
1572
1621
|
const drive_module = await import(`${module_path}/drive_module/index.mjs`);
|
|
1622
|
+
|
|
1623
|
+
// 2. Extract UID (Assuming it's in req.user or req.uid based on your usage)
|
|
1624
|
+
const uid = req.user?.uid || req.uid || 'unknown_user';
|
|
1625
|
+
|
|
1573
1626
|
const { url } = req;
|
|
1627
|
+
|
|
1574
1628
|
try {
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
throw new Error(`Failed to fetch image URL: ${res.status} ${res.statusText}`);
|
|
1584
|
-
}
|
|
1585
|
-
const arrayBuffer = await res.arrayBuffer();
|
|
1586
|
-
imageBuffer = Buffer.from(arrayBuffer);
|
|
1629
|
+
if (!url) {
|
|
1630
|
+
throw new Error('No URL provided in request');
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
// 3. Download the image to a Buffer
|
|
1634
|
+
const res = await fetch(url);
|
|
1635
|
+
if (!res.ok) {
|
|
1636
|
+
throw new Error(`Failed to fetch image URL: ${res.status} ${res.statusText}`);
|
|
1587
1637
|
}
|
|
1588
|
-
const
|
|
1638
|
+
const arrayBuffer = await res.arrayBuffer();
|
|
1639
|
+
const imageBuffer = Buffer.from(arrayBuffer);
|
|
1640
|
+
|
|
1641
|
+
// 4. Create Temporary File Paths
|
|
1642
|
+
// rembg works with files, so we must save the buffer to disk first.
|
|
1643
|
+
const tempDir = os.tmpdir();
|
|
1644
|
+
const uniqueId = Date.now() + '_' + Math.random().toString(36).substring(7);
|
|
1589
1645
|
|
|
1590
|
-
|
|
1591
|
-
const
|
|
1646
|
+
const inputExt = path.extname(url) || '.jpg';
|
|
1647
|
+
const tempInputPath = path.join(tempDir, `input_${uniqueId}${inputExt}`);
|
|
1648
|
+
const tempOutputPath = path.join(tempDir, `output_${uniqueId}.png`); // Output is always PNG (transparent)
|
|
1592
1649
|
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
fs.writeFileSync(tempPath, outputBuffer);
|
|
1650
|
+
// 5. Write the downloaded image to disk
|
|
1651
|
+
fs.writeFileSync(tempInputPath, imageBuffer);
|
|
1596
1652
|
|
|
1597
|
-
|
|
1653
|
+
// 6. EXECUTE REMBG via CLI
|
|
1654
|
+
// "rembg i [input] [output]"
|
|
1655
|
+
console.log(`Processing with rembg: ${tempInputPath} -> ${tempOutputPath}`);
|
|
1656
|
+
await execAsync(`rembg i "${tempInputPath}" "${tempOutputPath}"`);
|
|
1657
|
+
|
|
1658
|
+
// 7. Prepare File Object for Drive Upload
|
|
1659
|
+
// Note: The output file now exists at tempOutputPath
|
|
1660
|
+
const originalname = 'avatar_' + path.basename(url, inputExt) + '.png';
|
|
1598
1661
|
|
|
1599
1662
|
const file_obj = {
|
|
1600
|
-
originalname,
|
|
1601
|
-
path:
|
|
1602
|
-
mimetype:
|
|
1663
|
+
originalname: originalname,
|
|
1664
|
+
path: tempOutputPath,
|
|
1665
|
+
mimetype: 'image/png', // rembg output is always PNG
|
|
1603
1666
|
};
|
|
1604
1667
|
|
|
1668
|
+
// 8. Upload to Drive
|
|
1605
1669
|
const drive_ret = await drive_module.upload_drive_file_user({ uid, path: '/Profile Images' }, job_id, headers, file_obj);
|
|
1606
|
-
|
|
1670
|
+
|
|
1671
|
+
console.log(`Background removed!`, drive_ret);
|
|
1672
|
+
|
|
1673
|
+
// 9. Clean up Input File (Output file might be needed by upload, so clean input only)
|
|
1674
|
+
try {
|
|
1675
|
+
fs.unlinkSync(tempInputPath);
|
|
1676
|
+
// Optional: fs.unlinkSync(tempOutputPath); // Only if upload_drive_file_user handles the file reading fully
|
|
1677
|
+
} catch (cleanupErr) {
|
|
1678
|
+
console.warn('Warning: Failed to cleanup temp input file', cleanupErr);
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
return drive_ret;
|
|
1607
1682
|
} catch (error) {
|
|
1608
|
-
console.error('Error:', error);
|
|
1683
|
+
console.error('Error processing background removal:', error);
|
|
1684
|
+
throw error;
|
|
1609
1685
|
}
|
|
1610
1686
|
};
|
|
1611
|
-
|
|
1612
|
-
// Step 1: Create a local assets folder (e.g., in your project root)
|
|
1613
|
-
const ASSET_PATH = path.join(process.cwd(), 'assets/imgly-bg'); // e.g., ./assets/imgly-bg
|
|
1614
|
-
fs.mkdirSync(ASSET_PATH, { recursive: true });
|