facebetter 1.0.13 → 1.1.0

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.
@@ -48,6 +48,12 @@ class EngineConfig {
48
48
  this.appKey = config.appKey || null;
49
49
  this.licenseJson = config.licenseJson || null;
50
50
  this.resourcePath = '/facebetter/resource.bundle';
51
+ /**
52
+ * Whether to use an external GL context (native platforms only).
53
+ * In Web/WASM environments, this field is kept for configuration structure alignment,
54
+ * but it does not take effect in the current implementation.
55
+ */
56
+ this.externalContext = !!config.externalContext;
51
57
  }
52
58
 
53
59
  /**
@@ -55,11 +61,11 @@ class EngineConfig {
55
61
  * @returns {boolean} True if valid
56
62
  */
57
63
  isValid() {
58
- // 如果提供了 licenseJson,则使用授权数据验证
64
+ // If licenseJson is provided, use it for validation
59
65
  if (this.licenseJson) {
60
66
  return typeof this.licenseJson === 'string' && this.licenseJson.trim() !== '';
61
67
  }
62
- // 否则需要 appId appKey
68
+ // Otherwise appId and appKey are required
63
69
  return this.appId && typeof this.appId === 'string' && this.appId.trim() !== '' &&
64
70
  this.appKey && typeof this.appKey === 'string' && this.appKey.trim() !== '';
65
71
  }
