facebetter 1.0.14 → 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.
@@ -54,6 +54,12 @@
54
54
  this.appKey = config.appKey || null;
55
55
  this.licenseJson = config.licenseJson || null;
56
56
  this.resourcePath = '/facebetter/resource.bundle';
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
- // 如果提供了 licenseJson,则使用授权数据验证
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
- // 否则需要 appId appKey
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,75 @@
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)
95
102
  };
96
103
 
97
104
  /**
98
105
  * Basic beauty parameter enumeration
106
+ * All values should be in range [0.0, 1.0]
99
107
  */
100
108
  const BasicParam$1 = {
101
- Smoothing: 0, // 磨皮
102
- Sharpening: 1, // 锐化
103
- Whitening: 2, // 美白
104
- Rosiness: 3 // 红润
109
+ Smoothing: 0, // Skin smoothing (0.0: none, 1.0: maximum)
110
+ Sharpening: 1, // Image sharpening (0.0: none, 1.0: maximum)
111
+ Whitening: 2, // Skin whitening (0.0: none, 1.0: maximum)
112
+ Rosiness: 3 // Skin rosiness (0.0: none, 1.0: maximum)
105
113
  };
106
114
 
107
115
  /**
108
116
  * Face reshape parameter enumeration
117
+ * All values should be in range [0.0, 1.0]
109
118
  */
110
119
  const ReshapeParam$1 = {
111
- FaceThin: 0, // 瘦脸
112
- FaceVShape: 1, // V
113
- FaceNarrow: 2, // 窄脸
114
- FaceShort: 3, // 短脸
115
- Cheekbone: 4, // 颧骨
116
- Jawbone: 5, // 下颌骨
117
- Chin: 6, // 下巴
118
- NoseSlim: 7, // 瘦鼻梁
119
- EyeSize: 8, // 大眼
120
- EyeDistance: 9 // 眼距
120
+ FaceThinning: 0, // Face thinning (0.0: none, 1.0: maximum)
121
+ FaceVShape: 1, // V-shape face (0.0: none, 1.0: maximum)
122
+ FaceNarrowing: 2, // Face narrowing (0.0: none, 1.0: maximum)
123
+ FaceShortening: 3,// Face shortening (0.0: none, 1.0: maximum)
124
+ Cheekbone: 4, // Cheekbone slimming (0.0: none, 1.0: maximum)
125
+ Jawbone: 5, // Jawbone slimming (0.0: none, 1.0: maximum)
126
+ Chin: 6, // Chin length adjustment (0.0: none, 1.0: maximum)
127
+ NoseSlimming: 7, // Nose slimming (0.0: none, 1.0: maximum)
128
+ EyeSize: 8, // Eye size (0.0: normal, 1.0: maximum)
129
+ EyeDistance: 9 // Eye distance (0.0: normal, 1.0: maximum)
121
130
  };
122
131
 
123
132
  /**
124
133
  * Makeup parameter enumeration
134
+ * All values should be in range [0.0, 1.0]
125
135
  */
126
136
  const MakeupParam$1 = {
127
- Lipstick: 0, // 口红
128
- Blush: 1 // 腮红
137
+ Lipstick: 0, // Lipstick intensity (0.0: none, 1.0: maximum)
138
+ Blush: 1 // Blush intensity (0.0: none, 1.0: maximum)
139
+ };
140
+
141
+ /**
142
+ * Chroma Key parameter enumeration
143
+ */
144
+ const ChromaKeyParam = {
145
+ KeyColor: 0, // Key color (0.0: Green, 1.0: Blue, 2.0: Red)
146
+ Similarity: 1, // Color similarity (0.0 - 1.0)
147
+ Smoothness: 2, // Edge smoothness (0.0 - 1.0)
148
+ Desaturation: 3 // Spill desaturation (0.0 - 1.0)
129
149
  };
130
150
 
131
151
  /**
132
152
  * Background mode enumeration
133
153
  */
