MogensR commited on
Commit
e6e3409
Β·
1 Parent(s): a545b7d

Create examples/javascript/node/basic_usage.js

Browse files
examples/javascript/node/basic_usage.js ADDED
@@ -0,0 +1,499 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * BackgroundFX Pro - Node.js Usage Examples
5
+ *
6
+ * This script demonstrates how to use the BackgroundFX Pro API with Node.js
7
+ * including file uploads, async processing, and WebSocket connections.
8
+ */
9
+
10
+ const axios = require('axios');
11
+ const FormData = require('form-data');
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const WebSocket = require('ws');
15
+
16
+ // Configuration
17
+ const API_BASE_URL = process.env.BACKGROUNDFX_API_URL || 'https://api.backgroundfx.pro/v1';
18
+ const API_KEY = process.env.BACKGROUNDFX_API_KEY || 'your-api-key-here';
19
+ const WS_URL = process.env.BACKGROUNDFX_WS_URL || 'wss://ws.backgroundfx.pro';
20
+
21
+ /**
22
+ * BackgroundFX API Client
23
+ */
24
+ class BackgroundFXClient {
25
+ constructor(apiKey, baseUrl = API_BASE_URL) {
26
+ this.apiKey = apiKey;
27
+ this.baseUrl = baseUrl.replace(/\/$/, '');
28
+
29
+ // Configure axios instance
30
+ this.client = axios.create({
31
+ baseURL: this.baseUrl,
32
+ headers: {
33
+ 'Authorization': `Bearer ${apiKey}`,
34
+ 'User-Agent': 'BackgroundFX-Node-Client/1.0'
35
+ }
36
+ });
37
+ }
38
+
39
+ /**
40
+ * Remove background from an image
41
+ */
42
+ async removeBackground(imagePath, options = {}) {
43
+ const {
44
+ quality = 'high',
45
+ model = 'auto',
46
+ returnMask = false,
47
+ edgeRefinement = 50
48
+ } = options;
49
+
50
+ // Check if file exists
51
+ if (!fs.existsSync(imagePath)) {
52
+ throw new Error(`File not found: ${imagePath}`);
53
+ }
54
+
55
+ // Create form data
56
+ const formData = new FormData();
57
+ formData.append('file', fs.createReadStream(imagePath));
58
+ formData.append('quality', quality);
59
+ formData.append('model', model);
60
+ formData.append('return_mask', returnMask.toString());
61
+ formData.append('edge_refinement', edgeRefinement.toString());
62
+
63
+ try {
64
+ console.log(`πŸ”„ Processing image: ${path.basename(imagePath)}`);
65
+
66
+ const response = await this.client.post('/process/remove-background', formData, {
67
+ headers: formData.getHeaders(),
68
+ maxContentLength: Infinity,
69
+ maxBodyLength: Infinity
70
+ });
71
+
72
+ console.log('βœ… Background removed successfully!');
73
+ return response.data;
74
+ } catch (error) {
75
+ console.error('❌ Error processing image:', error.response?.data || error.message);
76
+ throw error;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Process multiple images in batch
82
+ */
83
+ async processBatch(imagePaths, options = {}) {
84
+ const formData = new FormData();
85
+
86
+ // Add all files
87
+ for (const imagePath of imagePaths) {
88
+ if (!fs.existsSync(imagePath)) {
89
+ console.warn(`⚠️ Skipping missing file: ${imagePath}`);
90
+ continue;
91
+ }
92
+ formData.append('files', fs.createReadStream(imagePath));
93
+ }
94
+
95
+ // Add options
96
+ formData.append('options', JSON.stringify(options));
97
+
98
+ try {
99
+ console.log(`πŸ”„ Processing batch of ${imagePaths.length} images...`);
100
+
101
+ const response = await this.client.post('/process/batch', formData, {
102
+ headers: formData.getHeaders()
103
+ });
104
+
105
+ const jobId = response.data.id;
106
+ console.log(`βœ… Batch job created: ${jobId}`);
107
+
108
+ // Monitor job progress
109
+ return await this.monitorJob(jobId);
110
+ } catch (error) {
111
+ console.error('❌ Batch processing failed:', error.message);
112
+ throw error;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Monitor batch job progress
118
+ */
119
+ async monitorJob(jobId, pollInterval = 2000) {
120
+ console.log(`πŸ“Š Monitoring job: ${jobId}`);
121
+
122
+ while (true) {
123
+ try {
124
+ const response = await this.client.get(`/process/jobs/${jobId}`);
125
+ const job = response.data;
126
+
127
+ console.log(` Status: ${job.status} | Progress: ${job.progress}%`);
128
+
129
+ if (job.status === 'completed') {
130
+ console.log('βœ… Job completed!');
131
+ return job;
132
+ } else if (job.status === 'failed') {
133
+ throw new Error(`Job failed: ${job.error}`);
134
+ }
135
+
136
+ // Wait before next poll
137
+ await new Promise(resolve => setTimeout(resolve, pollInterval));
138
+ } catch (error) {
139
+ console.error('❌ Error monitoring job:', error.message);
140
+ throw error;
141
+ }
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Replace background with color or image
147
+ */
148
+ async replaceBackground(imageId, background, blendMode = 'normal') {
149
+ try {
150
+ const response = await this.client.post('/process/replace-background', {
151
+ image_id: imageId,
152
+ background: background,
153
+ blend_mode: blendMode
154
+ });
155
+
156
+ console.log('βœ… Background replaced!');
157
+ return response.data;
158
+ } catch (error) {
159
+ console.error('❌ Error replacing background:', error.message);
160
+ throw error;
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Download result to file
166
+ */
167
+ async downloadResult(url, outputPath) {
168
+ const writer = fs.createWriteStream(outputPath);
169
+
170
+ const response = await axios({
171
+ url,
172
+ method: 'GET',
173
+ responseType: 'stream'
174
+ });
175
+
176
+ response.data.pipe(writer);
177
+
178
+ return new Promise((resolve, reject) => {
179
+ writer.on('finish', () => {
180
+ console.log(`πŸ’Ύ Saved to: ${outputPath}`);
181
+ resolve(outputPath);
182
+ });
183
+ writer.on('error', reject);
184
+ });
185
+ }
186
+
187
+ /**
188
+ * Connect to WebSocket for real-time updates
189
+ */
190
+ connectWebSocket(jobId) {
191
+ return new Promise((resolve, reject) => {
192
+ const ws = new WebSocket(`${WS_URL}?job_id=${jobId}`, {
193
+ headers: {
194
+ 'Authorization': `Bearer ${this.apiKey}`
195
+ }
196
+ });
197
+
198
+ ws.on('open', () => {
199
+ console.log('πŸ”Œ WebSocket connected');
200
+ ws.send(JSON.stringify({ action: 'subscribe', job_id: jobId }));
201
+ });
202
+
203
+ ws.on('message', (data) => {
204
+ const message = JSON.parse(data);
205
+ console.log('πŸ“¨ WebSocket message:', message);
206
+
207
+ if (message.type === 'job:complete') {
208
+ ws.close();
209
+ resolve(message.data);
210
+ } else if (message.type === 'job:error') {
211
+ ws.close();
212
+ reject(new Error(message.error));
213
+ } else if (message.type === 'job:progress') {
214
+ console.log(` Progress: ${message.progress}%`);
215
+ }
216
+ });
217
+
218
+ ws.on('error', (error) => {
219
+ console.error('❌ WebSocket error:', error);
220
+ reject(error);
221
+ });
222
+
223
+ ws.on('close', () => {
224
+ console.log('πŸ”Œ WebSocket disconnected');
225
+ });
226
+ });
227
+ }
228
+ }
229
+
230
+ // ============================================================================
231
+ // EXAMPLES
232
+ // ============================================================================
233
+
234
+ /**
235
+ * Example 1: Basic background removal
236
+ */
237
+ async function exampleBasicUsage() {
238
+ console.log('\n' + '='.repeat(60));
239
+ console.log('EXAMPLE 1: Basic Background Removal');
240
+ console.log('='.repeat(60));
241
+
242
+ const client = new BackgroundFXClient(API_KEY);
243
+
244
+ try {
245
+ // Process image
246
+ const result = await client.removeBackground('sample_images/portrait.jpg', {
247
+ quality: 'high'
248
+ });
249
+
250
+ // Download result
251
+ await client.downloadResult(
252
+ result.image,
253
+ 'output/portrait_no_bg.png'
254
+ );
255
+
256
+ console.log('✨ Basic processing complete!');
257
+ } catch (error) {
258
+ console.error('Failed:', error.message);
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Example 2: Batch processing with progress monitoring
264
+ */
265
+ async function exampleBatchProcessing() {
266
+ console.log('\n' + '='.repeat(60));
267
+ console.log('EXAMPLE 2: Batch Processing');
268
+ console.log('='.repeat(60));
269
+
270
+ const client = new BackgroundFXClient(API_KEY);
271
+
272
+ const images = [
273
+ 'sample_images/product1.jpg',
274
+ 'sample_images/product2.jpg',
275
+ 'sample_images/product3.jpg'
276
+ ];
277
+
278
+ try {
279
+ const job = await client.processBatch(images, {
280
+ quality: 'medium',
281
+ model: 'rembg'
282
+ });
283
+
284
+ // Download all results
285
+ for (const [index, result] of job.results.entries()) {
286
+ await client.downloadResult(
287
+ result.image,
288
+ `output/batch/product${index + 1}_no_bg.png`
289
+ );
290
+ }
291
+
292
+ console.log('✨ Batch processing complete!');
293
+ } catch (error) {
294
+ console.error('Failed:', error.message);
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Example 3: WebSocket real-time monitoring
300
+ */
301
+ async function exampleWebSocketMonitoring() {
302
+ console.log('\n' + '='.repeat(60));
303
+ console.log('EXAMPLE 3: WebSocket Real-time Monitoring');
304
+ console.log('='.repeat(60));
305
+
306
+ const client = new BackgroundFXClient(API_KEY);
307
+
308
+ try {
309
+ // Start batch job
310
+ const formData = new FormData();
311
+ formData.append('files', fs.createReadStream('sample_images/large1.jpg'));
312
+ formData.append('files', fs.createReadStream('sample_images/large2.jpg'));
313
+
314
+ const response = await client.client.post('/process/batch', formData, {
315
+ headers: formData.getHeaders()
316
+ });
317
+
318
+ const jobId = response.data.id;
319
+ console.log(`πŸ“‹ Job ID: ${jobId}`);
320
+
321
+ // Monitor via WebSocket
322
+ const result = await client.connectWebSocket(jobId);
323
+ console.log('✨ Processing complete via WebSocket!');
324
+
325
+ } catch (error) {
326
+ console.error('Failed:', error.message);
327
+ }
328
+ }
329
+
330
+ /**
331
+ * Example 4: Background replacement variations
332
+ */
333
+ async function exampleBackgroundReplacement() {
334
+ console.log('\n' + '='.repeat(60));
335
+ console.log('EXAMPLE 4: Background Replacement');
336
+ console.log('='.repeat(60));
337
+
338
+ const client = new BackgroundFXClient(API_KEY);
339
+
340
+ try {
341
+ // First remove background
342
+ const result = await client.removeBackground('sample_images/person.jpg');
343
+ const imageId = result.id;
344
+
345
+ // Try different backgrounds
346
+ const backgrounds = [
347
+ { type: 'color', value: '#3498db', name: 'blue' },
348
+ { type: 'gradient', value: 'linear-gradient(45deg, #ff6b6b, #4ecdc4)', name: 'gradient' },
349
+ { type: 'blur', value: 'blur:20', name: 'blurred' }
350
+ ];
351
+
352
+ for (const bg of backgrounds) {
353
+ console.log(`🎨 Applying ${bg.name} background...`);
354
+ const replaced = await client.replaceBackground(imageId, bg.value);
355
+ await client.downloadResult(
356
+ replaced.image,
357
+ `output/person_${bg.name}_bg.png`
358
+ );
359
+ }
360
+
361
+ console.log('✨ Background replacement complete!');
362
+ } catch (error) {
363
+ console.error('Failed:', error.message);
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Example 5: Error handling and retries
369
+ */
370
+ async function exampleErrorHandling() {
371
+ console.log('\n' + '='.repeat(60));
372
+ console.log('EXAMPLE 5: Error Handling');
373
+ console.log('='.repeat(60));
374
+
375
+ const client = new BackgroundFXClient(API_KEY);
376
+
377
+ // Retry logic
378
+ async function withRetry(fn, maxRetries = 3) {
379
+ for (let i = 0; i < maxRetries; i++) {
380
+ try {
381
+ return await fn();
382
+ } catch (error) {
383
+ console.log(`⚠️ Attempt ${i + 1} failed: ${error.message}`);
384
+ if (i === maxRetries - 1) throw error;
385
+
386
+ // Exponential backoff
387
+ const delay = Math.pow(2, i) * 1000;
388
+ console.log(`⏳ Waiting ${delay}ms before retry...`);
389
+ await new Promise(resolve => setTimeout(resolve, delay));
390
+ }
391
+ }
392
+ }
393
+
394
+ try {
395
+ const result = await withRetry(() =>
396
+ client.removeBackground('sample_images/test.jpg')
397
+ );
398
+ console.log('βœ… Success after retries');
399
+ } catch (error) {
400
+ console.error('❌ Failed after all retries:', error.message);
401
+ }
402
+ }
403
+
404
+ /**
405
+ * Example 6: Parallel processing
406
+ */
407
+ async function exampleParallelProcessing() {
408
+ console.log('\n' + '='.repeat(60));
409
+ console.log('EXAMPLE 6: Parallel Processing');
410
+ console.log('='.repeat(60));
411
+
412
+ const client = new BackgroundFXClient(API_KEY);
413
+
414
+ const images = [
415
+ 'sample_images/img1.jpg',
416
+ 'sample_images/img2.jpg',
417
+ 'sample_images/img3.jpg',
418
+ 'sample_images/img4.jpg'
419
+ ];
420
+
421
+ try {
422
+ console.log(`πŸš€ Processing ${images.length} images in parallel...`);
423
+ const startTime = Date.now();
424
+
425
+ // Process all images in parallel
426
+ const promises = images.map(imagePath =>
427
+ client.removeBackground(imagePath, { quality: 'medium' })
428
+ .catch(err => ({ error: err.message, path: imagePath }))
429
+ );
430
+
431
+ const results = await Promise.all(promises);
432
+
433
+ const elapsed = (Date.now() - startTime) / 1000;
434
+ console.log(`βœ… Processed ${results.length} images in ${elapsed.toFixed(2)}s`);
435
+
436
+ // Count successes and failures
437
+ const successes = results.filter(r => !r.error).length;
438
+ const failures = results.filter(r => r.error).length;
439
+
440
+ console.log(` Successes: ${successes}`);
441
+ console.log(` Failures: ${failures}`);
442
+
443
+ } catch (error) {
444
+ console.error('Failed:', error.message);
445
+ }
446
+ }
447
+
448
+ // ============================================================================
449
+ // MAIN
450
+ // ============================================================================
451
+
452
+ async function main() {
453
+ console.log('\n' + '#'.repeat(60));
454
+ console.log('# BackgroundFX Pro - Node.js Examples');
455
+ console.log('#'.repeat(60));
456
+
457
+ // Check API key
458
+ if (API_KEY === 'your-api-key-here') {
459
+ console.error('\n⚠️ Please set your API key in BACKGROUNDFX_API_KEY environment variable');
460
+ process.exit(1);
461
+ }
462
+
463
+ // Create output directories
464
+ const dirs = ['output', 'output/batch', 'sample_images'];
465
+ dirs.forEach(dir => {
466
+ if (!fs.existsSync(dir)) {
467
+ fs.mkdirSync(dir, { recursive: true });
468
+ }
469
+ });
470
+
471
+ // Run examples
472
+ const examples = [
473
+ exampleBasicUsage,
474
+ exampleBatchProcessing,
475
+ exampleWebSocketMonitoring,
476
+ exampleBackgroundReplacement,
477
+ exampleErrorHandling,
478
+ exampleParallelProcessing
479
+ ];
480
+
481
+ for (const example of examples) {
482
+ try {
483
+ await example();
484
+ } catch (error) {
485
+ console.error(`\n❌ Example failed: ${error.message}`);
486
+ }
487
+ }
488
+
489
+ console.log('\n' + '#'.repeat(60));
490
+ console.log('# All examples complete!');
491
+ console.log('#'.repeat(60));
492
+ }
493
+
494
+ // Run if called directly
495
+ if (require.main === module) {
496
+ main().catch(console.error);
497
+ }
498
+
499
+ module.exports = { BackgroundFXClient };