Overview
Nosmai provides built-in beauty controls that can be adjusted while the camera preview is running. These controls are separate from downloadable .nosmai packages and are intended for interactive controls such as sliders, color selectors, and style lists.
The built-in beauty features are divided into four groups:
| Group | Features |
|---|---|
| Skin and detail | Skin smoothing, skin whitening, sharpening, and teeth whitening |
| Makeup | Lipstick, eyeshadow, blusher, eyelashes, and eyebrows |
| Face shaping | Face slim, eye size, nose slim, and other supported shape controls |
| Eye color | Iris color and color intensity |
Built-in beauty can be combined with a regular filter package. A packaged beauty_effect is different: it is a complete authored beauty look stored in a .nosmai file. See Filters and effects for the package types and replacement rules.
Before applying beauty
Complete these steps first:
- Initialize the SDK with a valid license key.
- Show the Nosmai camera preview.
- Wait until the preview is ready.
- Apply the required beauty values.
Do not apply a saved beauty preset before initialization has completed. The native SDK can queue some operations, but waiting for a ready preview gives the application predictable state and clearer error handling.
Beauty effects that follow facial regions become visible when a face is detected. If the face leaves the camera view, the SDK hides those visual layers. The selected settings remain available and become visible again after the face is detected.
Strength values
Most beauty and makeup controls use a value from 0.0 to 1.0:
0.0means disabled or invisible.0.5means medium strength.1.0means maximum strength.
Start with low values. Maximum strength is useful for testing, but it often looks artificial in a production camera.
Suggested starting values:
| Control | Suggested starting value |
|---|---|
| Skin smoothing | 0.25 to 0.40 |
| Skin whitening | 0.05 to 0.15 |
| Sharpening | 0.10 to 0.20 |
| Teeth whitening | 0.15 to 0.30 |
| Lipstick | 0.45 to 0.70 |
| Eyeshadow | 0.20 to 0.40 |
| Blusher | 0.15 to 0.35 |
| Eyelashes | 0.30 to 0.55 |
| Eyebrows | 0.20 to 0.40 |
| Face slim | 0.10 to 0.25 |
| Eye size | 0.05 to 0.15 |
| Nose slim | 0.05 to 0.15 |
These are starting points, not required values. Test the final preset on different face shapes, skin tones, lighting conditions, camera distances, and device classes.
Skin and detail controls
Flutter
Apply the controls after NosmaiCameraPreview reports that it is ready:
final nosmai = NosmaiFlutter.instance; await nosmai.applySkinSmoothing(0.35); await nosmai.applySkinWhitening(0.10); await nosmai.applySharpening(0.15); await nosmai.applyTeethWhitening(0.20);
Remove the built-in skin and color controls:
await nosmai.removeBuiltInFilters();
Android
Use NosmaiBeauty:
import com.nosmai.effect.api.NosmaiBeauty; NosmaiBeauty.applySkinSmoothing(0.35f); NosmaiBeauty.applySkinWhitening(0.10f); NosmaiBeauty.applySharpen(0.15f); NosmaiBeauty.applyTeethWhitening(0.20f);
Remove the slider-based beauty controls:
NosmaiBeauty.removeAllBeautyFilters();
To clear both slider-based beauty and built-in makeup, use:
NosmaiBeauty.clearAllBeautyFilters();
iOS
Use the effects engine owned by NosmaiCore:
NosmaiEffectsEngine *effects = [NosmaiCore shared].effects; [effects applySkinSmoothing:0.35f]; [effects applySkinWhitening:0.10f]; [effects applySharpening:0.15f]; [effects applyTeethWhitening:0.20f];
Remove the built-in skin and color controls:
[[NosmaiCore shared].effects removeBuiltInFilters];
Makeup styles
Nosmai provides three styles for each makeup feature.
| Feature | Style 0 | Style 1 | Style 2 |
|---|---|---|---|
| Lipstick | Classic | Matte | Natural |
| Eyeshadow | Smokey | Shimmer | Natural |
| Blusher | Round | Contour | Natural |
| Eyelashes | Natural | Dramatic | Wispy |
| Eyebrows | Natural | Bold | Arched |
Applying one makeup feature does not remove the others. Lipstick, eyeshadow, blusher, eyelashes, and eyebrows can remain active together.
Flutter makeup
Flutter exposes named style enums and an intensity value:
final nosmai = NosmaiFlutter.instance; await nosmai.applyLipstick( style: NosmaiLipstickStyle.matte, intensity: 0.60, ); await nosmai.applyEyeshadow( style: NosmaiEyeshadowStyle.natural, intensity: 0.30, ); await nosmai.applyBlusher( style: NosmaiBlusherStyle.natural, intensity: 0.25, ); await nosmai.applyEyelash( style: NosmaiEyelashStyle.natural, intensity: 0.40, ); await nosmai.applyEyebrow( style: NosmaiEyebrowStyle.natural, intensity: 0.30, );
Available Flutter style values:
NosmaiLipstickStyle.classic NosmaiLipstickStyle.matte NosmaiLipstickStyle.natural NosmaiEyeshadowStyle.smokey NosmaiEyeshadowStyle.shimmer NosmaiEyeshadowStyle.natural NosmaiBlusherStyle.round NosmaiBlusherStyle.contour NosmaiBlusherStyle.natural NosmaiEyelashStyle.natural NosmaiEyelashStyle.dramatic NosmaiEyelashStyle.wispy NosmaiEyebrowStyle.natural NosmaiEyebrowStyle.bold NosmaiEyebrowStyle.arched
Change an active layer without loading a new style:
await nosmai.setLipstickIntensity(0.45); await nosmai.setEyeshadowIntensity(0.25); await nosmai.setBlusherIntensity(0.20); await nosmai.setEyelashIntensity(0.35); await nosmai.setEyebrowIntensity(0.25);
Check whether a layer is active:
final lipstickActive = await nosmai.hasLipstick(); final eyeshadowActive = await nosmai.hasEyeshadow(); final blusherActive = await nosmai.hasBlusher(); final eyelashActive = await nosmai.hasEyelash(); final eyebrowActive = await nosmai.hasEyebrow();
Remove one layer or all makeup:
await nosmai.removeLipstick(); await nosmai.removeEyeshadow(); await nosmai.removeBlusher(); await nosmai.removeEyelash(); await nosmai.removeEyebrow(); await nosmai.removeAllMakeup();
Android makeup
Android accepts a style constant and RGB components from 0.0 to 1.0.
NosmaiBeauty.applyLipstickStyle(
NosmaiBeauty.LIPSTICK_MATTE,
0.62f,
0.12f,
0.18f
);
NosmaiBeauty.applyEyeshadowStyle(
NosmaiBeauty.EYESHADOW_NATURAL,
0.42f,
0.30f,
0.48f
);
NosmaiBeauty.applyBlusherStyle(
NosmaiBeauty.BLUSHER_NATURAL,
0.95f,
0.38f,
0.42f
);
NosmaiBeauty.applyEyelashStyle(
NosmaiBeauty.EYELASH_NATURAL
);
The Android eyebrow method uses style values 0, 1, and 2 for Natural, Bold, and Arched:
int naturalEyebrowStyle = 0;
NosmaiBeauty.applyEyebrowStyle(
naturalEyebrowStyle,
0.16f,
0.11f,
0.08f
);
Set the intensity of an active layer:
NosmaiBeauty.setMakeupIntensity(
NosmaiBeauty.MAKEUP_LIPSTICK,
0.60f
);
NosmaiBeauty.setMakeupIntensity(
NosmaiBeauty.MAKEUP_EYESHADOW,
0.30f
);
Check or remove one layer:
boolean active = NosmaiBeauty.isMakeupActive(
NosmaiBeauty.MAKEUP_LIPSTICK
);
NosmaiBeauty.removeMakeup(
NosmaiBeauty.MAKEUP_LIPSTICK
);
Remove all built-in makeup:
NosmaiBeauty.removeMakeup(NosmaiBeauty.MAKEUP_ALL);
Use clearBuiltInMakeup() when the screen is being reset and the complete built-in makeup manager should be released:
NosmaiBeauty.clearBuiltInMakeup();
iOS makeup
iOS provides style enums and color indexes:
NosmaiEffectsEngine *effects = [NosmaiCore shared].effects;
[effects applyLipstickWithStyle:NosmaiLipstickStyleMatte
colorIndex:0];
[effects applyEyeshadowWithStyle:NosmaiEyeshadowStyleNatural
colorIndex:0];
[effects applyBlusherWithStyle:NosmaiBlusherStyleNatural
colorIndex:0];
[effects applyEyelashWithStyle:NosmaiEyelashStyleNatural];
[effects applyEyebrowWithStyle:NosmaiEyebrowStyleNatural
colorIndex:0];
Read the available colors before presenting a color list:
NSArray<NosmaiMakeupColor *> *colors =
[NosmaiCore shared].effects.lipstickColors;
for (NosmaiMakeupColor *color in colors) {
NSLog(@"%@, %.2f, %.2f, %.2f",
color.name,
color.r,
color.g,
color.b);
}
Change active intensities:
[effects setLipstickIntensity:0.60f]; [effects setEyeshadowIntensity:0.30f]; [effects setBlusherIntensity:0.25f]; [effects setEyelashIntensity:0.40f]; [effects setEyebrowIntensity:0.30f];
Check and remove individual layers:
if (effects.hasLipstick) {
[effects removeLipstick];
}
[effects removeEyeshadow];
[effects removeBlusher];
[effects removeEyelash];
[effects removeEyebrow];
Remove all makeup:
[effects removeAllMakeup];
The NosmaiSDKBeauty.h category also provides custom RGB overloads for native iOS applications that need an exact makeup color.
Face shaping
Face shaping changes facial geometry instead of adding color. Keep the default values low and let the user adjust each control separately.
Flutter
final nosmai = NosmaiFlutter.instance; await nosmai.setFaceSlimLevel(0.20); await nosmai.setEyeSizeLevel(0.10); await nosmai.setNoseSlimLevel(0.10);
Reset all face shaping:
await nosmai.removeAllMorphing();
Android
NosmaiBeauty.applyMorphFaceSlim(0.20f); NosmaiBeauty.applyMorphEyeSize(0.10f); NosmaiBeauty.applyMorphNoseSlim(0.10f);
Reset these controls:
NosmaiBeauty.applyMorphFaceSlim(0.0f); NosmaiBeauty.applyMorphEyeSize(0.0f); NosmaiBeauty.applyMorphNoseSlim(0.0f);
Android also exposes chin, lip size, and jawline controls:
NosmaiBeauty.applyMorphChinSize(0.0f); NosmaiBeauty.applyMorphLipSize(0.10f); NosmaiBeauty.applyMorphJawline(0.10f);
applyMorphChinSize accepts values from -1.0 to 1.0. The other controls in this example use 0.0 to 1.0.
iOS
NosmaiEffectsEngine *effects = [NosmaiCore shared].effects; [effects setFaceSlimLevel:0.20f]; [effects setEyeSizeLevel:0.10f]; [effects setNoseSlimLevel:0.10f];
iOS also provides eyebrow position, chin size, lip size, and jawline controls:
[effects setEyebrowPositionLevel:0.0f]; [effects setChinSizeLevel:0.0f]; [effects setLipSizeLevel:0.10f]; [effects setJawlineLevel:0.10f];
Reset all face shaping:
[effects removeAllMorphing];
Eye color
Eye color changes the visible iris color. Use a moderate intensity so natural iris detail remains visible.
Flutter
import 'package:flutter/material.dart'; final nosmai = NosmaiFlutter.instance; await nosmai.setEyeColor( const Color(0xFF4F7A56), intensity: 0.45, );
Update or remove it:
await nosmai.setEyeColorIntensity(0.30); await nosmai.removeEyeColoring();
Android
Android calls this feature an eye lens:
NosmaiBeauty.applyEyeLens(
0.31f,
0.48f,
0.34f,
0.45f
);
Update, inspect, or remove it:
NosmaiBeauty.setEyeLensIntensity(0.30f); boolean active = NosmaiBeauty.isEyeLensActive(); NosmaiBeauty.removeEyeLens();
iOS
NosmaiEffectsEngine *effects = [NosmaiCore shared].effects; [effects setEyeColorR:0.31f g:0.48f b:0.34f]; [effects setEyeColorIntensity:0.45f];
Update, inspect, or remove it:
[effects setEyeColorIntensity:0.30f]; BOOL active = effects.hasEyeColoring; [effects removeEyeColoring];
Build a complete beauty preset
A preset should store style choices and numeric values in application state. Apply it only after the preview is ready.
Flutter example:
Future<void> applyNaturalPreset() async {
final nosmai = NosmaiFlutter.instance;
await nosmai.applySkinSmoothing(0.30);
await nosmai.applySkinWhitening(0.08);
await nosmai.applySharpening(0.12);
await nosmai.applyTeethWhitening(0.18);
await nosmai.applyLipstick(
style: NosmaiLipstickStyle.natural,
intensity: 0.50,
);
await nosmai.applyEyeshadow(
style: NosmaiEyeshadowStyle.natural,
intensity: 0.22,
);
await nosmai.applyBlusher(
style: NosmaiBlusherStyle.natural,
intensity: 0.20,
);
await nosmai.applyEyelash(
style: NosmaiEyelashStyle.natural,
intensity: 0.32,
);
await nosmai.setFaceSlimLevel(0.12);
await nosmai.setEyeSizeLevel(0.06);
await nosmai.setNoseSlimLevel(0.05);
}
Keep the selected values in your application rather than reading them from the camera preview. This makes it easier to restore the same look after changing screens, switching cameras, or recreating the preview.
Reset behavior
Choose the narrowest reset method for the user action.
| User action | Flutter | Android | iOS |
|---|---|---|---|
| Remove one makeup layer | removeLipstick() or the matching method | removeMakeup(category) | removeLipstick or the matching method |
| Remove all makeup | removeAllMakeup() | removeMakeup(MAKEUP_ALL) | removeAllMakeup |
| Remove face shaping | removeAllMorphing() | Set active morph values to 0.0 | removeAllMorphing |
| Remove eye color | removeEyeColoring() | removeEyeLens() | removeEyeColoring |
| Remove skin and color controls | removeBuiltInFilters() | removeAllBeautyFilters() | removeBuiltInFilters |
| Remove all beauty groups | removeAllBeautyEffects() | clearAllBeautyFilters() and removeEyeLens() | removeAllBeautyEffects |
Do not use a full SDK reset when the user only turns off lipstick. A narrow reset keeps unrelated filters and camera state unchanged.
Built-in beauty and beauty_effect
Built-in beauty is best when the application needs:
- live sliders
- separate makeup controls
- runtime color choices
- user-created presets
- individual remove buttons
A packaged beauty_effect is best when the application needs:
- a complete authored look
- one preview image and one selection item
- assets and settings delivered as one
.nosmaipackage - cloud distribution and versioning
Apply a packaged look with the same applyEffect(path) method used for other .nosmai packages. Do not call the built-in makeup methods merely to apply a packaged beauty_effect.
Built-in beauty, makeup, reshape, color, and hair controls do not coexist with an external effect or beauty_effect. Applying the package clears those built-in controls. Applying a built-in control later clears the active AR package. Regular external filter packages and manual backgrounds can remain active with built-in beauty.
Always rebuild the selected UI from the apply result and active-state listener after switching modes. Do not leave a built-in slider or AR item selected after the SDK reports that it was cleared.
User interface guidance
Use controls that match the setting:
- Use a slider for strength.
- Use swatches for colors.
- Use a horizontal style list for Classic, Matte, and Natural choices.
- Use a visible Off choice for every feature.
- Update the selected state only after an asynchronous call succeeds.
- Keep the last selected value when the user changes only the style.
- Debounce very frequent slider changes if the application sends more updates than the display can present.
For a natural default look, avoid enabling every feature at medium or maximum strength. A small number of subtle controls usually looks better.
Performance guidance
Beauty rendering is designed for live use, but the final workload depends on the number of active features, camera resolution, recording, streaming, and the device GPU.
Follow these rules:
- Keep the camera at 30 FPS unless the target devices have been tested at a higher rate.
- Do not repeatedly reapply the same makeup style for every camera frame.
- Apply the style once, then use its intensity method for slider updates.
- Avoid rebuilding the camera preview while changing beauty settings.
- Keep image assets at the resolution required by the effect.
- Test beauty while recording and live streaming, not only in preview.
- Test rapid style changes and clear actions.
- Release the camera when its screen closes.
Test cases
Test every production preset with:
- one face centered
- the face near each screen edge
- fast head movement
- head rotation to the left and right
- mouth open and closed
- eyes open, blinking, and partly closed
- glasses and facial hair
- bright, dim, and mixed lighting
- front and back camera where supported
- camera switching
- leaving and reopening the camera screen
- recording
- live streaming
- repeated apply and remove actions
Watch for color outside the intended facial region, delayed attachment, sharp edges, visible movement, stale effects after the face disappears, and a drop in preview frame rate.
Troubleshooting
The feature is selected but not visible
Confirm that:
- the preview is ready
- a face is visible
- the intensity is greater than
0.0 - the selected style is supported
- the feature was not removed by a later clear action
Makeup looks too strong
Reduce the layer intensity before changing the style. Also reduce skin whitening and sharpening because strong global controls can make makeup edges more noticeable.
Makeup follows the face with visible delay
Test without recording or streaming, verify the camera remains near the target frame rate, and reduce unnecessary repeated UI updates. If the delay appears only on particular devices, collect the device model, OS version, active features, camera resolution, and frame-rate logs.
An effect remains after pressing Clear
Use the reset method for the correct group. Skin controls, makeup, face shaping, and eye color have separate remove methods. Use the combined beauty reset only when the user intends to remove all four groups.
Production checklist
Before release:
- initialize Nosmai before applying a preset
- wait for preview readiness
- keep all normal strength values within
0.0to1.0 - provide an Off choice for each feature
- use individual intensity methods for slider updates
- preserve selected settings in application state
- handle camera switching and screen reopening
- verify each remove action
- test no-face behavior
- test multiple skin tones and face shapes
- test low and high lighting
- test recording and live streaming
- test supported low-end and high-end devices
- disable debug logging in production
Next steps
- Read Filters and effects to understand packaged
beauty_effectfiles. - Read Errors and troubleshooting for initialization, camera, filter, and performance failures.
- Read Flutter live streaming with Agora before publishing the processed camera preview.