134
154
  const BackgroundMode$1 = {
135
- None: 0, // 无背景处理
136
- Blur: 1, // 模糊背景
137
- Image: 2 // 背景图片替换
155
+ None: 0, // No background processing
156
+ Blur: 1, // Blurred background
157
+ Image: 2 // Background image replacement
138
158
  };
139
159
 
140
160
  /**
141
- * Process mode enumeration
161
+ * Frame type enumeration
142
162
  */
143
- const ProcessMode$1 = {
144
- Image: 0, // 图片模式
145
- Video: 1 // 视频模式
163
+ const FrameType$1 = {
164
+ Image: 0, // Image mode
165
+ Video: 1 // Video mode
146
166
  };
147
167
 
148
168
  /**
@@ -178,8 +198,9 @@
178
198
  BackgroundMode: BackgroundMode$1,
179
199
  BasicParam: BasicParam$1,
180
200
  BeautyType: BeautyType$1,
201
+ ChromaKeyParam: ChromaKeyParam,
202
+ FrameType: FrameType$1,
181
203
  MakeupParam: MakeupParam$1,
182
- ProcessMode: ProcessMode$1,
183
204
  ReshapeParam: ReshapeParam$1,
184
205
  VirtualBackgroundOptions: VirtualBackgroundOptions$1
185
206
  });
@@ -217,7 +238,7 @@
217
238
  throw new FacebetterError('Platform API is required');
218
239
  }
219
240
 
220
- // 如果传入的是 EngineConfig 实例,直接使用;否则创建新的 EngineConfig
241
+ // If an EngineConfig instance is passed, use it directly; otherwise create a new EngineConfig
221
242
  let engineConfig;
222
243
  if (config instanceof EngineConfig) {
223
244
  engineConfig = config;
@@ -242,6 +263,10 @@
242
263
  this.dstBufferPtr = null;
243
264
  this.bufferSize = 0;
244
265
 
266
+ // Callback related state
267
+ this._callbackSharedBufferPtr = null;
268
+ this._callbackSharedBufferSize = 0;
269
+
245
270
  // Store platform API
246
271
  this._platformAPI = platformAPI;
247
272
  this._loadWasmModule = platformAPI.loadWasmModule;
@@ -326,23 +351,22 @@
326
351
  * @returns {Promise<void>} Promise that resolves when initialization is complete
327
352
  */
328
353
  async init(options = {}) {
329
- // 并发控制:如果已经初始化,直接返回
354
+ // Concurrency control: if already initialized, return immediately
330
355
  if (this.initialized) {
331
356
  return;
332
357
  }
333
358
 
334
- // 并发控制:如果正在初始化,返回同一个 Promise
359
+ // Concurrency control: if initialization is in progress, return the same Promise
335
360
  if (this._initPromise) {
336
361
  return this._initPromise;
337
362
  }
338
363
 
339
- // 创建初始化 Promise
364
+ // Create initialization Promise
340
365
  this._initPromise = (async () => {
341
366
  try {
342
367
  const wasmTimeout = options.timeout || 30000;
343
- const authTimeout = options.authTimeout || 10000;
344
368
 
345
- // 等待 WASM 模块加载(带超时)
369
+ // Wait for WASM module loading (with timeout)
346
370
  try {
347
371
  await Promise.race([
348
372
  this._wasmLoadPromise,
@@ -354,48 +378,60 @@
354
378
 
355
379
  const Module = this._getWasmModule();
356
380
 
357
- let licenseJsonToUse = this.licenseJson;
358
-
359
- // 如果用户提供了 appId appKey(但没有提供 licenseJson),则在 JS 层发送 HTTP 请求
360
- if (this.appId && this.appKey && !this.licenseJson && this._verifyAppKeyOnline) {
361
- try {
362
- // 在线认证(带超时)
363
- const authResponse = await Promise.race([
364
- this._verifyAppKeyOnline(this.appId, this.appKey),
365
- this._createTimeout(authTimeout, 'Online authentication')
366
- ]);
367
-
368
- if (!authResponse) {
369
- throw new FacebetterError(
370
- 'Failed to get server response from online_auth API. The server returned an empty response.',
371
- 'AUTH_EMPTY_RESPONSE'
372
- );
381
+ // Setup usage report proxy for WASM
382
+ if (!Module.onReportUsage) {
383
+ Module.onReportUsage = async (payloadJson) => {
384
+ try {
385
+ const url = 'https://facebetter.pixpark.net/rest/v1/rpc/report_sdk_usage';
386
+ const response = await fetch(url, {
387
+ method: 'POST',
388
+ headers: {
389
+ 'Content-Type': 'application/json'
390
+ },
391
+ body: payloadJson
392
+ });
393
+ return response.ok;
394
+ } catch (error) {
395
+ return false;
373
396
  }
397
+ };
398
+ }
374
399
 
375
- // 将服务器响应转换为 JSON 字符串,作为 licenseJson 传递给 WASM
376
- licenseJsonToUse = JSON.stringify(authResponse);
377
- console.log('Online auth response received, using as licenseJson');
378
- } catch (error) {
379
- if (error instanceof FacebetterError && error.code === 'TIMEOUT') {
380
- throw new FacebetterError(
381
- `Online authentication timed out after ${authTimeout}ms. Please check your network connection or provide licenseJson directly.`,
382
- 'AUTH_TIMEOUT'
383
- );
400
+ // Setup online auth proxy for WASM
401
+ if (!Module.onOnlineAuth) {
402
+ Module.onOnlineAuth = async (payloadJson) => {
403
+ try {
404
+ const url = 'https://facebetter.pixpark.net/rest/v1/rpc/online_auth_v2';
405
+ const response = await fetch(url, {
406
+ method: 'POST',
407
+ headers: {
408
+ 'Content-Type': 'application/json'
409
+ },
410
+ body: payloadJson
411
+ });
412
+ if (!response.ok) {
413
+ console.warn('[JS Engine] Online auth fetch failed with status:', response.status);
414
+ return "";
415
+ }
416
+ return await response.text();
417
+ } catch (error) {
418
+ console.error('[JS Engine] Online auth fetch exception:', error);
419
+ return "";
384
420
  }
385
- throw this._enhanceError(error, 'Failed to verify app key online');
386
- }
421
+ };
387
422
  }
388
423
 
389
- // 如果用户直接提供了 licenseJson,则直接使用
390
- // 如果通过 appId/appKey 获取到了响应,则使用响应作为 licenseJson
391
- // WASM 层只需要验证 licenseJson,不需要发送 HTTP 请求
424
+ // Create engine instance, auth (online/offline) is handled by WASM layer via onOnlineAuth
392
425
  const enginePtr = Module.ccall(
393
- 'CreateBeautyEffectEngine',
426
+ 'CreateBeautyEffectEngineEx',
394
427
  'number',
395
- ['string', 'string'],
428
+ ['string', 'string', 'string', 'string', 'number'],
396
429
  [
397
430
  this.resourcePath,
398
- licenseJsonToUse || '' // 使用 licenseJson 验证
431
+ this.licenseJson || '',
432
+ this.appId || '',
433
+ this.appKey || '',
434
+ this.config.externalContext ? 1 : 0
399
435
  ]
400
436
  );
401
437
 
@@ -408,9 +444,9 @@
408
444
 
409
445
  this.enginePtr = enginePtr;
410
446
  this.initialized = true;
411
- this._initPromise = null; // 清除 Promise 缓存,允许重新初始化(如果需要)
447
+ this._initPromise = null; // Clear Promise cache, allow re-initialization (if needed)
412
448
  } catch (error) {
413
- this._initPromise = null; // 清除 Promise 缓存,允许重试
449
+ this._initPromise = null; // Clear Promise cache, allow retry
414
450
  throw error;
415
451
  }
416
452
  })();
@@ -438,11 +474,18 @@
438
474
  this.dstBufferPtr = null;
439
475
  }
440
476
 
477
+ // Clean up shared memory
478
+ if (this._callbackSharedBufferPtr) {
479
+ Module._free(this._callbackSharedBufferPtr);
480
+ this._callbackSharedBufferPtr = null;
481
+ this._callbackSharedBufferSize = 0;
482
+ }
483
+
441
484
  Module.ccall('DestroyBeautyEffectEngine', null, ['number'], [this.enginePtr]);
442
485
  this.enginePtr = null;
443
486
  this.initialized = false;
444
487
  this.bufferSize = 0;
445
- this._initPromise = null; // 清除初始化 Promise
488
+ this._initPromise = null; // Clear initialization Promise
446
489
 
447
490
  // Clean up offscreen canvas
448
491
  if (this._offscreenCanvas) {
@@ -547,7 +590,7 @@
547
590
 
548
591
  /**
549
592
  * Sets a basic beauty parameter
550
- * @param {number} param - Parameter (use BasicParam enum)
593
+ * @param {number} param - Parameter (use BasicParam enum, e.g., BasicParam.Smoothing)
551
594
  * @param {number} value - Parameter value (0.0 - 1.0)
552
595
  */
553
596
  setBasicParam(param, value) {
@@ -557,7 +600,7 @@
557
600
 
558
601
  /**
559
602
  * Sets a reshape parameter
560
- * @param {number} param - Parameter (use ReshapeParam enum)
603
+ * @param {number} param - Parameter (use ReshapeParam enum, e.g., ReshapeParam.FaceThinning)
561
604
  * @param {number} value - Parameter value (0.0 - 1.0)
562
605
  */
563
606
  setReshapeParam(param, value) {
@@ -567,7 +610,7 @@
567
610
 
568
611
  /**
569
612
  * Sets a makeup parameter
570
- * @param {number} param - Parameter (use MakeupParam enum)
613
+ * @param {number} param - Parameter (use MakeupParam enum, e.g., MakeupParam.Lipstick)
571
614
  * @param {number} value - Parameter value (0.0 - 1.0)
572
615
  */
573
616
  setMakeupParam(param, value) {
@@ -575,6 +618,28 @@
575
618
  this._setBeautyParam('SetBeautyParamMakeup', param, value);
576
619
  }
577
620
 
621
+ /**
622
+ * Sets chroma key parameter
623
+ * @param {number} param - Parameter (use ChromaKeyParam enum, e.g., ChromaKeyParam.Similarity)
624
+ * @param {number} value - Parameter value (KeyColor: 0.0=Green, 1.0=Blue, 2.0=Red; others 0.0-1.0)
625
+ */
626
+ setChromaKeyParam(param, value) {
627
+ this._ensureInitialized();
628
+ // For KeyColor, values are 0, 1, 2, not 0.0-1.0
629
+ if (param === 0) { // ChromaKeyParam.KeyColor
630
+ const Module = this._getWasmModule();
631
+ const result = Module.ccall(
632
+ 'SetBeautyParamChromaKey',
633
+ 'number',
634
+ ['number', 'number', 'number'],
635
+ [this.enginePtr, param, value]
636
+ );
637
+ checkResult(result, `Failed to set chroma key parameter`);
638
+ return;
639
+ }
640
+ this._setBeautyParam('SetBeautyParamChromaKey', param, value);
641
+ }
642
+
578
643
  /**
579
644
  * Internal method to set beauty parameters
580
645
  * @private
@@ -595,6 +660,139 @@
595
660
  checkResult(result, `Failed to set beauty parameter`);
596
661
  }
597
662
 
663
+ /**
664
+ * Sets engine callbacks (face landmarks detection)
665
+ * @param {Object} callbacks - Callback functions
666
+ * @param {Function} callbacks.onFaceLandmarks - Callback for face landmarks detection
667
+ * @param {number} [callbacks.maxFaces=10] - Maximum number of faces to support (affects shared buffer size)
668
+ */
669
+ setCallbacks(callbacks) {
670
+ this._ensureInitialized();
671
+ const Module = this._getWasmModule();
672
+
673
+ // Initialize callback storage (if it doesn't exist)
674
+ if (!Module._face_landmarks_callbacks) {
675
+ Module._face_landmarks_callbacks = [];
676
+ }
677
+
678
+ let callbackId = 0;
679
+ let sharedBufferPtr = null;
680
+ let sharedBufferSize = 0;
681
+
682
+ if (callbacks && callbacks.onFaceLandmarks) {
683
+ // Get max faces (default 10)
684
+ const maxFaces = callbacks.maxFaces || 10;
685
+
686
+ // Pre-allocate shared memory
687
+ // Metadata: 2 ints (frame_number, face_count) = 8 bytes
688
+ // Face data: maxFaces * 343 floats * 4 bytes = maxFaces * 1372 bytes
689
+ const metadataSize = 2 * 4; // 2 ints
690
+ const faceDataSize = maxFaces * 343 * 4; // 343 floats per face
691
+ sharedBufferSize = metadataSize + faceDataSize;
692
+ sharedBufferPtr = Module._malloc(sharedBufferSize);
693
+
694
+ if (!sharedBufferPtr) {
695
+ throw new FacebetterError('Failed to allocate shared buffer for callbacks');
696
+ }
697
+
698
+ // Register callback function (internal wrapper, reads data from shared memory)
699
+ // Push first, then get index as callbackId (allows callbackId to be 0)
700
+ Module._face_landmarks_callbacks.push(
701
+ (frameNumber, faceCount, dataPtr) => {
702
+ // Read data from shared memory (zero-copy)
703
+ const heap = Module.HEAPF32;
704
+ const dataOffset = dataPtr / 4; // float is 4 bytes
705
+
706
+ const results = [];
707
+ const FLOATS_PER_FACE = 343;
708
+
709
+ for (let i = 0; i < faceCount; i++) {
710
+ const faceOffset = dataOffset + i * FLOATS_PER_FACE;
711
+ let offset = faceOffset;
712
+
713
+ // Read rect
714
+ const rect = {
715
+ x: heap[offset++],
716
+ y: heap[offset++],
717
+ width: heap[offset++],
718
+ height: heap[offset++]
719
+ };
720
+
721
+ // Read basic fields
722
+ const faceId = Math.round(heap[offset++]);
723
+ const faceAction = Math.round(heap[offset++]);
724
+ const score = heap[offset++];
725
+ const pitch = heap[offset++];
726
+ const roll = heap[offset++];
727
+ const yaw = heap[offset++];
728
+
729
+ // Read key_points (111 points)
730
+ const keyPoints = [];
731
+ for (let j = 0; j < 111; j++) {
732
+ keyPoints.push({
733
+ x: heap[offset++],
734
+ y: heap[offset++]
735
+ });
736
+ }
737
+
738
+ // Read visibility (111 points)
739
+ const visibility = [];
740
+ for (let j = 0; j < 111; j++) {
741
+ visibility.push(heap[offset++]);
742
+ }
743
+
744
+ results.push({
745
+ rect,
746
+ key_points: keyPoints,
747
+ visibility,
748
+ face_id: faceId,
749
+ face_action: faceAction,
750
+ score,
751
+ pitch,
752
+ roll,
753
+ yaw
754
+ });
755
+ }
756
+
757
+ // Call user callback
758
+ callbacks.onFaceLandmarks(results);
759
+ }
760
+ );
761
+
762
+ // Get callback ID (index after push, can be 0)
763
+ callbackId = Module._face_landmarks_callbacks.length - 1;
764
+ }
765
+
766
+ // Call C API
767
+ const result = Module.ccall(
768
+ 'SetCallbacks',
769
+ 'number',
770
+ ['number', 'number', 'number', 'number'],
771
+ [
772
+ this.enginePtr,
773
+ callbackId,
774
+ sharedBufferPtr || 0,
775
+ sharedBufferSize
776
+ ]
777
+ );
778
+
779
+ checkResult(result, 'Failed to set callbacks');
780
+
781
+ // Clean up old shared memory (if it exists)
782
+ if (this._callbackSharedBufferPtr) {
783
+ Module._free(this._callbackSharedBufferPtr);
784
+ }
785
+
786
+ // Store new shared memory pointer for cleanup
787
+ if (sharedBufferPtr) {
788
+ this._callbackSharedBufferPtr = sharedBufferPtr;
789
+ this._callbackSharedBufferSize = sharedBufferSize;
790
+ } else {
791
+ this._callbackSharedBufferPtr = null;
792
+ this._callbackSharedBufferSize = 0;
793
+ }
794
+ }
795
+
598
796
  /**
599
797
  * Sets virtual background options (unified API, matches C++/Java/OC)
600
798
  * @param {VirtualBackgroundOptions|Object} options - Virtual background options
@@ -612,7 +810,7 @@
612
810
  let imageBufferPtr = null;
613
811
 
614
812
  try {
615
- // 如果提供了背景图片,转换为 ImageData 并准备缓冲区
813
+ // If a background image is provided, convert to ImageData and prepare buffer
616
814
  if (opts.backgroundImage) {
617
815
  imageData = this._toImageData(opts.backgroundImage);
618
816
  const bufferSize = imageData.width * imageData.height * 4;
@@ -623,7 +821,7 @@
623
821
  view.set(imageData.data);
624
822
  }
625
823
 
626
- // 使用统一的 SetVirtualBackground C 接口(与其他平台一致)
824
+ // Use unified SetVirtualBackground C interface (consistent with other platforms)
627
825
  const result = Module.ccall(
628
826
  'SetVirtualBackground',
629
827
  'number',
@@ -631,7 +829,7 @@
631
829
  [
632
830
  this.enginePtr,
633
831
  opts.mode,
634
- imageBufferPtr || 0, // 如果为 null,传递 0
832
+ imageBufferPtr || 0, // If null, pass 0
635
833
  imageData ? imageData.width : 0,
636
834
  imageData ? imageData.height : 0,
637
835
  imageData ? imageData.width * 4 : 0
@@ -640,7 +838,7 @@
640
838
 
641
839
  checkResult(result, 'Failed to set virtual background');
642
840
  } finally {
643
- // 释放内存
841
+ // Free memory
644
842
  if (imageBufferPtr) {
645
843
  Module._free(imageBufferPtr);
646
844
  }
@@ -680,10 +878,10 @@
680
878
  * @param {ImageData|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|Uint8ClampedArray} input - Input image
681
879
  * @param {number} width - Image width (required if input is Uint8ClampedArray)
682
880
  * @param {number} height - Image height (required if input is Uint8ClampedArray)
683
- * @param {number} processMode - Process mode (use ProcessMode enum, default: ProcessMode.Image)
881
+ * @param {number} frameType - Frame type (use FrameType enum, default: FrameType.Video)
684
882
  * @returns {ImageData} Processed image data
685
883
  */
686
- processImage(input, width, height, processMode = ProcessMode$1.Image) {
884
+ processImage(input, width, height, frameType = FrameType$1.Video) {
687
885
  this._ensureInitialized();
688
886
  const imageData = this._platformAPI.toImageData(input, width, height);
689
887
  const Module = this._getWasmModule();
@@ -709,7 +907,7 @@
709
907
  imageData.height,
710
908
  imageData.width * 4,
711
909
  this.dstBufferPtr,
712
- processMode
910
+ frameType
713
911
  ]
714
912
  );
715
913
 
@@ -728,6 +926,62 @@
728
926
  }
729
927
  }
730
928
 
929
+ /**
930
+ * Processes an external GPU texture.
931
+ *
932
+ * Note:
933
+ * - This interface is mainly used for integration with internal WASM or advanced scenarios.
934
+ * - textureHandle must be a texture handle (uint32) compatible with the OpenGL/WebGL context used by WASM.
935
+ * - For common web scenarios, it is recommended to use processImage with ImageData/Canvas etc.
936
+ *
937
+ * @param {number} textureHandle - External texture handle (GL_TEXTURE_2D)
938
+ * @param {number} width - Texture width
939
+ * @param {number} height - Texture height
940
+ * @param {number} stride - Row stride (usually width * 4)
941
+ * @param {number} [frameType] - Frame type (FrameType.Image / FrameType.Video)
942
+ * @returns {number} Processed texture handle (GL_TEXTURE_2D, uint32)
943
+ */
944
+ processTexture(textureHandle,
945
+ width,
946
+ height,
947
+ stride,
948
+ frameType = FrameType$1.Video) {
949
+ this._ensureInitialized();
950
+ if (!textureHandle || width <= 0 || height <= 0 || stride <= 0) {
951
+ throw new FacebetterError('Invalid textureHandle or dimensions for processTexture');
952
+ }
953
+
954
+ const Module = this._getWasmModule();
955
+
956
+ try {
957
+ const result = Module.ccall(
958
+ 'ProcessImageTexture',
959
+ 'number',
960
+ ['number', 'number', 'number', 'number', 'number', 'number'],
961
+ [
962
+ this.enginePtr,
963
+ textureHandle,
964
+ width,
965
+ height,
966
+ stride,
967
+ frameType
968
+ ]
969
+ );
970
+
971
+ if (!result || result === 0) {
972
+ throw new FacebetterError('Failed to process external texture or got invalid output texture');
973
+ }
974
+
975
+ // Return processed texture handle for caller to continue using in same GL context
976
+ return result;
977
+ } catch (error) {
978
+ if (error instanceof FacebetterError) {
979
+ throw error;
980
+ }
981
+ throw new FacebetterError(`Texture processing error: ${error.message}`);
982
+ }
983
+ }
984
+
731
985
  /**
732
986
  * Ensures the engine is initialized
733
987
  * @private
@@ -797,6 +1051,15 @@
797
1051
  return this._offscreenCanvas;
798
1052
  }
799
1053
 
1054
+ /**
1055
+ * Internal method for online authentication (Deprecated: logic moved to WASM layer)
1056
+ * @private
1057
+ */
1058
+ async _verifyAppKeyOnline(appId, appKey) {
1059
+ // This method is now deprecated as logic is moved to WASM layer via Module.onOnlineAuth
1060
+ return null;
1061
+ }
1062
+
800
1063
  }
801
1064
 
802
1065
  /**
@@ -1109,7 +1372,7 @@
1109
1372
  p_user_agent: getUserAgentString()
1110
1373
  };
1111
1374
 
1112
- const response = await fetch('https://facebetter.pixpark.net/rest/v1/rpc/online_auth', {
1375
+ const response = await fetch('https://facebetter.pixpark.net/rest/v1/rpc/online_auth_v2', {
1113
1376
  method: 'POST',
1114
1377
  headers: {
1115
1378
  'Content-Type': 'application/json',
@@ -1187,7 +1450,7 @@
1187
1450
  const ReshapeParam = ReshapeParam$1;
1188
1451
  const MakeupParam = MakeupParam$1;
1189
1452
  const BackgroundMode = BackgroundMode$1;
1190
- const ProcessMode = ProcessMode$1;
1453
+ const FrameType = FrameType$1;
1191
1454
  const VirtualBackgroundOptions = VirtualBackgroundOptions$1;
1192
1455
 
1193
1456
  // Default export
@@ -1205,8 +1468,8 @@
1205
1468
  exports.BeautyType = BeautyType;
1206
1469
  exports.EngineConfig = EngineConfig;
1207
1470
  exports.FacebetterError = FacebetterError;
1471
+ exports.FrameType = FrameType;
1208
1472
  exports.MakeupParam = MakeupParam;
1209
- exports.ProcessMode = ProcessMode;
1210
1473
  exports.ReshapeParam = ReshapeParam;
1211
1474
  exports.VirtualBackgroundOptions = VirtualBackgroundOptions;
1212
1475
  exports.createBeautyEffectEngine = createBeautyEffectEngine;