Skip to main content

Add the SDK

In the project build.gradle / settings.gradle repositories:
Module build.gradle:
Version Catalog (gradle/libs.versions.toml):

Method B: Local AAR

Download the SDK from Download, copy facebetter.aar into libs/, then:

Permissions

AndroidManifest.xml:
Request CAMERA at runtime on API 23+.

Imports

Logging

Logging is off by default. Enable it before new BeautyEffectEngine(...).
Call setLogConfig before constructing the engine, or you will miss initialization logs.

Create the engine

Credentials: Subscription. Auth details: Auth & License. If licenseToken is non-empty, it is used (license token / {token} JSON / offline .lic). Otherwise appId + appKey call /facebetter/v2/auth.
The constructor does not return null; it throws if config is invalid. Watch EngineEventCode.INITIALIZATION_COMPLETE / INITIALIZATION_FAILED on callbacks for async init.

Beauty

Intensity [0.0, 1.0]. 0 disables the effect. Check ErrorCode.SUCCESS (0).
With setBeautySkinOnly(true), smoothing / whitening / sharpening / rosiness apply only on detected skin. Clothing and background stay unchanged.
Styles: Parameter enums.

Reshape

Range [-1.0, 1.0]. 0 is off.
All 26 parameters (FACE_THIN … BROW_THICKNESS) and positive / negative directions: Parameter enums.

Body reshape

Range [0.0, 1.0]. 0 is off. Register resource_body.fbd with addResourcePack first (not in the AAR). See Parameter enums and Optional resource packs.

Makeup

Set intensity, then style and/or color.
Full preset lists: Parameter enums.

Virtual background and chroma key

Blur (0 clears), still image, or chroma-key mask + fill.
clearChromaKey() restores portrait segmentation and does not remove the current blur/image fill.

Filters and stickers

Load a .fbd from a file path or assets. No register step.
3D stickers need the optional resource_3d.fbd pack (not in the AAR). See Optional resource packs. Register it from your app assets, then apply a 3D sticker .fbd:
Filter / sticker changes take effect on the next processImage.

Callbacks and stats

Process frames

Call ImageFrame.release() on every frame you create (and on processImage output). Skipping this leaks native memory.
Set ImageFrame.type to FrameType.IMAGE (still) or FrameType.VIDEO (camera / live). processImage takes only the frame — no extra mode argument.
From a file or Bitmap:
Rotate / mirror before processing if the camera sensor is rotated:
The engine keeps input and output pixel formats aligned (NV21 in → NV21 out, RGBA in → RGBA out).
Read pixels with getData() / planar accessors, or convert:

Camera pipeline

Typical Camera2 YUV_420_888 → engine → display:

External texture (OpenGL ES)

Create the engine on the GL thread with externalContext = true. Input and output textures must share that context.
Use this when you already render with OpenGL ES and want to avoid CPU round-trips.
Recommended sampler state for input GL_TEXTURE_2D:
Notes:
  • Input texture: GL_TEXTURE_2D, typically RGBA; stride is usually width * 4
  • Lazy-create the engine in the first GL callback so the context is current
  • Output texture is owned by the SDK; do not glDeleteTextures it. Release the ImageFrame
  • If the GL context is lost, release() the engine and create it again on the new context
  • Use FrameType.VIDEO for live GL pipelines
  • For TRTC / Agora / LiveKit and similar SDKs: Third-party Integration

Lifecycle

Call engine.release() in onDestroy / onDetach. Unreleased engines leak GPU and native memory.