facebetter 1.0.14 → 1.1.1
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/README.md +157 -0
- package/dist/facebetter.esm.js +586 -161
- package/dist/facebetter.esm.js.map +1 -1
- package/dist/facebetter.js +586 -161
- package/dist/facebetter.js.map +1 -1
- package/package.json +2 -2
package/dist/facebetter.js
CHANGED
|
@@ -53,7 +53,13 @@
|
|
|
53
53
|
this.appId = config.appId || null;
|
|
54
54
|
this.appKey = config.appKey || null;
|
|
55
55
|
this.licenseJson = config.licenseJson || null;
|
|
56
|
-
this.resourcePath = '/
|
|
56
|
+
this.resourcePath = '/resource.fbd';
|
|
57
|
+
/**
|
|
58
|
+
* Whether to use an external GL context (native platforms only).
|
|
59
|
+
* In Web/WASM environments, this field is kept for configuration structure alignment,
|
|
60
|
+
* but it does not take effect in the current implementation.
|
|
61
|
+
*/
|
|
62
|
+
this.externalContext = !!config.externalContext;
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
/**
|
|
@@ -61,11 +67,11 @@
|
|
|
61
67
|
* @returns {boolean} True if valid
|
|
62
68
|
*/
|
|
63
69
|
isValid() {
|
|
64
|
-
//
|
|
70
|
+
// If licenseJson is provided, use it for validation
|
|
65
71
|
if (this.licenseJson) {
|
|
66
72
|
return typeof this.licenseJson === 'string' && this.licenseJson.trim() !== '';
|
|
67
73
|
}
|
|
68
|
-
//
|
|
74
|
+
// Otherwise appId and appKey are required
|
|
69
75
|
return this.appId && typeof this.appId === 'string' && this.appId.trim() !== '' &&
|
|
70
76
|
this.appKey && typeof this.appKey === 'string' && this.appKey.trim() !== '';
|
|
71
77
|
}
|
|
@@ -88,61 +94,87 @@
|
|
|
88
94
|
* Beauty type enumeration
|
|
89
95
|
*/
|
|
90
96
|
const BeautyType$1 = {
|
|
91
|
-
Basic: 0,
|
|
92
|
-
Reshape: 1,
|
|
93
|
-
Makeup: 2,
|
|
94
|
-
VirtualBackground: 3
|
|
97
|
+
Basic: 0, // Basic beauty (smoothing, whitening, etc.)
|
|
98
|
+
Reshape: 1, // Face reshaping (face thinning, big eyes, etc.)
|
|
99
|
+
Makeup: 2, // Makeup effects (lipstick, blush, etc.)
|
|
100
|
+
VirtualBackground: 3, // Virtual background (blur, image replacement)
|
|
101
|
+
ChromaKey: 4, // Chroma key (green screen removal)
|
|
102
|
+
Filter: 5, // LUT based filter
|
|
103
|
+
Sticker: 6 // 2D/3D sticker
|
|
95
104
|
};
|
|
96
105
|
|
|
97
106
|
/**
|
|
98
107
|
* Basic beauty parameter enumeration
|
|
108
|
+
* All values should be in range [0.0, 1.0]
|
|
99
109
|
*/
|
|
100
110
|
const BasicParam$1 = {
|
|
101
|
-
Smoothing: 0, //
|
|
102
|
-
Sharpening: 1,
|
|
103
|
-
Whitening: 2, //
|
|
104
|
-
Rosiness: 3 //
|
|
111
|
+
Smoothing: 0, // Skin smoothing (0.0: none, 1.0: maximum)
|
|
112
|
+
Sharpening: 1, // Image sharpening (0.0: none, 1.0: maximum)
|
|
113
|
+
Whitening: 2, // Skin whitening (0.0: none, 1.0: maximum)
|
|
114
|
+
Rosiness: 3 // Skin rosiness (0.0: none, 1.0: maximum)
|
|
105
115
|
};
|
|
106
116
|
|
|
107
117
|
/**
|
|
108
118
|
* Face reshape parameter enumeration
|
|
119
|
+
* All values should be in range [0.0, 1.0]
|
|
109
120
|
*/
|
|
110
121
|
const ReshapeParam$1 = {
|
|
111
|
-
|
|
112
|
-
FaceVShape: 1,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Cheekbone: 4,
|
|
116
|
-
Jawbone: 5,
|
|
117
|
-
Chin: 6,
|
|
118
|
-
|
|
119
|
-
EyeSize: 8,
|
|
120
|
-
EyeDistance: 9
|
|
122
|
+
FaceThinning: 0, // Face thinning (0.0: none, 1.0: maximum)
|
|
123
|
+
FaceVShape: 1, // V-shape face (0.0: none, 1.0: maximum)
|
|
124
|
+
FaceNarrowing: 2, // Face narrowing (0.0: none, 1.0: maximum)
|
|
125
|
+
FaceShortening: 3,// Face shortening (0.0: none, 1.0: maximum)
|
|
126
|
+
Cheekbone: 4, // Cheekbone slimming (0.0: none, 1.0: maximum)
|
|
127
|
+
Jawbone: 5, // Jawbone slimming (0.0: none, 1.0: maximum)
|
|
128
|
+
Chin: 6, // Chin length adjustment (0.0: none, 1.0: maximum)
|
|
129
|
+
NoseSlimming: 7, // Nose slimming (0.0: none, 1.0: maximum)
|
|
130
|
+
EyeSize: 8, // Eye size (0.0: normal, 1.0: maximum)
|
|
131
|
+
EyeDistance: 9 // Eye distance (0.0: normal, 1.0: maximum)
|
|
121
132
|
};
|
|
122
133
|
|
|
123
134
|
/**
|
|
124
135
|
* Makeup parameter enumeration
|
|
136
|
+
* All values should be in range [0.0, 1.0]
|
|
125
137
|
*/
|
|
126
138
|
const MakeupParam$1 = {
|
|
127
|
-
Lipstick: 0, //
|
|
128
|
-
Blush: 1 //
|
|
139
|
+
Lipstick: 0, // Lipstick intensity (0.0: none, 1.0: maximum)
|
|
140
|
+
Blush: 1 // Blush intensity (0.0: none, 1.0: maximum)
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Chroma Key parameter enumeration
|
|
145
|
+
*/
|
|
146
|
+
const ChromaKeyParam = {
|
|
147
|
+
KeyColor: 0, // Key color (0.0: Green, 1.0: Blue, 2.0: Red)
|
|
148
|
+
Similarity: 1, // Color similarity (0.0 - 1.0)
|
|
149
|
+
Smoothness: 2, // Edge smoothness (0.0 - 1.0)
|
|
150
|
+
Desaturation: 3 // Spill desaturation (0.0 - 1.0)
|
|
129
151
|
};
|
|
130
152
|
|
|
131
153
|
/**
|
|
132
154
|
* Background mode enumeration
|
|
133
155
|
*/
|
|
134
156
|
const BackgroundMode$1 = {
|
|
135
|
-
None: 0, //
|
|
136
|
-
Blur: 1, //
|
|
137
|
-
Image: 2 //
|
|
157
|
+
None: 0, // No background processing
|
|
158
|
+
Blur: 1, // Blurred background
|
|
159
|
+
Image: 2 // Background image replacement
|
|
138
160
|
};
|
|
139
161
|
|
|
140
162
|
/**
|
|
141
|
-
*
|
|
163
|
+
* Frame type enumeration
|
|
142
164
|
*/
|
|
143
|
-
const
|
|
144
|
-
Image: 0, //
|
|
145
|
-
Video: 1 //
|
|
165
|
+
const FrameType$1 = {
|
|
166
|
+
Image: 0, // Image mode
|
|
167
|
+
Video: 1 // Video mode
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Mirror mode enumeration (apply to input before processing)
|
|
172
|
+
*/
|
|
173
|
+
const MirrorMode$1 = {
|
|
174
|
+
None: 0, // No mirror
|
|
175
|
+
Horizontal: 1, // Mirror horizontally (e.g. front camera selfie)
|
|
176
|
+
Vertical: 2, // Mirror vertically
|
|
177
|
+
Both: 3 // Mirror both axes
|
|
146
178
|
};
|
|
147
179
|
|
|
148
180
|
/**
|
|
@@ -178,8 +210,10 @@
|
|
|
178
210
|
BackgroundMode: BackgroundMode$1,
|
|
179
211
|
BasicParam: BasicParam$1,
|
|
180
212
|
BeautyType: BeautyType$1,
|
|
213
|
+
ChromaKeyParam: ChromaKeyParam,
|
|
214
|
+
FrameType: FrameType$1,
|
|
181
215
|
MakeupParam: MakeupParam$1,
|
|
182
|
-
|
|
216
|
+
MirrorMode: MirrorMode$1,
|
|
183
217
|
ReshapeParam: ReshapeParam$1,
|
|
184
218
|
VirtualBackgroundOptions: VirtualBackgroundOptions$1
|
|
185
219
|
});
|
|
@@ -217,7 +251,7 @@
|
|
|
217
251
|
throw new FacebetterError('Platform API is required');
|
|
218
252
|
}
|
|
219
253
|
|
|
220
|
-
//
|
|
254
|
+
// If an EngineConfig instance is passed, use it directly; otherwise create a new EngineConfig
|
|
221
255
|
let engineConfig;
|
|
222
256
|
if (config instanceof EngineConfig) {
|
|
223
257
|
engineConfig = config;
|
|
@@ -235,20 +269,23 @@
|
|
|
235
269
|
this.appId = engineConfig.appId;
|
|
236
270
|
this.appKey = engineConfig.appKey;
|
|
237
271
|
this.licenseJson = engineConfig.licenseJson;
|
|
238
|
-
this.resourcePath = '/
|
|
272
|
+
this.resourcePath = '/resource.fbd';
|
|
239
273
|
this.enginePtr = null;
|
|
240
274
|
this.initialized = false;
|
|
241
275
|
this.srcBufferPtr = null;
|
|
242
276
|
this.dstBufferPtr = null;
|
|
243
277
|
this.bufferSize = 0;
|
|
244
278
|
|
|
279
|
+
// Callback related state
|
|
280
|
+
this._callbackSharedBufferPtr = null;
|
|
281
|
+
this._callbackSharedBufferSize = 0;
|
|
282
|
+
|
|
245
283
|
// Store platform API
|
|
246
284
|
this._platformAPI = platformAPI;
|
|
247
285
|
this._loadWasmModule = platformAPI.loadWasmModule;
|
|
248
286
|
this._getWasmModule = platformAPI.getWasmModule;
|
|
249
287
|
this._getWasmBuffer = platformAPI.getWasmBuffer;
|
|
250
288
|
this._toImageData = platformAPI.toImageData;
|
|
251
|
-
this._verifyAppKeyOnline = platformAPI.verifyAppKeyOnline;
|
|
252
289
|
this._ensureGPUPixelCanvas = platformAPI.ensureGPUPixelCanvas;
|
|
253
290
|
this._cleanupGPUPixelCanvas = platformAPI.cleanupGPUPixelCanvas;
|
|
254
291
|
|
|
@@ -326,23 +363,22 @@
|
|
|
326
363
|
* @returns {Promise<void>} Promise that resolves when initialization is complete
|
|
327
364
|
*/
|
|
328
365
|
async init(options = {}) {
|
|
329
|
-
//
|
|
366
|
+
// Concurrency control: if already initialized, return immediately
|
|
330
367
|
if (this.initialized) {
|
|
331
368
|
return;
|
|
332
369
|
}
|
|
333
370
|
|
|
334
|
-
//
|
|
371
|
+
// Concurrency control: if initialization is in progress, return the same Promise
|
|
335
372
|
if (this._initPromise) {
|
|
336
373
|
return this._initPromise;
|
|
337
374
|
}
|
|
338
375
|
|
|
339
|
-
//
|
|
376
|
+
// Create initialization Promise
|
|
340
377
|
this._initPromise = (async () => {
|
|
341
378
|
try {
|
|
342
379
|
const wasmTimeout = options.timeout || 30000;
|
|
343
|
-
const authTimeout = options.authTimeout || 10000;
|
|
344
380
|
|
|
345
|
-
//
|
|
381
|
+
// Wait for WASM module loading (with timeout)
|
|
346
382
|
try {
|
|
347
383
|
await Promise.race([
|
|
348
384
|
this._wasmLoadPromise,
|
|
@@ -354,48 +390,60 @@
|
|
|
354
390
|
|
|
355
391
|
const Module = this._getWasmModule();
|
|
356
392
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
);
|
|
393
|
+
// Setup usage report proxy for WASM
|
|
394
|
+
if (!Module.onReportUsage) {
|
|
395
|
+
Module.onReportUsage = async (payloadJson) => {
|
|
396
|
+
try {
|
|
397
|
+
const url = 'https://facebetter.pixpark.net/facebetter/v1/report';
|
|
398
|
+
const response = await fetch(url, {
|
|
399
|
+
method: 'POST',
|
|
400
|
+
headers: {
|
|
401
|
+
'Content-Type': 'application/json'
|
|
402
|
+
},
|
|
403
|
+
body: payloadJson
|
|
404
|
+
});
|
|
405
|
+
return response.ok;
|
|
406
|
+
} catch (error) {
|
|
407
|
+
return false;
|
|
373
408
|
}
|
|
409
|
+
};
|
|
410
|
+
}
|
|
374
411
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
412
|
+
// Setup online auth proxy for WASM
|
|
413
|
+
if (!Module.onOnlineAuth) {
|
|
414
|
+
Module.onOnlineAuth = async (payloadJson) => {
|
|
415
|
+
try {
|
|
416
|
+
const url = 'https://facebetter.pixpark.net/facebetter/v1/auth';
|
|
417
|
+
const response = await fetch(url, {
|
|
418
|
+
method: 'POST',
|
|
419
|
+
headers: {
|
|
420
|
+
'Content-Type': 'application/json'
|
|
421
|
+
},
|
|
422
|
+
body: payloadJson
|
|
423
|
+
});
|
|
424
|
+
if (!response.ok) {
|
|
425
|
+
console.warn('[JS Engine] Online auth fetch failed with status:', response.status);
|
|
426
|
+
return "";
|
|
427
|
+
}
|
|
428
|
+
return await response.text();
|
|
429
|
+
} catch (error) {
|
|
430
|
+
console.error('[JS Engine] Online auth fetch exception:', error);
|
|
431
|
+
return "";
|
|
384
432
|
}
|
|
385
|
-
|
|
386
|
-
}
|
|
433
|
+
};
|
|
387
434
|
}
|
|
388
435
|
|
|
389
|
-
//
|
|
390
|
-
// 如果通过 appId/appKey 获取到了响应,则使用响应作为 licenseJson
|
|
391
|
-
// WASM 层只需要验证 licenseJson,不需要发送 HTTP 请求
|
|
436
|
+
// Create engine instance, auth (online/offline) is handled by WASM layer via onOnlineAuth
|
|
392
437
|
const enginePtr = Module.ccall(
|
|
393
|
-
'
|
|
438
|
+
'CreateBeautyEffectEngineEx',
|
|
394
439
|
'number',
|
|
395
|
-
['string', 'string'],
|
|
440
|
+
['string', 'string', 'string', 'string', 'number'],
|
|
396
441
|
[
|
|
397
442
|
this.resourcePath,
|
|
398
|
-
|
|
443
|
+
this.licenseJson || '',
|
|
444
|
+
this.appId || '',
|
|
445
|
+
this.appKey || '',
|
|
446
|
+
this.config.externalContext ? 1 : 0
|
|
399
447
|
]
|
|
400
448
|
);
|
|
401
449
|
|
|
@@ -408,9 +456,9 @@
|
|
|
408
456
|
|
|
409
457
|
this.enginePtr = enginePtr;
|
|
410
458
|
this.initialized = true;
|
|
411
|
-
this._initPromise = null; //
|
|
459
|
+
this._initPromise = null; // Clear Promise cache, allow re-initialization (if needed)
|
|
412
460
|
} catch (error) {
|
|
413
|
-
this._initPromise = null; //
|
|
461
|
+
this._initPromise = null; // Clear Promise cache, allow retry
|
|
414
462
|
throw error;
|
|
415
463
|
}
|
|
416
464
|
})();
|
|
@@ -438,11 +486,18 @@
|
|
|
438
486
|
this.dstBufferPtr = null;
|
|
439
487
|
}
|
|
440
488
|
|
|
489
|
+
// Clean up shared memory
|
|
490
|
+
if (this._callbackSharedBufferPtr) {
|
|
491
|
+
Module._free(this._callbackSharedBufferPtr);
|
|
492
|
+
this._callbackSharedBufferPtr = null;
|
|
493
|
+
this._callbackSharedBufferSize = 0;
|
|
494
|
+
}
|
|
495
|
+
|
|
441
496
|
Module.ccall('DestroyBeautyEffectEngine', null, ['number'], [this.enginePtr]);
|
|
442
497
|
this.enginePtr = null;
|
|
443
498
|
this.initialized = false;
|
|
444
499
|
this.bufferSize = 0;
|
|
445
|
-
this._initPromise = null; //
|
|
500
|
+
this._initPromise = null; // Clear initialization Promise
|
|
446
501
|
|
|
447
502
|
// Clean up offscreen canvas
|
|
448
503
|
if (this._offscreenCanvas) {
|
|
@@ -547,7 +602,7 @@
|
|
|
547
602
|
|
|
548
603
|
/**
|
|
549
604
|
* Sets a basic beauty parameter
|
|
550
|
-
* @param {number} param - Parameter (use BasicParam enum)
|
|
605
|
+
* @param {number} param - Parameter (use BasicParam enum, e.g., BasicParam.Smoothing)
|
|
551
606
|
* @param {number} value - Parameter value (0.0 - 1.0)
|
|
552
607
|
*/
|
|
553
608
|
setBasicParam(param, value) {
|
|
@@ -557,7 +612,7 @@
|
|
|
557
612
|
|
|
558
613
|
/**
|
|
559
614
|
* Sets a reshape parameter
|
|
560
|
-
* @param {number} param - Parameter (use ReshapeParam enum)
|
|
615
|
+
* @param {number} param - Parameter (use ReshapeParam enum, e.g., ReshapeParam.FaceThinning)
|
|
561
616
|
* @param {number} value - Parameter value (0.0 - 1.0)
|
|
562
617
|
*/
|
|
563
618
|
setReshapeParam(param, value) {
|
|
@@ -567,7 +622,7 @@
|
|
|
567
622
|
|
|
568
623
|
/**
|
|
569
624
|
* Sets a makeup parameter
|
|
570
|
-
* @param {number} param - Parameter (use MakeupParam enum)
|
|
625
|
+
* @param {number} param - Parameter (use MakeupParam enum, e.g., MakeupParam.Lipstick)
|
|
571
626
|
* @param {number} value - Parameter value (0.0 - 1.0)
|
|
572
627
|
*/
|
|
573
628
|
setMakeupParam(param, value) {
|
|
@@ -576,7 +631,253 @@
|
|
|
576
631
|
}
|
|
577
632
|
|
|
578
633
|
/**
|
|
579
|
-
*
|
|
634
|
+
* Sets chroma key parameter
|
|
635
|
+
* @param {number} param - Parameter (use ChromaKeyParam enum, e.g., ChromaKeyParam.Similarity)
|
|
636
|
+
* @param {number} value - Parameter value (KeyColor: 0.0=Green, 1.0=Blue, 2.0=Red; others 0.0-1.0)
|
|
637
|
+
*/
|
|
638
|
+
setChromaKeyParam(param, value) {
|
|
639
|
+
this._ensureInitialized();
|
|
640
|
+
// For KeyColor, values are 0, 1, 2, not 0.0-1.0
|
|
641
|
+
if (param === 0) { // ChromaKeyParam.KeyColor
|
|
642
|
+
const Module = this._getWasmModule();
|
|
643
|
+
const result = Module.ccall(
|
|
644
|
+
'SetBeautyParamChromaKey',
|
|
645
|
+
'number',
|
|
646
|
+
['number', 'number', 'number'],
|
|
647
|
+
[this.enginePtr, param, value]
|
|
648
|
+
);
|
|
649
|
+
checkResult(result, `Failed to set chroma key parameter`);
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
this._setBeautyParam('SetBeautyParamChromaKey', param, value);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Sets a LUT-based filter
|
|
657
|
+
* @param {string} filterId - Unique identifier of the filter (e.g., "chuxin"). Pass "" to clear.
|
|
658
|
+
*/
|
|
659
|
+
setFilter(filterId) {
|
|
660
|
+
this._ensureInitialized();
|
|
661
|
+
const Module = this._getWasmModule();
|
|
662
|
+
const result = Module.ccall(
|
|
663
|
+
'SetFilter',
|
|
664
|
+
'number',
|
|
665
|
+
['number', 'string'],
|
|
666
|
+
[this.enginePtr, filterId || '']
|
|
667
|
+
);
|
|
668
|
+
checkResult(result, 'Failed to set filter');
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Sets the intensity of the current filter
|
|
673
|
+
* @param {number} intensity - Filter intensity (0.0 - 1.0)
|
|
674
|
+
*/
|
|
675
|
+
setFilterIntensity(intensity) {
|
|
676
|
+
this._ensureInitialized();
|
|
677
|
+
const Module = this._getWasmModule();
|
|
678
|
+
const result = Module.ccall(
|
|
679
|
+
'SetFilterIntensity',
|
|
680
|
+
'number',
|
|
681
|
+
['number', 'number'],
|
|
682
|
+
[this.enginePtr, intensity]
|
|
683
|
+
);
|
|
684
|
+
checkResult(result, 'Failed to set filter intensity');
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Sets a 2D sticker
|
|
689
|
+
* @param {string} stickerId - Unique identifier of the sticker (e.g., "樱花"). Pass "" to clear.
|
|
690
|
+
*/
|
|
691
|
+
setSticker(stickerId) {
|
|
692
|
+
this._ensureInitialized();
|
|
693
|
+
const Module = this._getWasmModule();
|
|
694
|
+
const result = Module.ccall(
|
|
695
|
+
'SetSticker',
|
|
696
|
+
'number',
|
|
697
|
+
['number', 'string'],
|
|
698
|
+
[this.enginePtr, stickerId || '']
|
|
699
|
+
);
|
|
700
|
+
checkResult(result, 'Failed to set sticker');
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Registers a filter from a file path or data
|
|
705
|
+
* @param {string} filterId - Unique identifier for the filter
|
|
706
|
+
* @param {string|Uint8Array} resource - Path to .fbd file or Uint8Array data
|
|
707
|
+
*/
|
|
708
|
+
registerFilter(filterId, resource) {
|
|
709
|
+
this._ensureInitialized();
|
|
710
|
+
const Module = this._getWasmModule();
|
|
711
|
+
|
|
712
|
+
if (typeof resource === 'string') {
|
|
713
|
+
const result = Module.ccall(
|
|
714
|
+
'RegisterFilterPath',
|
|
715
|
+
'number',
|
|
716
|
+
['number', 'string', 'string'],
|
|
717
|
+
[this.enginePtr, filterId, resource]
|
|
718
|
+
);
|
|
719
|
+
checkResult(result, `Failed to register filter path: ${filterId}`);
|
|
720
|
+
} else if (resource instanceof Uint8Array) {
|
|
721
|
+
const dataPtr = Module._malloc(resource.length);
|
|
722
|
+
Module.HEAPU8.set(resource, dataPtr);
|
|
723
|
+
try {
|
|
724
|
+
const result = Module.ccall(
|
|
725
|
+
'RegisterFilterData',
|
|
726
|
+
'number',
|
|
727
|
+
['number', 'string', 'number', 'number'],
|
|
728
|
+
[this.enginePtr, filterId, dataPtr, resource.length]
|
|
729
|
+
);
|
|
730
|
+
checkResult(result, `Failed to register filter data: ${filterId}`);
|
|
731
|
+
} finally {
|
|
732
|
+
Module._free(dataPtr);
|
|
733
|
+
}
|
|
734
|
+
} else {
|
|
735
|
+
throw new FacebetterError('Resource must be a string path or Uint8Array data');
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Registers a sticker from a file path or data
|
|
741
|
+
* @param {string} stickerId - Unique identifier for the sticker
|
|
742
|
+
* @param {string|Uint8Array} resource - Path to .fbd file or Uint8Array data
|
|
743
|
+
*/
|
|
744
|
+
registerSticker(stickerId, resource) {
|
|
745
|
+
this._ensureInitialized();
|
|
746
|
+
const Module = this._getWasmModule();
|
|
747
|
+
|
|
748
|
+
if (typeof resource === 'string') {
|
|
749
|
+
const result = Module.ccall(
|
|
750
|
+
'RegisterStickerPath',
|
|
751
|
+
'number',
|
|
752
|
+
['number', 'string', 'string'],
|
|
753
|
+
[this.enginePtr, stickerId, resource]
|
|
754
|
+
);
|
|
755
|
+
checkResult(result, `Failed to register sticker path: ${stickerId}`);
|
|
756
|
+
} else if (resource instanceof Uint8Array) {
|
|
757
|
+
const dataPtr = Module._malloc(resource.length);
|
|
758
|
+
Module.HEAPU8.set(resource, dataPtr);
|
|
759
|
+
try {
|
|
760
|
+
const result = Module.ccall(
|
|
761
|
+
'RegisterStickerData',
|
|
762
|
+
'number',
|
|
763
|
+
['number', 'string', 'number', 'number'],
|
|
764
|
+
[this.enginePtr, stickerId, dataPtr, resource.length]
|
|
765
|
+
);
|
|
766
|
+
checkResult(result, `Failed to register sticker data: ${stickerId}`);
|
|
767
|
+
} finally {
|
|
768
|
+
Module._free(dataPtr);
|
|
769
|
+
}
|
|
770
|
+
} else {
|
|
771
|
+
throw new FacebetterError('Resource must be a string path or Uint8Array data');
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Unregisters a specific filter
|
|
777
|
+
* @param {string} filterId - Filter ID to unregister
|
|
778
|
+
*/
|
|
779
|
+
unregisterFilter(filterId) {
|
|
780
|
+
this._ensureInitialized();
|
|
781
|
+
const Module = this._getWasmModule();
|
|
782
|
+
const result = Module.ccall(
|
|
783
|
+
'UnregisterFilter',
|
|
784
|
+
'number',
|
|
785
|
+
['number', 'string'],
|
|
786
|
+
[this.enginePtr, filterId]
|
|
787
|
+
);
|
|
788
|
+
checkResult(result, `Failed to unregister filter: ${filterId}`);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Unregisters all filters
|
|
793
|
+
*/
|
|
794
|
+
unregisterAllFilters() {
|
|
795
|
+
this._ensureInitialized();
|
|
796
|
+
const Module = this._getWasmModule();
|
|
797
|
+
const result = Module.ccall(
|
|
798
|
+
'UnregisterAllFilters',
|
|
799
|
+
'number',
|
|
800
|
+
['number'],
|
|
801
|
+
[this.enginePtr]
|
|
802
|
+
);
|
|
803
|
+
checkResult(result, 'Failed to unregister all filters');
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* Unregisters a specific sticker
|
|
808
|
+
* @param {string} stickerId - Sticker ID to unregister
|
|
809
|
+
*/
|
|
810
|
+
unregisterSticker(stickerId) {
|
|
811
|
+
this._ensureInitialized();
|
|
812
|
+
const Module = this._getWasmModule();
|
|
813
|
+
const result = Module.ccall(
|
|
814
|
+
'UnregisterSticker',
|
|
815
|
+
'number',
|
|
816
|
+
['number', 'string'],
|
|
817
|
+
[this.enginePtr, stickerId]
|
|
818
|
+
);
|
|
819
|
+
checkResult(result, `Failed to unregister sticker: ${stickerId}`);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Unregisters all stickers
|
|
824
|
+
*/
|
|
825
|
+
unregisterAllStickers() {
|
|
826
|
+
this._ensureInitialized();
|
|
827
|
+
const Module = this._getWasmModule();
|
|
828
|
+
const result = Module.ccall(
|
|
829
|
+
'UnregisterAllStickers',
|
|
830
|
+
'number',
|
|
831
|
+
['number'],
|
|
832
|
+
[this.enginePtr]
|
|
833
|
+
);
|
|
834
|
+
checkResult(result, 'Failed to unregister all stickers');
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Gets the list of registered filter IDs
|
|
839
|
+
* @returns {string[]} Array of registered filter IDs
|
|
840
|
+
*/
|
|
841
|
+
getRegisteredFilters() {
|
|
842
|
+
this._ensureInitialized();
|
|
843
|
+
const Module = this._getWasmModule();
|
|
844
|
+
const jsonStr = Module.ccall(
|
|
845
|
+
'GetRegisteredFilters',
|
|
846
|
+
'string',
|
|
847
|
+
['number'],
|
|
848
|
+
[this.enginePtr]
|
|
849
|
+
);
|
|
850
|
+
try {
|
|
851
|
+
return JSON.parse(jsonStr || '[]');
|
|
852
|
+
} catch (e) {
|
|
853
|
+
console.error('Failed to parse registered filters JSON:', e);
|
|
854
|
+
return [];
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Gets the list of registered sticker IDs
|
|
860
|
+
* @returns {string[]} Array of registered sticker IDs
|
|
861
|
+
*/
|
|
862
|
+
getRegisteredStickers() {
|
|
863
|
+
this._ensureInitialized();
|
|
864
|
+
const Module = this._getWasmModule();
|
|
865
|
+
const jsonStr = Module.ccall(
|
|
866
|
+
'GetRegisteredStickers',
|
|
867
|
+
'string',
|
|
868
|
+
['number'],
|
|
869
|
+
[this.enginePtr]
|
|
870
|
+
);
|
|
871
|
+
try {
|
|
872
|
+
return JSON.parse(jsonStr || '[]');
|
|
873
|
+
} catch (e) {
|
|
874
|
+
console.error('Failed to parse registered stickers JSON:', e);
|
|
875
|
+
return [];
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Internal method to set beauty parameters
|
|
580
881
|
* @private
|
|
581
882
|
*/
|
|
582
883
|
_setBeautyParam(functionName, param, value) {
|
|
@@ -595,6 +896,139 @@
|
|
|
595
896
|
checkResult(result, `Failed to set beauty parameter`);
|
|
596
897
|
}
|
|
597
898
|
|
|
899
|
+
/**
|
|
900
|
+
* Sets engine callbacks (face landmarks detection)
|
|
901
|
+
* @param {Object} callbacks - Callback functions
|
|
902
|
+
* @param {Function} callbacks.onFaceLandmarks - Callback for face landmarks detection
|
|
903
|
+
* @param {number} [callbacks.maxFaces=10] - Maximum number of faces to support (affects shared buffer size)
|
|
904
|
+
*/
|
|
905
|
+
setCallbacks(callbacks) {
|
|
906
|
+
this._ensureInitialized();
|
|
907
|
+
const Module = this._getWasmModule();
|
|
908
|
+
|
|
909
|
+
// Initialize callback storage (if it doesn't exist)
|
|
910
|
+
if (!Module._face_landmarks_callbacks) {
|
|
911
|
+
Module._face_landmarks_callbacks = [];
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
let callbackId = 0;
|
|
915
|
+
let sharedBufferPtr = null;
|
|
916
|
+
let sharedBufferSize = 0;
|
|
917
|
+
|
|
918
|
+
if (callbacks && callbacks.onFaceLandmarks) {
|
|
919
|
+
// Get max faces (default 10)
|
|
920
|
+
const maxFaces = callbacks.maxFaces || 10;
|
|
921
|
+
|
|
922
|
+
// Pre-allocate shared memory
|
|
923
|
+
// Metadata: 2 ints (frame_number, face_count) = 8 bytes
|
|
924
|
+
// Face data: maxFaces * 343 floats * 4 bytes = maxFaces * 1372 bytes
|
|
925
|
+
const metadataSize = 2 * 4; // 2 ints
|
|
926
|
+
const faceDataSize = maxFaces * 343 * 4; // 343 floats per face
|
|
927
|
+
sharedBufferSize = metadataSize + faceDataSize;
|
|
928
|
+
sharedBufferPtr = Module._malloc(sharedBufferSize);
|
|
929
|
+
|
|
930
|
+
if (!sharedBufferPtr) {
|
|
931
|
+
throw new FacebetterError('Failed to allocate shared buffer for callbacks');
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// Register callback function (internal wrapper, reads data from shared memory)
|
|
935
|
+
// Push first, then get index as callbackId (allows callbackId to be 0)
|
|
936
|
+
Module._face_landmarks_callbacks.push(
|
|
937
|
+
(frameNumber, faceCount, dataPtr) => {
|
|
938
|
+
// Read data from shared memory (zero-copy)
|
|
939
|
+
const heap = Module.HEAPF32;
|
|
940
|
+
const dataOffset = dataPtr / 4; // float is 4 bytes
|
|
941
|
+
|
|
942
|
+
const results = [];
|
|
943
|
+
const FLOATS_PER_FACE = 343;
|
|
944
|
+
|
|
945
|
+
for (let i = 0; i < faceCount; i++) {
|
|
946
|
+
const faceOffset = dataOffset + i * FLOATS_PER_FACE;
|
|
947
|
+
let offset = faceOffset;
|
|
948
|
+
|
|
949
|
+
// Read rect
|
|
950
|
+
const rect = {
|
|
951
|
+
x: heap[offset++],
|
|
952
|
+
y: heap[offset++],
|
|
953
|
+
width: heap[offset++],
|
|
954
|
+
height: heap[offset++]
|
|
955
|
+
};
|
|
956
|
+
|
|
957
|
+
// Read basic fields
|
|
958
|
+
const faceId = Math.round(heap[offset++]);
|
|
959
|
+
const faceAction = Math.round(heap[offset++]);
|
|
960
|
+
const score = heap[offset++];
|
|
961
|
+
const pitch = heap[offset++];
|
|
962
|
+
const roll = heap[offset++];
|
|
963
|
+
const yaw = heap[offset++];
|
|
964
|
+
|
|
965
|
+
// Read key_points (111 points)
|
|
966
|
+
const keyPoints = [];
|
|
967
|
+
for (let j = 0; j < 111; j++) {
|
|
968
|
+
keyPoints.push({
|
|
969
|
+
x: heap[offset++],
|
|
970
|
+
y: heap[offset++]
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
// Read visibility (111 points)
|
|
975
|
+
const visibility = [];
|
|
976
|
+
for (let j = 0; j < 111; j++) {
|
|
977
|
+
visibility.push(heap[offset++]);
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
results.push({
|
|
981
|
+
rect,
|
|
982
|
+
key_points: keyPoints,
|
|
983
|
+
visibility,
|
|
984
|
+
face_id: faceId,
|
|
985
|
+
face_action: faceAction,
|
|
986
|
+
score,
|
|
987
|
+
pitch,
|
|
988
|
+
roll,
|
|
989
|
+
yaw
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// Call user callback
|
|
994
|
+
callbacks.onFaceLandmarks(results);
|
|
995
|
+
}
|
|
996
|
+
);
|
|
997
|
+
|
|
998
|
+
// Get callback ID (index after push, can be 0)
|
|
999
|
+
callbackId = Module._face_landmarks_callbacks.length - 1;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
// Call C API
|
|
1003
|
+
const result = Module.ccall(
|
|
1004
|
+
'SetCallbacks',
|
|
1005
|
+
'number',
|
|
1006
|
+
['number', 'number', 'number', 'number'],
|
|
1007
|
+
[
|
|
1008
|
+
this.enginePtr,
|
|
1009
|
+
callbackId,
|
|
1010
|
+
sharedBufferPtr || 0,
|
|
1011
|
+
sharedBufferSize
|
|
1012
|
+
]
|
|
1013
|
+
);
|
|
1014
|
+
|
|
1015
|
+
checkResult(result, 'Failed to set callbacks');
|
|
1016
|
+
|
|
1017
|
+
// Clean up old shared memory (if it exists)
|
|
1018
|
+
if (this._callbackSharedBufferPtr) {
|
|
1019
|
+
Module._free(this._callbackSharedBufferPtr);
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// Store new shared memory pointer for cleanup
|
|
1023
|
+
if (sharedBufferPtr) {
|
|
1024
|
+
this._callbackSharedBufferPtr = sharedBufferPtr;
|
|
1025
|
+
this._callbackSharedBufferSize = sharedBufferSize;
|
|
1026
|
+
} else {
|
|
1027
|
+
this._callbackSharedBufferPtr = null;
|
|
1028
|
+
this._callbackSharedBufferSize = 0;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
598
1032
|
/**
|
|
599
1033
|
* Sets virtual background options (unified API, matches C++/Java/OC)
|
|
600
1034
|
* @param {VirtualBackgroundOptions|Object} options - Virtual background options
|
|
@@ -612,7 +1046,7 @@
|
|
|
612
1046
|
let imageBufferPtr = null;
|
|
613
1047
|
|
|
614
1048
|
try {
|
|
615
|
-
//
|
|
1049
|
+
// If a background image is provided, convert to ImageData and prepare buffer
|
|
616
1050
|
if (opts.backgroundImage) {
|
|
617
1051
|
imageData = this._toImageData(opts.backgroundImage);
|
|
618
1052
|
const bufferSize = imageData.width * imageData.height * 4;
|
|
@@ -623,7 +1057,7 @@
|
|
|
623
1057
|
view.set(imageData.data);
|
|
624
1058
|
}
|
|
625
1059
|
|
|
626
|
-
//
|
|
1060
|
+
// Use unified SetVirtualBackground C interface (consistent with other platforms)
|
|
627
1061
|
const result = Module.ccall(
|
|
628
1062
|
'SetVirtualBackground',
|
|
629
1063
|
'number',
|
|
@@ -631,7 +1065,7 @@
|
|
|
631
1065
|
[
|
|
632
1066
|
this.enginePtr,
|
|
633
1067
|
opts.mode,
|
|
634
|
-
imageBufferPtr || 0, //
|
|
1068
|
+
imageBufferPtr || 0, // If null, pass 0
|
|
635
1069
|
imageData ? imageData.width : 0,
|
|
636
1070
|
imageData ? imageData.height : 0,
|
|
637
1071
|
imageData ? imageData.width * 4 : 0
|
|
@@ -640,7 +1074,7 @@
|
|
|
640
1074
|
|
|
641
1075
|
checkResult(result, 'Failed to set virtual background');
|
|
642
1076
|
} finally {
|
|
643
|
-
//
|
|
1077
|
+
// Free memory
|
|
644
1078
|
if (imageBufferPtr) {
|
|
645
1079
|
Module._free(imageBufferPtr);
|
|
646
1080
|
}
|
|
@@ -680,10 +1114,11 @@
|
|
|
680
1114
|
* @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|Uint8ClampedArray} input - Input image
|
|
681
1115
|
* @param {number} width - Image width (required if input is Uint8ClampedArray)
|
|
682
1116
|
* @param {number} height - Image height (required if input is Uint8ClampedArray)
|
|
683
|
-
* @param {number}
|
|
1117
|
+
* @param {number} frameType - Frame type (use FrameType enum, default: FrameType.Video)
|
|
1118
|
+
* @param {number} mirrorMode - Mirror mode applied to input before processing (MirrorMode enum, default: MirrorMode.None)
|
|
684
1119
|
* @returns {ImageData} Processed image data
|
|
685
1120
|
*/
|
|
686
|
-
processImage(input, width, height,
|
|
1121
|
+
processImage(input, width, height, frameType = FrameType$1.Video, mirrorMode = MirrorMode$1.None) {
|
|
687
1122
|
this._ensureInitialized();
|
|
688
1123
|
const imageData = this._platformAPI.toImageData(input, width, height);
|
|
689
1124
|
const Module = this._getWasmModule();
|
|
@@ -701,7 +1136,7 @@
|
|
|
701
1136
|
const result = Module.ccall(
|
|
702
1137
|
'ProcessImageRGBA',
|
|
703
1138
|
'number',
|
|
704
|
-
['number', 'number', 'number', 'number', 'number', 'number', 'number'],
|
|
1139
|
+
['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number'],
|
|
705
1140
|
[
|
|
706
1141
|
this.enginePtr,
|
|
707
1142
|
this.srcBufferPtr,
|
|
@@ -709,7 +1144,8 @@
|
|
|
709
1144
|
imageData.height,
|
|
710
1145
|
imageData.width * 4,
|
|
711
1146
|
this.dstBufferPtr,
|
|
712
|
-
|
|
1147
|
+
frameType,
|
|
1148
|
+
mirrorMode
|
|
713
1149
|
]
|
|
714
1150
|
);
|
|
715
1151
|
|
|
@@ -728,6 +1164,65 @@
|
|
|
728
1164
|
}
|
|
729
1165
|
}
|
|
730
1166
|
|
|
1167
|
+
/**
|
|
1168
|
+
* Processes an external GPU texture.
|
|
1169
|
+
*
|
|
1170
|
+
* Note:
|
|
1171
|
+
* - This interface is mainly used for integration with internal WASM or advanced scenarios.
|
|
1172
|
+
* - textureHandle must be a texture handle (uint32) compatible with the OpenGL/WebGL context used by WASM.
|
|
1173
|
+
* - For common web scenarios, it is recommended to use processImage with ImageData/Canvas etc.
|
|
1174
|
+
*
|
|
1175
|
+
* @param {number} textureHandle - External texture handle (GL_TEXTURE_2D)
|
|
1176
|
+
* @param {number} width - Texture width
|
|
1177
|
+
* @param {number} height - Texture height
|
|
1178
|
+
* @param {number} stride - Row stride (usually width * 4)
|
|
1179
|
+
* @param {number} [frameType] - Frame type (FrameType.Image / FrameType.Video)
|
|
1180
|
+
* @param {number} [mirrorMode] - Mirror mode (MirrorMode enum; texture path does not support mirror, param reserved)
|
|
1181
|
+
* @returns {number} Processed texture handle (GL_TEXTURE_2D, uint32)
|
|
1182
|
+
*/
|
|
1183
|
+
processTexture(textureHandle,
|
|
1184
|
+
width,
|
|
1185
|
+
height,
|
|
1186
|
+
stride,
|
|
1187
|
+
frameType = FrameType$1.Video,
|
|
1188
|
+
mirrorMode = MirrorMode$1.None) {
|
|
1189
|
+
this._ensureInitialized();
|
|
1190
|
+
if (!textureHandle || width <= 0 || height <= 0 || stride <= 0) {
|
|
1191
|
+
throw new FacebetterError('Invalid textureHandle or dimensions for processTexture');
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
const Module = this._getWasmModule();
|
|
1195
|
+
|
|
1196
|
+
try {
|
|
1197
|
+
const result = Module.ccall(
|
|
1198
|
+
'ProcessImageTexture',
|
|
1199
|
+
'number',
|
|
1200
|
+
['number', 'number', 'number', 'number', 'number', 'number', 'number'],
|
|
1201
|
+
[
|
|
1202
|
+
this.enginePtr,
|
|
1203
|
+
textureHandle,
|
|
1204
|
+
width,
|
|
1205
|
+
height,
|
|
1206
|
+
stride,
|
|
1207
|
+
frameType,
|
|
1208
|
+
mirrorMode
|
|
1209
|
+
]
|
|
1210
|
+
);
|
|
1211
|
+
|
|
1212
|
+
if (!result || result === 0) {
|
|
1213
|
+
throw new FacebetterError('Failed to process external texture or got invalid output texture');
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
// Return processed texture handle for caller to continue using in same GL context
|
|
1217
|
+
return result;
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
if (error instanceof FacebetterError) {
|
|
1220
|
+
throw error;
|
|
1221
|
+
}
|
|
1222
|
+
throw new FacebetterError(`Texture processing error: ${error.message}`);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
731
1226
|
/**
|
|
732
1227
|
* Ensures the engine is initialized
|
|
733
1228
|
* @private
|
|
@@ -1055,77 +1550,6 @@
|
|
|
1055
1550
|
throw new FacebetterError('Unsupported image source type');
|
|
1056
1551
|
}
|
|
1057
1552
|
|
|
1058
|
-
/**
|
|
1059
|
-
* Gets User-Agent string for web platform
|
|
1060
|
-
* @returns {string} User-Agent string
|
|
1061
|
-
*/
|
|
1062
|
-
function getUserAgentString() {
|
|
1063
|
-
return 'FB/1.0 (web; wasm32)';
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
/**
|
|
1067
|
-
* Generates HMAC-SHA256 signature (browser version)
|
|
1068
|
-
* @param {string} key - HMAC key (app_key)
|
|
1069
|
-
* @param {string} data - Data to sign (timestamp string)
|
|
1070
|
-
* @returns {Promise<string>} Promise that resolves with hex-encoded signature
|
|
1071
|
-
*/
|
|
1072
|
-
async function generateHMACSignature(key, data) {
|
|
1073
|
-
const encoder = new TextEncoder();
|
|
1074
|
-
const keyData = encoder.encode(key);
|
|
1075
|
-
const messageData = encoder.encode(data);
|
|
1076
|
-
|
|
1077
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
1078
|
-
'raw',
|
|
1079
|
-
keyData,
|
|
1080
|
-
{ name: 'HMAC', hash: 'SHA-256' },
|
|
1081
|
-
false,
|
|
1082
|
-
['sign']
|
|
1083
|
-
);
|
|
1084
|
-
|
|
1085
|
-
const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
|
|
1086
|
-
|
|
1087
|
-
// Convert to hex string
|
|
1088
|
-
const hashArray = Array.from(new Uint8Array(signature));
|
|
1089
|
-
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
1090
|
-
return hashHex;
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
/**
|
|
1094
|
-
* Calls online_auth API to verify app_key (browser version)
|
|
1095
|
-
* @param {string} appId - Application ID
|
|
1096
|
-
* @param {string} appKey - Application key
|
|
1097
|
-
* @returns {Promise<Object>} Promise that resolves with response data
|
|
1098
|
-
*/
|
|
1099
|
-
async function verifyAppKeyOnline(appId, appKey) {
|
|
1100
|
-
try {
|
|
1101
|
-
const timestamp = Math.floor(Date.now() / 1000);
|
|
1102
|
-
const timestampStr = timestamp.toString();
|
|
1103
|
-
const hmacSignature = await generateHMACSignature(appKey, timestampStr);
|
|
1104
|
-
|
|
1105
|
-
const requestBody = {
|
|
1106
|
-
p_app_id: appId,
|
|
1107
|
-
p_hmac_signature: hmacSignature,
|
|
1108
|
-
p_timestamp: timestamp,
|
|
1109
|
-
p_user_agent: getUserAgentString()
|
|
1110
|
-
};
|
|
1111
|
-
|
|
1112
|
-
const response = await fetch('https://facebetter.pixpark.net/rest/v1/rpc/online_auth', {
|
|
1113
|
-
method: 'POST',
|
|
1114
|
-
headers: {
|
|
1115
|
-
'Content-Type': 'application/json',
|
|
1116
|
-
'User-Agent': getUserAgentString()
|
|
1117
|
-
},
|
|
1118
|
-
body: JSON.stringify(requestBody)
|
|
1119
|
-
});
|
|
1120
|
-
|
|
1121
|
-
const responseData = await response.json();
|
|
1122
|
-
return responseData;
|
|
1123
|
-
} catch (error) {
|
|
1124
|
-
console.error('Online auth request failed:', error);
|
|
1125
|
-
return null;
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
1553
|
/**
|
|
1130
1554
|
* Browser Entry Point
|
|
1131
1555
|
* For <script> tag usage (UMD format)
|
|
@@ -1162,7 +1586,6 @@
|
|
|
1162
1586
|
getWasmModule: getWasmModule,
|
|
1163
1587
|
getWasmBuffer: getWasmBuffer,
|
|
1164
1588
|
toImageData: toImageData,
|
|
1165
|
-
verifyAppKeyOnline: verifyAppKeyOnline,
|
|
1166
1589
|
ensureGPUPixelCanvas,
|
|
1167
1590
|
cleanupGPUPixelCanvas
|
|
1168
1591
|
};
|
|
@@ -1187,7 +1610,8 @@
|
|
|
1187
1610
|
const ReshapeParam = ReshapeParam$1;
|
|
1188
1611
|
const MakeupParam = MakeupParam$1;
|
|
1189
1612
|
const BackgroundMode = BackgroundMode$1;
|
|
1190
|
-
const
|
|
1613
|
+
const FrameType = FrameType$1;
|
|
1614
|
+
const MirrorMode = MirrorMode$1;
|
|
1191
1615
|
const VirtualBackgroundOptions = VirtualBackgroundOptions$1;
|
|
1192
1616
|
|
|
1193
1617
|
// Default export
|
|
@@ -1205,8 +1629,9 @@
|
|
|
1205
1629
|
exports.BeautyType = BeautyType;
|
|
1206
1630
|
exports.EngineConfig = EngineConfig;
|
|
1207
1631
|
exports.FacebetterError = FacebetterError;
|
|
1632
|
+
exports.FrameType = FrameType;
|
|
1208
1633
|
exports.MakeupParam = MakeupParam;
|
|
1209
|
-
exports.
|
|
1634
|
+
exports.MirrorMode = MirrorMode;
|
|
1210
1635
|
exports.ReshapeParam = ReshapeParam;
|
|
1211
1636
|
exports.VirtualBackgroundOptions = VirtualBackgroundOptions;
|
|
1212
1637
|
exports.createBeautyEffectEngine = createBeautyEffectEngine;
|