@@ -82,61 +88,75 @@ class EngineConfig {
82
88
  * Beauty type enumeration
83
89
  */
84
90
  const BeautyType$1 = {
85
- Basic: 0, // 基础美颜
86
- Reshape: 1, // 面部重塑
87
- Makeup: 2, // 美妆效果
88
- VirtualBackground: 3 // 虚拟背景
91
+ Basic: 0, // Basic beauty (smoothing, whitening, etc.)
92
+ Reshape: 1, // Face reshaping (face thinning, big eyes, etc.)
93
+ Makeup: 2, // Makeup effects (lipstick, blush, etc.)
94
+ VirtualBackground: 3, // Virtual background (blur, image replacement)
95
+ ChromaKey: 4 // Chroma key (green screen removal)
89
96
  };
90
97
 
91
98
  /**
92
99
  * Basic beauty parameter enumeration
100
+ * All values should be in range [0.0, 1.0]
93
101
  */
94
102
  const BasicParam$1 = {
95
- Smoothing: 0, // 磨皮
96
- Sharpening: 1, // 锐化
97
- Whitening: 2, // 美白
98
- Rosiness: 3 // 红润
103
+ Smoothing: 0, // Skin smoothing (0.0: none, 1.0: maximum)
104
+ Sharpening: 1, // Image sharpening (0.0: none, 1.0: maximum)
105
+ Whitening: 2, // Skin whitening (0.0: none, 1.0: maximum)
106
+ Rosiness: 3 // Skin rosiness (0.0: none, 1.0: maximum)
99
107
  };
100
108
 
101
109
  /**
102
110
  * Face reshape parameter enumeration
111
+ * All values should be in range [0.0, 1.0]
103
112
  */
104
113
  const ReshapeParam$1 = {
105
- FaceThin: 0, // 瘦脸
106
- FaceVShape: 1, // V
107
- FaceNarrow: 2, // 窄脸
108
- FaceShort: 3, // 短脸
109
- Cheekbone: 4, // 颧骨
110
- Jawbone: 5, // 下颌骨
111
- Chin: 6, // 下巴
112
- NoseSlim: 7, // 瘦鼻梁
113
- EyeSize: 8, // 大眼
114
- EyeDistance: 9 // 眼距
114
+ FaceThinning: 0, // Face thinning (0.0: none, 1.0: maximum)
115
+ FaceVShape: 1, // V-shape face (0.0: none, 1.0: maximum)
116
+ FaceNarrowing: 2, // Face narrowing (0.0: none, 1.0: maximum)
117
+ FaceShortening: 3,// Face shortening (0.0: none, 1.0: maximum)
118
+ Cheekbone: 4, // Cheekbone slimming (0.0: none, 1.0: maximum)
119
+ Jawbone: 5, // Jawbone slimming (0.0: none, 1.0: maximum)
120
+ Chin: 6, // Chin length adjustment (0.0: none, 1.0: maximum)
121
+ NoseSlimming: 7, // Nose slimming (0.0: none, 1.0: maximum)
122
+ EyeSize: 8, // Eye size (0.0: normal, 1.0: maximum)
123
+ EyeDistance: 9 // Eye distance (0.0: normal, 1.0: maximum)
115
124
  };
116
125
 
117
126
  /**
118
127
  * Makeup parameter enumeration
128
+ * All values should be in range [0.0, 1.0]
119
129
  */
120
130
  const MakeupParam$1 = {
121
- Lipstick: 0, // 口红
122
- Blush: 1 // 腮红
131
+ Lipstick: 0, // Lipstick intensity (0.0: none, 1.0: maximum)
132
+ Blush: 1 // Blush intensity (0.0: none, 1.0: maximum)
133
+ };
134
+
135
+ /**
136
+ * Chroma Key parameter enumeration
137
+ */
138
+ const ChromaKeyParam$1 = {
139
+ KeyColor: 0, // Key color (0.0: Green, 1.0: Blue, 2.0: Red)
140
+ Similarity: 1, // Color similarity (0.0 - 1.0)
141
+ Smoothness: 2, // Edge smoothness (0.0 - 1.0)
142
+ Desaturation: 3 // Spill desaturation (0.0 - 1.0)
123
143
  };
124
144
 
125
145
  /**
126
146
  * Background mode enumeration
127
147
  */
128
148
  const BackgroundMode$1 = {
129
- None: 0, // 无背景处理
130
- Blur: 1, // 模糊背景
131
- Image: 2 // 背景图片替换
149
+ None: 0, // No background processing
150
+ Blur: 1, // Blurred background
151
+ Image: 2 // Background image replacement
132
152
  };
133
153
 
134
154
  /**
135
- * Process mode enumeration
155
+ * Frame type enumeration
136
156
  */
137
- const ProcessMode$1 = {
138
- Image: 0, // 图片模式
139
- Video: 1 // 视频模式
157
+ const FrameType$1 = {
158
+ Image: 0, // Image mode
159
+ Video: 1 // Video mode
140
160
  };
141
161
 
142
162
  /**
@@ -172,8 +192,9 @@ var constants = /*#__PURE__*/Object.freeze({
172
192
  BackgroundMode: BackgroundMode$1,
173
193
  BasicParam: BasicParam$1,
174
194
  BeautyType: BeautyType$1,
195
+ ChromaKeyParam: ChromaKeyParam$1,
196
+ FrameType: FrameType$1,
175
197
  MakeupParam: MakeupParam$1,
176
- ProcessMode: ProcessMode$1,
177
198
  ReshapeParam: ReshapeParam$1,
178
199
  VirtualBackgroundOptions: VirtualBackgroundOptions$1
179
200
  });
@@ -211,7 +232,7 @@ class BeautyEffectEngine {
211
232
  throw new FacebetterError('Platform API is required');
212
233
  }
213
234
 
214
- // 如果传入的是 EngineConfig 实例,直接使用;否则创建新的 EngineConfig
235
+ // If an EngineConfig instance is passed, use it directly; otherwise create a new EngineConfig
215
236
  let engineConfig;
216
237
  if (config instanceof EngineConfig) {
217
238
  engineConfig = config;
@@ -236,6 +257,10 @@ class BeautyEffectEngine {
236
257
  this.dstBufferPtr = null;
237
258
  this.bufferSize = 0;
238
259
 
260
+ // Callback related state
261
+ this._callbackSharedBufferPtr = null;
262
+ this._callbackSharedBufferSize = 0;
263
+
239
264
  // Store platform API
240
265
  this._platformAPI = platformAPI;
241
266
  this._loadWasmModule = platformAPI.loadWasmModule;
@@ -320,23 +345,22 @@ class BeautyEffectEngine {
320
345
  * @returns {Promise<void>} Promise that resolves when initialization is complete
321
346
  */
322
347
  async init(options = {}) {
323
- // 并发控制:如果已经初始化,直接返回
348
+ // Concurrency control: if already initialized, return immediately
324
349
  if (this.initialized) {
325
350
  return;
326
351
  }
327
352
 
328
- // 并发控制:如果正在初始化,返回同一个 Promise
353
+ // Concurrency control: if initialization is in progress, return the same Promise
329
354
  if (this._initPromise) {
330
355
  return this._initPromise;
331
356
  }
332
357
 
333
- // 创建初始化 Promise
358
+ // Create initialization Promise
334
359
  this._initPromise = (async () => {
335
360
  try {
336
361
  const wasmTimeout = options.timeout || 30000;
337
- const authTimeout = options.authTimeout || 10000;
338
362
 
339
- // 等待 WASM 模块加载(带超时)
363
+ // Wait for WASM module loading (with timeout)
340
364
  try {
341
365
  await Promise.race([
342
366
  this._wasmLoadPromise,
@@ -348,48 +372,60 @@ class BeautyEffectEngine {
348
372
 
349
373
  const Module = this._getWasmModule();
350
374
 
351
- let licenseJsonToUse = this.licenseJson;
352
-
353
- // 如果用户提供了 appId appKey(但没有提供 licenseJson),则在 JS 层发送 HTTP 请求
354
- if (this.appId && this.appKey && !this.licenseJson && this._verifyAppKeyOnline) {
355
- try {
356
- // 在线认证(带超时)
357
- const authResponse = await Promise.race([
358
- this._verifyAppKeyOnline(this.appId, this.appKey),
359
- this._createTimeout(authTimeout, 'Online authentication')
360
- ]);
361
-
362
- if (!authResponse) {
363
- throw new FacebetterError(
364
- 'Failed to get server response from online_auth API. The server returned an empty response.',
365
- 'AUTH_EMPTY_RESPONSE'
366
- );
375
+ // Setup usage report proxy for WASM
376
+ if (!Module.onReportUsage) {
377
+ Module.onReportUsage = async (payloadJson) => {
378
+ try {
379
+ const url = 'https://facebetter.pixpark.net/rest/v1/rpc/report_sdk_usage';
380
+ const response = await fetch(url, {
381
+ method: 'POST',
382
+ headers: {
383
+ 'Content-Type': 'application/json'
384
+ },
385
+ body: payloadJson
386
+ });
387
+ return response.ok;
388
+ } catch (error) {
389
+ return false;
367
390
  }
391
+ };
392
+ }
368
393
 
369
- // 将服务器响应转换为 JSON 字符串,作为 licenseJson 传递给 WASM
370
- licenseJsonToUse = JSON.stringify(authResponse);
371
- console.log('Online auth response received, using as licenseJson');
372
- } catch (error) {
373
- if (error instanceof FacebetterError && error.code === 'TIMEOUT') {
374
- throw new FacebetterError(
375
- `Online authentication timed out after ${authTimeout}ms. Please check your network connection or provide licenseJson directly.`,
376
- 'AUTH_TIMEOUT'
377
- );
394
+ // Setup online auth proxy for WASM
395
+ if (!Module.onOnlineAuth) {
396
+ Module.onOnlineAuth = async (payloadJson) => {
397
+ try {
398
+ const url = 'https://facebetter.pixpark.net/rest/v1/rpc/online_auth_v2';
399
+ const response = await fetch(url, {
400
+ method: 'POST',
401
+ headers: {
402
+ 'Content-Type': 'application/json'
403
+ },
404
+ body: payloadJson
405
+ });
406
+ if (!response.ok) {
407
+ console.warn('[JS Engine] Online auth fetch failed with status:', response.status);
408
+ return "";
409
+ }
410
+ return await response.text();
411
+ } catch (error) {
412
+ console.error('[JS Engine] Online auth fetch exception:', error);
413
+ return "";
378
414
  }
379
- throw this._enhanceError(error, 'Failed to verify app key online');
380
- }
415
+ };
381
416
  }
382
417
 
383
- // 如果用户直接提供了 licenseJson,则直接使用
384
- // 如果通过 appId/appKey 获取到了响应,则使用响应作为 licenseJson
385
- // WASM 层只需要验证 licenseJson,不需要发送 HTTP 请求
418
+ // Create engine instance, auth (online/offline) is handled by WASM layer via onOnlineAuth
386
419
  const enginePtr = Module.ccall(
387
- 'CreateBeautyEffectEngine',
420
+ 'CreateBeautyEffectEngineEx',
388
421
  'number',
389
- ['string', 'string'],
422
+ ['string', 'string', 'string', 'string', 'number'],
390
423
  [
391
424
  this.resourcePath,
392
- licenseJsonToUse || '' // 使用 licenseJson 验证
425
+ this.licenseJson || '',
426
+ this.appId || '',
427
+ this.appKey || '',
428
+ this.config.externalContext ? 1 : 0
393
429
  ]
394
430
  );
395
431
 
@@ -402,9 +438,9 @@ class BeautyEffectEngine {
402
438
 
403
439
  this.enginePtr = enginePtr;
404
440
  this.initialized = true;
405
- this._initPromise = null; // 清除 Promise 缓存,允许重新初始化(如果需要)
441
+ this._initPromise = null; // Clear Promise cache, allow re-initialization (if needed)
406
442
  } catch (error) {
407
- this._initPromise = null; // 清除 Promise 缓存,允许重试
443
+ this._initPromise = null; // Clear Promise cache, allow retry
408
444
  throw error;
409
445
  }
410
446
  })();
@@ -432,11 +468,18 @@ class BeautyEffectEngine {
432
468
  this.dstBufferPtr = null;
433
469
  }
434
470
 
471
+ // Clean up shared memory
472
+ if (this._callbackSharedBufferPtr) {
473
+ Module._free(this._callbackSharedBufferPtr);
474
+ this._callbackSharedBufferPtr = null;
475
+ this._callbackSharedBufferSize = 0;
476
+ }
477
+
435
478
  Module.ccall('DestroyBeautyEffectEngine', null, ['number'], [this.enginePtr]);
436
479
  this.enginePtr = null;
437
480
  this.initialized = false;
438
481
  this.bufferSize = 0;
439
- this._initPromise = null; // 清除初始化 Promise
482
+ this._initPromise = null; // Clear initialization Promise
440
483
 
441
484
  // Clean up offscreen canvas
442
485
  if (this._offscreenCanvas) {
@@ -541,7 +584,7 @@ class BeautyEffectEngine {
541
584
 
542
585
  /**
543
586
  * Sets a basic beauty parameter
544
- * @param {number} param - Parameter (use BasicParam enum)
587
+ * @param {number} param - Parameter (use BasicParam enum, e.g., BasicParam.Smoothing)
545
588
  * @param {number} value - Parameter value (0.0 - 1.0)
546
589
  */
547
590
  setBasicParam(param, value) {
@@ -551,7 +594,7 @@ class BeautyEffectEngine {
551
594
 
552
595
  /**
553
596
  * Sets a reshape parameter
554
- * @param {number} param - Parameter (use ReshapeParam enum)
597
+ * @param {number} param - Parameter (use ReshapeParam enum, e.g., ReshapeParam.FaceThinning)
555
598
  * @param {number} value - Parameter value (0.0 - 1.0)
556
599
  */
557
600
  setReshapeParam(param, value) {
@@ -561,7 +604,7 @@ class BeautyEffectEngine {
561
604
 
562
605
  /**
563
606
  * Sets a makeup parameter
564
- * @param {number} param - Parameter (use MakeupParam enum)
607
+ * @param {number} param - Parameter (use MakeupParam enum, e.g., MakeupParam.Lipstick)
565
608
  * @param {number} value - Parameter value (0.0 - 1.0)
566
609
  */
567
610
  setMakeupParam(param, value) {
@@ -569,6 +612,28 @@ class BeautyEffectEngine {
569
612
  this._setBeautyParam('SetBeautyParamMakeup', param, value);
570
613
  }
571
614
 
615
+ /**
616
+ * Sets chroma key parameter
617
+ * @param {number} param - Parameter (use ChromaKeyParam enum, e.g., ChromaKeyParam.Similarity)
618
+ * @param {number} value - Parameter value (KeyColor: 0.0=Green, 1.0=Blue, 2.0=Red; others 0.0-1.0)
619
+ */
620
+ setChromaKeyParam(param, value) {
621
+ this._ensureInitialized();
622
+ // For KeyColor, values are 0, 1, 2, not 0.0-1.0
623
+ if (param === 0) { // ChromaKeyParam.KeyColor
624
+ const Module = this._getWasmModule();
625
+ const result = Module.ccall(
626
+ 'SetBeautyParamChromaKey',
627
+ 'number',
628
+ ['number', 'number', 'number'],
629
+ [this.enginePtr, param, value]
630
+ );
631
+ checkResult(result, `Failed to set chroma key parameter`);
632
+ return;
633
+ }
634
+ this._setBeautyParam('SetBeautyParamChromaKey', param, value);
635
+ }
636
+
572
637
  /**
573
638
  * Internal method to set beauty parameters
574
639
  * @private
@@ -589,6 +654,139 @@ class BeautyEffectEngine {
589
654
  checkResult(result, `Failed to set beauty parameter`);
590
655
  }
591
656
 
657
+ /**
658
+ * Sets engine callbacks (face landmarks detection)
659
+ * @param {Object} callbacks - Callback functions
660
+ * @param {Function} callbacks.onFaceLandmarks - Callback for face landmarks detection
661
+ * @param {number} [callbacks.maxFaces=10] - Maximum number of faces to support (affects shared buffer size)
662
+ */
663
+ setCallbacks(callbacks) {
664
+ this._ensureInitialized();
665
+ const Module = this._getWasmModule();
666
+
667
+ // Initialize callback storage (if it doesn't exist)
668
+ if (!Module._face_landmarks_callbacks) {
669
+ Module._face_landmarks_callbacks = [];
670
+ }
671
+
672
+ let callbackId = 0;
673
+ let sharedBufferPtr = null;
674
+ let sharedBufferSize = 0;
675
+
676
+ if (callbacks && callbacks.onFaceLandmarks) {
677
+ // Get max faces (default 10)
678
+ const maxFaces = callbacks.maxFaces || 10;
679
+
680
+ // Pre-allocate shared memory
681
+ // Metadata: 2 ints (frame_number, face_count) = 8 bytes
682
+ // Face data: maxFaces * 343 floats * 4 bytes = maxFaces * 1372 bytes
683
+ const metadataSize = 2 * 4; // 2 ints
684
+ const faceDataSize = maxFaces * 343 * 4; // 343 floats per face
685
+ sharedBufferSize = metadataSize + faceDataSize;
686
+ sharedBufferPtr = Module._malloc(sharedBufferSize);
687
+
688
+ if (!sharedBufferPtr) {
689
+ throw new FacebetterError('Failed to allocate shared buffer for callbacks');
690
+ }
691
+
692
+ // Register callback function (internal wrapper, reads data from shared memory)
693
+ // Push first, then get index as callbackId (allows callbackId to be 0)
694
+ Module._face_landmarks_callbacks.push(
695
+ (frameNumber, faceCount, dataPtr) => {
696
+ // Read data from shared memory (zero-copy)
697
+ const heap = Module.HEAPF32;
698
+ const dataOffset = dataPtr / 4; // float is 4 bytes
699
+
700
+ const results = [];
701
+ const FLOATS_PER_FACE = 343;
702
+
703
+ for (let i = 0; i < faceCount; i++) {
704
+ const faceOffset = dataOffset + i * FLOATS_PER_FACE;
705
+ let offset = faceOffset;
706
+
707
+ // Read rect
708
+ const rect = {
709
+ x: heap[offset++],
710
+ y: heap[offset++],
711
+ width: heap[offset++],
712
+ height: heap[offset++]
713
+ };
714
+
715
+ // Read basic fields
716
+ const faceId = Math.round(heap[offset++]);
717
+ const faceAction = Math.round(heap[offset++]);
718
+ const score = heap[offset++];
719
+ const pitch = heap[offset++];
720
+ const roll = heap[offset++];
721
+ const yaw = heap[offset++];
722
+
723
+ // Read key_points (111 points)
724
+ const keyPoints = [];
725
+ for (let j = 0; j < 111; j++) {
726
+ keyPoints.push({
727
+ x: heap[offset++],
728
+ y: heap[offset++]
729
+ });
730
+ }
731
+
732
+ // Read visibility (111 points)
733
+ const visibility = [];
734
+ for (let j = 0; j < 111; j++) {
735
+ visibility.push(heap[offset++]);
736
+ }
737
+
738
+ results.push({
739
+ rect,
740
+ key_points: keyPoints,
741
+ visibility,
742
+ face_id: faceId,
743
+ face_action: faceAction,
744
+ score,
745
+ pitch,
746
+ roll,
747
+ yaw
748
+ });
749
+ }
750
+
751
+ // Call user callback
752
+ callbacks.onFaceLandmarks(results);
753
+ }
754
+ );
755
+
756
+ // Get callback ID (index after push, can be 0)
757
+ callbackId = Module._face_landmarks_callbacks.length - 1;
758
+ }
759
+
760
+ // Call C API
761
+ const result = Module.ccall(
762
+ 'SetCallbacks',
763
+ 'number',
764
+ ['number', 'number', 'number', 'number'],
765
+ [
766
+ this.enginePtr,
767
+ callbackId,
768
+ sharedBufferPtr || 0,
769
+ sharedBufferSize
770
+ ]
771
+ );
772
+
773
+ checkResult(result, 'Failed to set callbacks');
774
+
775
+ // Clean up old shared memory (if it exists)
776
+ if (this._callbackSharedBufferPtr) {
777
+ Module._free(this._callbackSharedBufferPtr);
778
+ }
779
+
780
+ // Store new shared memory pointer for cleanup
781
+ if (sharedBufferPtr) {
782
+ this._callbackSharedBufferPtr = sharedBufferPtr;
783
+ this._callbackSharedBufferSize = sharedBufferSize;
784
+ } else {
785
+ this._callbackSharedBufferPtr = null;
786
+ this._callbackSharedBufferSize = 0;
787
+ }
788
+ }
789
+
592
790
  /**
593
791
  * Sets virtual background options (unified API, matches C++/Java/OC)
594
792
  * @param {VirtualBackgroundOptions|Object} options - Virtual background options
@@ -606,7 +804,7 @@ class BeautyEffectEngine {
606
804
  let imageBufferPtr = null;
607
805
 
608
806
  try {
609
- // 如果提供了背景图片,转换为 ImageData 并准备缓冲区
807
+ // If a background image is provided, convert to ImageData and prepare buffer
610
808
  if (opts.backgroundImage) {
611
809
  imageData = this._toImageData(opts.backgroundImage);
612
810
  const bufferSize = imageData.width * imageData.height * 4;
@@ -617,7 +815,7 @@ class BeautyEffectEngine {
617
815
  view.set(imageData.data);
618
816
  }
619
817
 
620
- // 使用统一的 SetVirtualBackground C 接口(与其他平台一致)
818
+ // Use unified SetVirtualBackground C interface (consistent with other platforms)
621
819
  const result = Module.ccall(
622
820
  'SetVirtualBackground',
623
821
  'number',
@@ -625,7 +823,7 @@ class BeautyEffectEngine {
625
823
  [
626
824
  this.enginePtr,
627
825
  opts.mode,
628
- imageBufferPtr || 0, // 如果为 null,传递 0
826
+ imageBufferPtr || 0, // If null, pass 0
629
827
  imageData ? imageData.width : 0,
630
828
  imageData ? imageData.height : 0,
631
829
  imageData ? imageData.width * 4 : 0
@@ -634,7 +832,7 @@ class BeautyEffectEngine {
634
832
 
635
833
  checkResult(result, 'Failed to set virtual background');
636
834
  } finally {
637
- // 释放内存
835
+ // Free memory
638
836
  if (imageBufferPtr) {
639
837
  Module._free(imageBufferPtr);
640
838
  }
@@ -674,10 +872,10 @@ class BeautyEffectEngine {
674
872
  * @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|Uint8ClampedArray} input - Input image
675
873
  * @param {number} width - Image width (required if input is Uint8ClampedArray)
676
874
  * @param {number} height - Image height (required if input is Uint8ClampedArray)
677
- * @param {number} processMode - Process mode (use ProcessMode enum, default: ProcessMode.Image)
875
+ * @param {number} frameType - Frame type (use FrameType enum, default: FrameType.Video)
678
876
  * @returns {ImageData} Processed image data
679
877
  */
680
- processImage(input, width, height, processMode = ProcessMode$1.Image) {
878
+ processImage(input, width, height, frameType = FrameType$1.Video) {
681
879
  this._ensureInitialized();
682
880
  const imageData = this._platformAPI.toImageData(input, width, height);
683
881
  const Module = this._getWasmModule();
@@ -703,7 +901,7 @@ class BeautyEffectEngine {
703
901
  imageData.height,
704
902
  imageData.width * 4,
705
903
  this.dstBufferPtr,
706
- processMode
904
+ frameType
707
905
  ]
708
906
  );
709
907
 
@@ -722,6 +920,62 @@ class BeautyEffectEngine {
722
920
  }
723
921
  }
724
922
 
923
+ /**
924
+ * Processes an external GPU texture.
925
+ *
926
+ * Note:
927
+ * - This interface is mainly used for integration with internal WASM or advanced scenarios.
928
+ * - textureHandle must be a texture handle (uint32) compatible with the OpenGL/WebGL context used by WASM.
929
+ * - For common web scenarios, it is recommended to use processImage with ImageData/Canvas etc.
930
+ *
931
+ * @param {number} textureHandle - External texture handle (GL_TEXTURE_2D)
932
+ * @param {number} width - Texture width
933
+ * @param {number} height - Texture height
934
+ * @param {number} stride - Row stride (usually width * 4)
935
+ * @param {number} [frameType] - Frame type (FrameType.Image / FrameType.Video)
936
+ * @returns {number} Processed texture handle (GL_TEXTURE_2D, uint32)
937
+ */
938
+ processTexture(textureHandle,
939
+ width,
940
+ height,
941
+ stride,
942
+ frameType = FrameType$1.Video) {
943
+ this._ensureInitialized();
944
+ if (!textureHandle || width <= 0 || height <= 0 || stride <= 0) {
945
+ throw new FacebetterError('Invalid textureHandle or dimensions for processTexture');
946
+ }
947
+
948
+ const Module = this._getWasmModule();
949
+
950
+ try {
951
+ const result = Module.ccall(
952
+ 'ProcessImageTexture',
953
+ 'number',
954
+ ['number', 'number', 'number', 'number', 'number', 'number'],
955
+ [
956
+ this.enginePtr,
957
+ textureHandle,
958
+ width,
959
+ height,
960
+ stride,
961
+ frameType
962
+ ]
963
+ );
964
+
965
+ if (!result || result === 0) {
966
+ throw new FacebetterError('Failed to process external texture or got invalid output texture');
967
+ }
968
+
969
+ // Return processed texture handle for caller to continue using in same GL context
970
+ return result;
971
+ } catch (error) {
972
+ if (error instanceof FacebetterError) {
973
+ throw error;
974
+ }
975
+ throw new FacebetterError(`Texture processing error: ${error.message}`);
976
+ }
977
+ }
978
+
725
979
  /**
726
980
  * Ensures the engine is initialized
727
981
  * @private
@@ -791,6 +1045,15 @@ class BeautyEffectEngine {
791
1045
  return this._offscreenCanvas;
792
1046
  }
793
1047
 
1048
+ /**
1049
+ * Internal method for online authentication (Deprecated: logic moved to WASM layer)
1050
+ * @private
1051
+ */
1052
+ async _verifyAppKeyOnline(appId, appKey) {
1053
+ // This method is now deprecated as logic is moved to WASM layer via Module.onOnlineAuth
1054
+ return null;
1055
+ }
1056
+
794
1057
  }
795
1058
 
796
1059
  /**
@@ -896,7 +1159,7 @@ async function verifyAppKeyOnline(appId, appKey) {
896
1159
  p_user_agent: getUserAgentString()
897
1160
  };
898
1161
 
899
- const response = await fetch('https://facebetter.pixpark.net/rest/v1/rpc/online_auth', {
1162
+ const response = await fetch('https://facebetter.pixpark.net/rest/v1/rpc/online_auth_v2', {
900
1163
  method: 'POST',
901
1164
  headers: {
902
1165
  'Content-Type': 'application/json',
@@ -1078,8 +1341,9 @@ const BeautyType = BeautyType$1;
1078
1341
  const BasicParam = BasicParam$1;
1079
1342
  const ReshapeParam = ReshapeParam$1;
1080
1343
  const MakeupParam = MakeupParam$1;
1344
+ const ChromaKeyParam = ChromaKeyParam$1;
1081
1345
  const BackgroundMode = BackgroundMode$1;
1082
- const ProcessMode = ProcessMode$1;
1346
+ const FrameType = FrameType$1;
1083
1347
  const VirtualBackgroundOptions = VirtualBackgroundOptions$1;
1084
1348
 
1085
1349
  // Default export
@@ -1091,5 +1355,5 @@ var index = {
1091
1355
  loadWasmModule
1092
1356
  };
1093
1357
 
1094
- export { BackgroundMode, BasicParam, ESMBeautyEffectEngine as BeautyEffectEngine, BeautyType, EngineConfig, FacebetterError, MakeupParam, ProcessMode, ReshapeParam, VirtualBackgroundOptions, createBeautyEffectEngine, index as default, getWasmBuffer, getWasmModule, loadWasmModule };
1358
+ export { BackgroundMode, BasicParam, ESMBeautyEffectEngine as BeautyEffectEngine, BeautyType, ChromaKeyParam, EngineConfig, FacebetterError, FrameType, MakeupParam, ReshapeParam, VirtualBackgroundOptions, createBeautyEffectEngine, index as default, getWasmBuffer, getWasmModule, loadWasmModule };
1095
1359
  //# sourceMappingURL=facebetter.esm.js.map