Choose FrameType
SetImageFrame.type before processImage. There is no extra mode argument.
FrameType.VIDEO (default)
- Camera preview, video calls, live streaming
- Lower latency
FrameType.IMAGE
- Gallery photos, export, capture stills
- Higher quality, more cost per frame
Large stills (preview vs export)
Do not feed full-resolution pixels intoprocessImage on every slider change, and do not throw the original away after scaling.
When the photo opens, keep the full Bitmap and build one preview frame (long edge about 1280–1440). Slider changes call processImage on the preview (FrameType.IMAGE). Export calls processImage on a full-resolution frame with the same setters. Output size matches the input frame — do not upscale the preview. Camera preview stays capture resolution + FrameType.VIDEO.
Parameter ranges
Start low; raise after you confirm face detection and FPS.
Live preview (example):
setBeautySkinOnly(true) when you do not want smoothing on hair / clothes / background.
Preset names: Parameter enums.
Memory
Use directByteBuffers when creating frames from pixel data:
- One engine per process / GL context; do not create per frame
- Interactive stills: scale a copy for preview; keep the original
Bitmapfor export. See Large stills convert()allocates a new frame — release it
OpenGL ES
WhenexternalContext = true:
- Construct the engine on the GL thread with a current context
- Keep input texture,
processImage, and output texture on that same context - Recreate the engine after context loss
- Read the result with
output.getTexture(), not a CPU download, when you stay on GPU
One engine, application context
Hold a singleBeautyEffectEngine. Use getApplicationContext() so the engine outlives an Activity, and still release() when the session ends.
Off the UI thread
RunprocessImage on a camera / GL / dedicated thread. Post results to the main looper only for UI.
ImageFrame across threads without your own lock. The demo camera path processes the latest frame on the render thread.
Filters and stickers from assets
Keep.fbd files in assets/ and pass byte[] (or copy to filesDir and pass a path). Call setFilter / setSticker once when the user picks an effect, not every frame. Adjust mix with setFilterIntensity.
GPU upload happens on the next processImage.
Monitor with getStats
avgProcessTimeMs stays above ~33 ms on a live 30 FPS preview, drop resolution, use FrameType.VIDEO, or reduce simultaneous reshape / makeup / VB.
Persist user sliders
Store intensities yourself (SharedPreferences). Re-apply with setSmoothing, setReshape, setLipstick, … after the engine is created — the SDK does not persist UI state.
Lifecycle
onResume/onPause: start and stop the camera; keep the engine if you will resume soononDestroy/onDetach:engine.release()if this owner created itexternalContext: create / destroy on the GL thread
Tests
licenseToken or reachable /facebetter/v2/auth plus a bound package name).
