facebetter 1.1.0 → 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.
@@ -53,7 +53,7 @@
53
53
  this.appId = config.appId || null;
54
54
  this.appKey = config.appKey || null;
55
55
  this.licenseJson = config.licenseJson || null;
56
- this.resourcePath = '/facebetter/resource.bundle';
56
+ this.resourcePath = '/resource.fbd';
57
57
  /**
58
58
  * Whether to use an external GL context (native platforms only).
59
59
  * In Web/WASM environments, this field is kept for configuration structure alignment,
@@ -98,7 +98,9 @@
98
98
  Reshape: 1, // Face reshaping (face thinning, big eyes, etc.)
99
99
  Makeup: 2, // Makeup effects (lipstick, blush, etc.)
100
100
  VirtualBackground: 3, // Virtual background (blur, image replacement)
101
- ChromaKey: 4 // Chroma key (green screen removal)
101
+ ChromaKey: 4, // Chroma key (green screen removal)
102
+ Filter: 5, // LUT based filter
103
+ Sticker: 6 // 2D/3D sticker
102
104
  };
103
105
 
104
106
  /**
@@ -165,6 +167,16 @@
165
167
  Video: 1 // Video mode
166
168
  };
167
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
178
+ };
179
+
168
180
  /**
169
181
  * Virtual background options class
170
182
  * Matches the C++/Java/OC API design
@@ -201,6 +213,7 @@
201
213
  ChromaKeyParam: ChromaKeyParam,
202
214
  FrameType: FrameType$1,
203
215
  MakeupParam: MakeupParam$1,
216
+ MirrorMode: MirrorMode$1,
204
217
  ReshapeParam: ReshapeParam$1,
205
218
  VirtualBackgroundOptions: VirtualBackgroundOptions$1
206
219
  });
@@ -256,7 +269,7 @@
256
269
  this.appId = engineConfig.appId;
257
270
  this.appKey = engineConfig.appKey;
258
271
  this.licenseJson = engineConfig.licenseJson;
259
- this.resourcePath = '/facebetter/resource.bundle';
272
+ this.resourcePath = '/resource.fbd';
260
273
  this.enginePtr = null;
261
274
  this.initialized = false;
262
275
  this.srcBufferPtr = null;
@@ -273,7 +286,6 @@
273
286
  this._getWasmModule = platformAPI.getWasmModule;
274
287
  this._getWasmBuffer = platformAPI.getWasmBuffer;
275
288
  this._toImageData = platformAPI.toImageData;
276
- this._verifyAppKeyOnline = platformAPI.verifyAppKeyOnline;
277
289
  this._ensureGPUPixelCanvas = platformAPI.ensureGPUPixelCanvas;
278
290
  this._cleanupGPUPixelCanvas = platformAPI.cleanupGPUPixelCanvas;
279
291
 
@@ -382,7 +394,7 @@
382
394
  if (!Module.onReportUsage) {
383
395
  Module.onReportUsage = async (payloadJson) => {
384
396
  try {
385
- const url = 'https://facebetter.pixpark.net/rest/v1/rpc/report_sdk_usage';
397
+ const url = 'https://facebetter.pixpark.net/facebetter/v1/report';
386
398
  const response = await fetch(url, {
387
399
  method: 'POST',
388
400
  headers: {
@@ -401,7 +413,7 @@
401
413
  if (!Module.onOnlineAuth) {
402
414
  Module.onOnlineAuth = async (payloadJson) => {
403
415
  try {
404
- const url = 'https://facebetter.pixpark.net/rest/v1/rpc/online_auth_v2';
416
+ const url = 'https://facebetter.pixpark.net/facebetter/v1/auth';
405
417
  const response = await fetch(url, {
406
418
  method: 'POST',
407
419
  headers: {
@@ -641,7 +653,231 @@
641
653
  }
642
654
 
643
655
  /**
644
- * Internal method to set beauty parameters
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
645
881
  * @private
646
882
  */
647
883
  _setBeautyParam(functionName, param, value) {
@@ -879,9 +1115,10 @@
879
1115
  * @param {number} width - Image width (required if input is Uint8ClampedArray)
880
1116
  * @param {number} height - Image height (required if input is Uint8ClampedArray)
881
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)
882
1119
  * @returns {ImageData} Processed image data
883
1120
  */
