Integration
Engine construction throws or never becomes ready
IllegalArgumentException:EngineConfigneeds a non-emptylicenseToken, or bothappIdandappKey- Bind the application package name in the Dashboard to this app
- For online auth, confirm network access to
/facebetter/v2/auth - Listen for
EngineEventCode.LICENSE_VALIDATION_FAILED/INITIALIZATION_FAILED - Call
setLogConfigbeforenew BeautyEffectEngine(...)
Compile: cannot resolve net.pixpark.facebetter
- Maven:
implementation 'net.pixpark:facebetter:2.0.0' - Local AAR:
implementation files('libs/facebetter.aar')and Sync - Clean / Rebuild
UnsatisfiedLinkError
- Device ABI must be
arm64-v8aorarmeabi-v7a - Keep
libfacebetter.soif you shrink/obfuscate; keep Facebetter native methods in ProGuard / R8 - Confirm the AAR / Maven artifact is complete
Effects
Beauty looks weak
- Raise intensities in
[0, 1](setSmoothing,setWhitening, makeup, …) - Reshape uses
[-1, 1]— a value near0is almost off - Confirm
INITIALIZATION_COMPLETEand thatprocessImagereturns a non-null frame - Check landmarks via
onFaceLandmarks(empty list = no face)
Face looks warped
- Lower
setReshapemagnitudes; opposite sign reverses the direction - Avoid stacking many reshape knobs at high absolute values
- Use
FrameType.IMAGEfor still export if liveVIDEOlooks softer, not stronger
Virtual background does nothing
- Call
setVirtualBackgroundBlur(level)withlevel > 0, orsetVirtualBackground(path|bytes) setVirtualBackgroundBlur(0)clears the effect- Image path must be a readable PNG/JPG; empty path returns
ErrorCode.INVALID_ARGUMENT - Green screen:
setChromaKey(ChromaKeyColor.GREEN)plus a fill (blur or image) clearChromaKey()only restores the portrait mask; it does not remove the fill
Filter or sticker does not appear
- Pass a
.fbdpath or bytes tosetFilter/setSticker(no register API) - Upload happens on the next
processImageon the GL thread - With
externalContext = true, that call must run with a current GL context setFilterIntensity(0)makes a LUT invisible
Performance and memory
Preview is slow
input.type = ImageFrame.FrameType.VIDEO- Lower capture resolution
- Fewer simultaneous reshape / makeup / VB effects
processImageoff the main thread (camera or GL thread)- Watch
engine.getStats().avgProcessTimeMs - Large gallery stills: build a smaller preview frame when the photo opens; export the original once. See Best practices
Memory climbs or native crash
release()everyImageFrame, includingconvert()results andprocessImageoutput- Use
ByteBuffer.allocateDirect - One engine instance; call
engine.release()inonDestroy
ANR
- Do not run
processImageon the UI thread for HD video - Do not load large
.fbd/ JPEG files on the main thread
Image and camera
How do I change pixel format?
UseImageFrame.convert(Format) (returns a new frame):
getData(). Planar YUV: getDataY() / getDataU() / getDataV() or getDataUV().
Camera2 preview
ImagefromYUV_420_888ImageFrame.createWithAndroid420(...)rotate/mirrorfor sensor + front camerainput.type = FrameType.VIDEOprocessImage(input)- Convert or
getTexture()for display
Rotation
rotate(ImageFrame.Rotation.ROTATION_90) (0 / 90 / 180 / 270, clockwise) mutates the frame.
Permissions
Online auth:CAMERA (runtime request on API 23+). File logs outside app storage may need storage permissions on older APIs.
Debugging
Enable logs before creating the engine:0 on success. -1 = invalid argument, -2 = not initialized. Full list: Error Handling.
Compatibility
- Android 7.0 (API 24)+
- ABIs:
arm64-v8a,armeabi-v7a - Maven:
net.pixpark:facebetter:2.0.0

