Docs / Migrating from FaceUnity
Migrating from FaceUnity
Facevity's kit API follows the call flow of FaceUnity's Android beauty integration, so existing glue code ports almost line by line.
Facevity’s com.knight98.facevity.kit package mirrors the flow of FaceUnity’s Android beauty integration: set up with a licence, load the face processor, attach a beauty object, render each frame. Facevity is an independent implementation; FaceUnity’s public API names appear here only to map one to the other.
Call flow
| Step | FaceUnity | Facevity |
|---|---|---|
| 1. Setup + auth | FURenderManager.registerFURender(context, authpack, callback) |
FVRenderManager.setup(context, licenseToken, callback) or setupWithKey(context, serverUrl, licenseKey, callback) |
| 2. Face model | FUAIController.loadAIProcessor(BUNDLE_AI_FACE, FUAITYPE_FACEPROCESSOR) |
kit.aiKit.loadAIProcessor() (model is inside the AAR); aiKit.setMaxFaces(n) |
| 3. Beauty object | FaceBeauty(FUBundleData(BUNDLE_BEAUTY)), kit.faceBeauty = fb |
FVFaceBeauty(), kit.faceBeauty = fb (no bundle file) |
| 4. Render | kit.renderWithInput(FURenderInputData) → FURenderOutputData |
kit.renderWithInput(FVRenderInputData) → FVRenderOutputData |
| 5. Tracking | FUAIController.isTracking() |
aiKit.isTracking() (number of faces) |
| 6. Reset / release | resetTrackStatus(), kit.release() |
aiKit.resetTrackStatus(), kit.release() (GL thread), kit.releaseAll() |
The callback reports onSuccess(FVCodes.AUTH_SUCCESS, …) or onFail(code, msg). Unlike FaceUnity, a missing or invalid licence does not stop rendering by default: frames get a watermark, or pass through with UnlicensedBehavior.PASSTHROUGH.
Side by side
// FaceUnity // Facevity
FURenderManager.registerFURender(ctx, authpack, cb) FVRenderManager.setup(ctx, token, cb)
kit.FUAIController.loadAIProcessor(AI, FACEPROCESSOR) kit.aiKit.loadAIProcessor()
kit.faceBeauty = FaceBeauty(FUBundleData(BEAUTY)) kit.faceBeauty = FVFaceBeauty()
fb.blurIntensity = smooth * 6.0 fb.smoothIntensity = smooth * 6.0 // 3.0 = natural
fb.colorIntensity = whiten * 2.0 fb.brightenIntensity = whiten * 2.0 // 1.0 = natural
val out = kit.renderWithInput(input) val out = kit.renderWithInput(input)
out.texture?.texId out.texture?.texId
kit.release() kit.release()
Render input and output
| FaceUnity | Facevity |
|---|---|
FURenderInputData(width, height) |
FVRenderInputData(width, height) |
.texture = FUTexture(FU_ADM_FLAG_EXTERNAL_OES_TEXTURE / FU_ADM_FLAG_COMMON_TEXTURE, texId) |
.texture = FVTexture(FVInputTextureType.OES / TEXTURE_2D, texId) |
.imageBuffer = FUImageBuffer(FU_FORMAT_NV21_BUFFER / I420, bytes) |
.imageBuffer = FVImageBuffer(FVBufferFormat.NV21 / NV12 / I420, bytes) |
renderConfig.externalInputType CAMERA / VIDEO / IMAGE |
same |
renderConfig.inputOrientation, deviceOrientation, cameraFacing |
same names (FVCameraFacing.FRONT / BACK) |
inputTextureMatrix / inputBufferMatrix / outputMatrix (CCROT0 …) |
FVTransformMatrix.ROT_0, ROT_90, ROT_180, ROT_270, ROT_0_FLIP_H, ROT_0_FLIP_V, ROT_90_FLIP_H, ROT_90_FLIP_V |
isNeedBufferReturn |
isNeedBufferReturn |
| (none) | textureTransform (the SurfaceTexture 4×4 matrix), timestampNs |
output.texture.texId, output.image.buffer |
output.texture.texId (+ width / height), output.image.buffer |
Verify the output orientation once in your pipeline when you use a transform other than ROT_0.
Beauty properties
Since 0.3.0 every range follows one curve: 0 = off, the middle of the range = natural, the top = strong but still realistic. FaceUnity’s own maxima are similarly strong, so values from a FaceUnity sheet land at a comparable strength.
FaceUnity FaceBeauty |
Range | Facevity FVFaceBeauty |
Range | Natural | Default |
|---|---|---|---|---|---|
blurIntensity |
0 to 6 | smoothIntensity |
0 to 6 | 3.0 | 3.7 |
colorIntensity (whitening) |
0 to 2 | brightenIntensity |
0 to 2 | 1.0 | 0.8 |
redIntensity |
0 to 2 | rosyIntensity |
0 to 2 | 1.0 | 0.83 |
sharpenIntensity |
0 to 1 | sharpenIntensity (eyes, brows, hair) |
0 to 1 | 0.5 | 0.4 |
eyeBrightIntensity |
0 to 1 | eyeBrightIntensity (iris lift, whites cleared) |
0 to 1 | 0.5 | 0 |
toothIntensity |
0 to 1 | teethWhitenIntensity (+ teethBrightIntensity) |
0 to 1 | 0.5 | 0 |
removePouchIntensity |
0 to 1 | darkCircleIntensity |
0 to 1 | 0.5 | 0.43 |
removeLawPatternIntensity |
0 to 1 | foldSoftenIntensity |
0 to 1 | 0.5 | 0 |
cheekThinningIntensity |
0 to 1 | cheekSlimIntensity |
0 to 1 | 0.5 | 0 |
cheekVIntensity / intensityChin |
0 to 1 | jawSlimIntensity |
0 to 1 | 0.5 | 0 |
eyeEnlargingIntensity |
0 to 1 | eyeEnlargeIntensity |
0 to 1 | 0.5 | 0 |
filterName + filterIntensity |
name, 0 to 1 | filterName + filterIntensity |
name, 0 to 1 | 0.5 | 0.54 |
| Makeup lipstick colour + intensity | colour, 0 to 1 | lipstickColor (BeautyColors.LIP_* or RGB) + lipColorIntensity, lipGlossIntensity (0 matte to 1 gloss) |
0 to 1 | none | |
| (none) | backlightIntensity (automatic, acts only on backlit faces) |
0 to 1 | 0.5 | 0.5 | |
blurType |
enum | (one smoothing pipeline) | |||
| (none) | evenToneIntensity, warmthIntensity (-1 to 1) |
linear |
Not available: hair beauty colour, other reshape controls (nose, mouth, forehead, eye spacing), eyeshadow and blush makeup, animated stickers. Facevity’s accessories use their own API: kit.setProp(id), kit.clearProp(), kit.availableProps().
Scale change in 0.3.0
If your app stored levels with Facevity 0.2, convert them once. Each effect has a natural strength mid (reached at 50) and a maximum max (at 100), linear on both halves; 0.2 used internal = level / 100. A 0.2 level old becomes 50 × s / mid when s = old / 100 is at most mid, otherwise 50 + 50 × (s - mid) / (max - mid).
Effect (BeautyParams / kit) |
mid | max | 0.2 level to 0.3 level |
|---|---|---|---|
smooth / smoothIntensity |
0.45 | 1.5 | 35 to 39, 55 to 55, 60 to 57, 100 to 76 |
brightness / brightenIntensity |
0.25 | 1.5 | 10 to 20, 20 to 40 |
rosy / rosyIntensity |
0.12 | 1.0 | 5 to 21, 10 to 42, 14 to 51 |
sharpen |
0.25 | 1.4 | 20 to 40, 30 to 52 |
slimFace / cheekSlimIntensity |
0.35 | 0.95 | 35 to 50 |
jawSlim |
0.35 | 1.0 | 35 to 50 |
bigEyes / eyeEnlargeIntensity |
0.25 | 1.6 | 15 to 30 |
eyeBrighten |
0.2 | 1.3 | 10 to 25, 30 to 55 |
underEye / darkCircleIntensity |
0.35 | 1.25 | 30 to 43, 50 to 58 |
foldSoften |
0.3 | 1.0 | 15 to 25, 40 to 57 |
filterLevel / filterIntensity |
0.5 | 1.8 | 35 to 35, 60 to 54 |
teethWhitening |
0.3 | 1.4 | 15 to 25, 40 to 55 |
lipColor, backlight |
0.5 | 1.0 | unchanged (linear) |
evenTone, skinTone, overall |
unchanged (linear) |
The built-in presets were re-expressed and look the same as in 0.2.
Facevity filter names: origin, natural, warm, cool, fresh, vivid, soft, rose, mono. Common FaceUnity filter names map like this: ziran → natural, zhiganhui → soft, bailiang → fresh, fennen → rose, lengsediao → cool, nuansediao → warm, xiaoqingxin → fresh.
Differences to keep in mind
- Licence is a signed token or
.fvlfile instead of an authpack; it is verified offline and refreshed online. See Licensing. - No bundles to ship: the face model is inside the AAR.
- Output texture is engine-owned and alternates between two textures (valid until the call after next).
- Buffer rendering through the kit needs a current GL context, as with FaceUnity. The simple API’s
processBufferbrings its own GL thread. - Not available: additional reshape controls (nose, mouth, forehead, eye spacing), eyeshadow and blush, animated stickers, body shaping and background replacement.
- Both APIs share one engine, so you can move to the simpler
FacevityAPI later without changing the output.
Need help with an integration? Contact the Facevity team. We answer integration questions during trials.