884
- processImage(input, width, height, frameType = FrameType$1.Video) {
1121
+ processImage(input, width, height, frameType = FrameType$1.Video, mirrorMode = MirrorMode$1.None) {
885
1122
  this._ensureInitialized();
886
1123
  const imageData = this._platformAPI.toImageData(input, width, height);
887
1124
  const Module = this._getWasmModule();
@@ -899,7 +1136,7 @@
899
1136
  const result = Module.ccall(
900
1137
  'ProcessImageRGBA',
901
1138
  'number',
902
- ['number', 'number', 'number', 'number', 'number', 'number', 'number'],
1139
+ ['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number'],
903
1140
  [
904
1141
  this.enginePtr,
905
1142
  this.srcBufferPtr,
@@ -907,7 +1144,8 @@
907
1144
  imageData.height,
908
1145
  imageData.width * 4,
909
1146
  this.dstBufferPtr,
910
- frameType
1147
+ frameType,
1148
+ mirrorMode
911
1149
  ]
912
1150
  );
913
1151
 
@@ -939,13 +1177,15 @@
939
1177
  * @param {number} height - Texture height
940
1178
  * @param {number} stride - Row stride (usually width * 4)
941
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)
942
1181
  * @returns {number} Processed texture handle (GL_TEXTURE_2D, uint32)
943
1182
  */
944
1183
  processTexture(textureHandle,
945
1184
  width,
946
1185
  height,
947
1186
  stride,
948
- frameType = FrameType$1.Video) {
1187
+ frameType = FrameType$1.Video,
1188
+ mirrorMode = MirrorMode$1.None) {
949
1189
  this._ensureInitialized();
950
1190
  if (!textureHandle || width <= 0 || height <= 0 || stride <= 0) {
951
1191
  throw new FacebetterError('Invalid textureHandle or dimensions for processTexture');
@@ -957,14 +1197,15 @@
957
1197
  const result = Module.ccall(
958
1198
  'ProcessImageTexture',
959
1199
  'number',
960
- ['number', 'number', 'number', 'number', 'number', 'number'],
1200
+ ['number', 'number', 'number', 'number', 'number', 'number', 'number'],
961
1201
  [
962
1202
  this.enginePtr,
963
1203
  textureHandle,
964
1204
  width,
965
1205
  height,
966
1206
  stride,
967
- frameType
1207
+ frameType,
1208
+ mirrorMode
968
1209
  ]
969
1210
  );
970
1211
 
@@ -1051,15 +1292,6 @@
1051
1292
  return this._offscreenCanvas;
1052
1293
  }
1053
1294
 
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
-
1063
1295
  }
1064
1296
 
1065
1297
  /**
@@ -1318,77 +1550,6 @@
1318
1550
  throw new FacebetterError('Unsupported image source type');
1319
1551
  }
1320
1552
 
1321
- /**
1322
- * Gets User-Agent string for web platform
1323
- * @returns {string} User-Agent string
1324
- */
1325
- function getUserAgentString() {
1326
- return 'FB/1.0 (web; wasm32)';
1327
- }
1328
-
1329
- /**
1330
- * Generates HMAC-SHA256 signature (browser version)
1331
- * @param {string} key - HMAC key (app_key)
1332
- * @param {string} data - Data to sign (timestamp string)
1333
- * @returns {Promise<string>} Promise that resolves with hex-encoded signature
1334
- */
1335
- async function generateHMACSignature(key, data) {
1336
- const encoder = new TextEncoder();
1337
- const keyData = encoder.encode(key);
1338
- const messageData = encoder.encode(data);
1339
-
1340
- const cryptoKey = await crypto.subtle.importKey(
1341
- 'raw',
1342
- keyData,
1343
- { name: 'HMAC', hash: 'SHA-256' },
1344
- false,
1345
- ['sign']
1346
- );
1347
-
1348
- const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
1349
-
1350
- // Convert to hex string
1351
- const hashArray = Array.from(new Uint8Array(signature));
1352
- const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
1353
- return hashHex;
1354
- }
1355
-
1356
- /**
1357
- * Calls online_auth API to verify app_key (browser version)
1358
- * @param {string} appId - Application ID
1359
- * @param {string} appKey - Application key
1360
- * @returns {Promise<Object>} Promise that resolves with response data
1361
- */
1362
- async function verifyAppKeyOnline(appId, appKey) {
1363
- try {
1364
- const timestamp = Math.floor(Date.now() / 1000);
1365
- const timestampStr = timestamp.toString();
1366
- const hmacSignature = await generateHMACSignature(appKey, timestampStr);
1367
-
1368
- const requestBody = {
1369
- p_app_id: appId,
1370
- p_hmac_signature: hmacSignature,
1371
- p_timestamp: timestamp,
1372
- p_user_agent: getUserAgentString()
1373
- };
1374
-
1375
- const response = await fetch('https://facebetter.pixpark.net/rest/v1/rpc/online_auth_v2', {
1376
- method: 'POST',
1377
- headers: {
1378
- 'Content-Type': 'application/json',
1379
- 'User-Agent': getUserAgentString()
1380
- },
1381
- body: JSON.stringify(requestBody)
1382
- });
1383
-
1384
- const responseData = await response.json();
1385
- return responseData;
1386
- } catch (error) {
1387
- console.error('Online auth request failed:', error);
1388
- return null;
1389
- }
1390
- }
1391
-
1392
1553
  /**
1393
1554
  * Browser Entry Point
1394
1555
  * For <script> tag usage (UMD format)
@@ -1425,7 +1586,6 @@
1425
1586
  getWasmModule: getWasmModule,
1426
1587
  getWasmBuffer: getWasmBuffer,
1427
1588
  toImageData: toImageData,
1428
- verifyAppKeyOnline: verifyAppKeyOnline,
1429
1589
  ensureGPUPixelCanvas,
1430
1590
  cleanupGPUPixelCanvas
1431
1591
  };
@@ -1451,6 +1611,7 @@
1451
1611
  const MakeupParam = MakeupParam$1;
1452
1612
  const BackgroundMode = BackgroundMode$1;
1453
1613
  const FrameType = FrameType$1;
1614
+ const MirrorMode = MirrorMode$1;
1454
1615
  const VirtualBackgroundOptions = VirtualBackgroundOptions$1;
1455
1616
 
1456
1617
  // Default export
@@ -1470,6 +1631,7 @@
1470
1631
  exports.FacebetterError = FacebetterError;
1471
1632
  exports.FrameType = FrameType;
1472
1633
  exports.MakeupParam = MakeupParam;
1634
+ exports.MirrorMode = MirrorMode;
1473
1635
  exports.ReshapeParam = ReshapeParam;
1474
1636
  exports.VirtualBackgroundOptions = VirtualBackgroundOptions;
1475
1637
  exports.createBeautyEffectEngine = createBeautyEffectEngine;