Nosmai / docs
Nosmai Effects Nosmai Moderation Nosmai Try-ons coming soon
Docs menu Custom stickers and overlays
docs / nosmai effects / custom / custom stickers and overlays

Custom stickers and overlays

Place your own images on the camera in real time: PNG and animated stickers, fixed screen positions, and face-attached overlays on the nose, lips, eyes, or head, all included in preview, photo, recording, and live streaming.

Overview

Custom overlays let an application draw its own images on top of the live camera. Unlike a packaged .nosmai effect, a custom overlay uses an image that the application already has, such as a bundled asset, a downloaded file, a picture selected from the gallery, or an image at a network URL.

A custom overlay can be:

  • a still PNG image
  • an animated image played from a frame sequence or a GIF
  • placed at a fixed screen position that the user can move, scale, and rotate
  • attached to a face point such as the nose, lips, eyes, or head so it follows the face

Because a custom overlay is composited inside the Nosmai pipeline, it appears everywhere the processed frame is used:

  • the live preview
  • captured photos
  • recorded video
  • live streaming output

[!NOTE] Drawing an image in the application's own view layer only shows it on screen. A custom overlay is part of the processed frame, so it is also present in photos, recordings, and streams.

Custom overlays or a .nosmai effect

Custom overlays and packaged .nosmai effects solve different problems. Use the one that matches the content.

RequirementRecommended choice
The user places their own PNG, drawing, or gallery imageCustom overlay
A logo, badge, or branded watermark on the outputCustom overlay
An image chosen or moved at runtimeCustom overlay
Several movable stickers at onceCustom overlay
A downloadable, protected, or monetized effect.nosmai effect
An authored face mask, 3D model, or particle experience.nosmai effect
A coordinated makeup or beauty lookBuilt-in beauty or beauty_effect

Custom overlays are an independent layer. They remain visible together with color filters, built-in beauty, backgrounds, and .nosmai effects. See Filters and effects for package slots and Beauty and makeup for built-in beauty.

Where you can use custom overlays

Custom overlays work in any camera experience built on Nosmai, because they are part of the processed frame. The same overlay reaches the preview, captured photos, recorded video, and live streams.

Common use cases include:

Use caseWhat a custom overlay adds
Live streamingA streamer badge, event banner, donation sticker, or brand watermark visible to every viewer
Video calls and conferencingA name tag, team logo, or event label on the sent video
Short-video and social appsMovable stickers the user places, scales, and rotates on a clip
Selfie and photo-booth appsFun face stickers on the nose, lips, eyes, or head
Branding and watermarksA logo or campaign mark included in recorded and streamed output
Events and weddingsA custom frame, hashtag, or date overlay for shared media
Marketing and seasonal campaignsA network-loaded promo sticker that can change without an app release
Live shopping and creatorsA price tag, offer badge, or handle shown during a stream

Live streaming

Because a custom overlay is composited before the frame leaves the SDK, it is included in the live-stream output, not only the local preview. A streamer badge, sponsor logo, or event banner is visible to every viewer through the same processed frame that carries filters, beauty, and effects.

This works with both native and Flutter streaming. Add the overlay after the preview is ready and keep it active for the whole session. See Native live streaming and Flutter live streaming with Agora.

Photo capture and recording

The same overlay is present in a captured photo and in recorded video, so a sticker, frame, or watermark carries into saved and shared media without a separate compositing step. Add the overlay before capture or before recording starts.

Before you start

Complete these steps first:

  1. Initialize the SDK with a valid license key.
  2. Show the Nosmai camera preview.
  3. Wait until the preview is ready.
  4. Add the overlay.

Face-attached overlays become visible when a face is detected. If the face leaves the camera view, the SDK hides the attached overlay and restores it when the face returns. A screen-anchored overlay does not require a face.

Image sources

An overlay image can come from several sources.

SourceUse it for
Bundled assetAn image shipped inside the application
Local fileA downloaded or user-saved file on the device
Image bytesAn image the application already holds in memory
Network URLAn image hosted on a server
Frame sequence or GIFAn animated overlay

Keep overlay images at a reasonable resolution. A very large image uses more memory and can lower the preview frame rate without improving the visible result.

Placement and anchors

An overlay is positioned with an anchor and a transform.

Anchor

The anchor decides where the overlay is placed.

AnchorPlacement
screenA fixed position on the screen
headThe top of the head
noseThe nose
lipsThe lips
eyesBetween the eyes
leftEyeThe left eye
rightEyeThe right eye

Use screen for a movable sticker or a watermark. Use a face anchor for an overlay that should follow the face, such as glasses on the eyes or a shape on the nose.

Transform

Every overlay accepts the same transform values.

ValueMeaning
x, yPosition
zDepth and draw order
scaleSize multiplier
rotationRotation in degrees
opacityTransparency from 0.0 to 1.0

The transform is interpreted relative to the anchor:

  • For the screen anchor, x and y are normalized screen coordinates from 0.0 to 1.0 with the origin at the top-left, and z sets the draw order of overlapping overlays.
  • For a face anchor, x, y, and z are offsets from the anchor point. The overlay is automatically scaled to the size of the detected face, and scale multiplies that automatic size.

This means an application can select a face point and still fine-tune the exact placement:

finalPosition = anchorPoint + (x, y, z)
finalSize     = autoFaceSize × scale
finalRotation = rotation

Add an overlay

Give each overlay a unique identifier so it can be updated or removed later.

Flutter

Add a screen-anchored sticker:

final nosmai = NosmaiFlutter.instance;

await nosmai.addOverlay(
  id: 'heart',
  source: NosmaiOverlaySource.asset('assets/stickers/heart.png'),
  anchor: NosmaiOverlayAnchor.screen,
  x: 0.5,
  y: 0.5,
  scale: 1.0,
  rotation: 0.0,
  opacity: 1.0,
);

Attach an overlay to a face point:

await nosmai.addOverlay(
  id: 'glasses',
  source: NosmaiOverlaySource.asset('assets/stickers/glasses.png'),
  anchor: NosmaiOverlayAnchor.eyes,
  x: 0.0,
  y: -0.02,
  z: 0.0,
  scale: 1.0,
);

Available Flutter anchors:

NosmaiOverlayAnchor.screen
NosmaiOverlayAnchor.head
NosmaiOverlayAnchor.nose
NosmaiOverlayAnchor.lips
NosmaiOverlayAnchor.eyes
NosmaiOverlayAnchor.leftEye
NosmaiOverlayAnchor.rightEye

Available Flutter image sources:

NosmaiOverlaySource.asset('assets/stickers/star.png');
NosmaiOverlaySource.file('/path/to/sticker.png');
NosmaiOverlaySource.bytes(imageBytes);
NosmaiOverlaySource.network('https://cdn.example.com/star.png');
NosmaiOverlaySource.sequence(framePaths); // animated frames

iOS

NosmaiEffectsEngine *effects = [NosmaiCore shared].effects;

NosmaiOverlayConfig *config = [[NosmaiOverlayConfig alloc] init];
config.identifier = @"heart";
config.anchor = NosmaiOverlayAnchorScreen;
config.x = 0.5f;
config.y = 0.5f;
config.scale = 1.0f;
config.rotation = 0.0f;
config.opacity = 1.0f;

UIImage *image = [UIImage imageNamed:@"heart"];
[effects addOverlay:config image:image];

Attach an overlay to a face point:

NosmaiOverlayConfig *config = [[NosmaiOverlayConfig alloc] init];
config.identifier = @"glasses";
config.anchor = NosmaiOverlayAnchorEyes;
config.x = 0.0f;
config.y = -0.02f;
config.z = 0.0f;
config.scale = 1.0f;

[effects addOverlay:config image:[UIImage imageNamed:@"glasses"]];

Add from a file path or a network URL:

[effects addOverlayFromPath:localPath config:config];
[effects addOverlayFromURL:remoteURL config:config];

Available iOS anchors:

NosmaiOverlayAnchorScreen
NosmaiOverlayAnchorHead
NosmaiOverlayAnchorNose
NosmaiOverlayAnchorLips
NosmaiOverlayAnchorEyes
NosmaiOverlayAnchorLeftEye
NosmaiOverlayAnchorRightEye

Android

import com.nosmai.effect.api.NosmaiOverlay;

NosmaiOverlay.Config config = new NosmaiOverlay.Config();
config.id = "heart";
config.anchor = NosmaiOverlay.Anchor.SCREEN;
config.x = 0.5f;
config.y = 0.5f;
config.scale = 1.0f;
config.rotation = 0.0f;
config.opacity = 1.0f;

NosmaiOverlay.add(bitmap, config);

Attach an overlay to a face point:

NosmaiOverlay.Config config = new NosmaiOverlay.Config();
config.id = "glasses";
config.anchor = NosmaiOverlay.Anchor.EYES;
config.x = 0.0f;
config.y = -0.02f;
config.z = 0.0f;
config.scale = 1.0f;

NosmaiOverlay.add(bitmap, config);

Add from a bundled asset, a file, or a network URL:

NosmaiOverlay.addFromAsset("stickers/heart.png", config);
NosmaiOverlay.addFromFile(localPath, config);
NosmaiOverlay.addFromUrl("https://cdn.example.com/star.png", config);

Available Android anchors:

NosmaiOverlay.Anchor.SCREEN
NosmaiOverlay.Anchor.HEAD
NosmaiOverlay.Anchor.NOSE
NosmaiOverlay.Anchor.LIPS
NosmaiOverlay.Anchor.EYES
NosmaiOverlay.Anchor.LEFT_EYE
NosmaiOverlay.Anchor.RIGHT_EYE

Move, scale, and rotate an overlay

Update an existing overlay by its identifier. This is how a draggable, pinch-to-zoom sticker is implemented.

Flutter

await NosmaiFlutter.instance.updateOverlay(
  id: 'heart',
  x: 0.4,
  y: 0.6,
  scale: 1.3,
  rotation: 15.0,
);

iOS

NosmaiOverlayConfig *update = [[NosmaiOverlayConfig alloc] init];
update.identifier = @"heart";
update.x = 0.4f;
update.y = 0.6f;
update.scale = 1.3f;
update.rotation = 15.0f;

[[NosmaiCore shared].effects updateOverlay:update];

Android

NosmaiOverlay.update("heart", 0.4f, 0.6f, 1.3f, 15.0f);

Update only the transform. The image is not reloaded, so continuous gesture updates stay smooth.

Animated overlays

An animated overlay plays a loop of frames. Provide a frame sequence or a GIF.

Flutter

await NosmaiFlutter.instance.addOverlay(
  id: 'confetti',
  source: NosmaiOverlaySource.sequence(confettiFramePaths),
  anchor: NosmaiOverlayAnchor.screen,
  x: 0.5,
  y: 0.3,
);

A single animated file is also accepted:

await NosmaiFlutter.instance.addOverlay(
  id: 'confetti',
  source: NosmaiOverlaySource.asset('assets/stickers/confetti.gif'),
  anchor: NosmaiOverlayAnchor.screen,
  x: 0.5,
  y: 0.3,
);

iOS

NosmaiOverlayConfig *config = [[NosmaiOverlayConfig alloc] init];
config.identifier = @"confetti";
config.anchor = NosmaiOverlayAnchorScreen;
config.x = 0.5f;
config.y = 0.3f;

[[NosmaiCore shared].effects addOverlayFromPath:confettiPath config:config];

Android

NosmaiOverlay.Config config = new NosmaiOverlay.Config();
config.id = "confetti";
config.anchor = NosmaiOverlay.Anchor.SCREEN;
config.x = 0.5f;
config.y = 0.3f;

NosmaiOverlay.addFromAsset("stickers/confetti.gif", config);

Keep animated frames compact. A long high-resolution animation uses more memory than a short optimized loop.

Network images

An overlay image can be loaded from a network URL. The image is fetched, cached, and then composited like any other overlay.

await NosmaiFlutter.instance.addOverlay(
  id: 'promo',
  source: NosmaiOverlaySource.network('https://cdn.example.com/promo.png'),
  anchor: NosmaiOverlayAnchor.screen,
  x: 0.5,
  y: 0.9,
);

Recommended behavior:

  • Show a placeholder or loading state until the overlay is added.
  • Reuse a downloaded image for repeated use instead of fetching it again.
  • Handle a failed download and offer a retry.
  • Prefer a local file or bundled asset when the same image is used often.

A network image needs a connection the first time it is fetched. Applying an already cached overlay image does not require a new download.

Remove overlays

Remove one overlay by identifier, or clear every overlay.

Flutter

await NosmaiFlutter.instance.removeOverlay('heart');
await NosmaiFlutter.instance.clearOverlays();

iOS

[[NosmaiCore shared].effects removeOverlayWithIdentifier:@"heart"];
[[NosmaiCore shared].effects clearOverlays];

Android

NosmaiOverlay.remove("heart");
NosmaiOverlay.clear();

Removing an overlay clears only that overlay. Color filters, built-in beauty, backgrounds, and .nosmai effects stay active.

How custom overlays combine with other features

Custom overlays are an independent layer, so they coexist with the other Nosmai features.

Active togetherResult
Custom overlay and a color filterBoth visible
Custom overlay and built-in beauty or makeupBoth visible
Custom overlay and a backgroundBoth visible
Custom overlay and a .nosmai effect or beauty_effectBoth visible
Two custom overlaysBoth visible, ordered by z

Custom overlays are drawn above the processed content. This keeps a sticker, badge, or watermark on top of filters and effects.

Output: photo, recording, and streaming

Custom overlays are part of the processed frame, so they are automatically included in:

  • captured photos
  • recorded video
  • live-stream output

No extra step is required to add an overlay to captured or streamed media. Before capturing, wait for the preview to be ready and for the overlay to be added.

Performance guidance

For a smooth camera:

  1. Keep overlay images at the resolution the design needs.
  2. Reuse a downloaded or decoded image instead of loading it again for each use.
  3. Update the transform for gestures instead of removing and adding the overlay.
  4. Limit the number of simultaneous animated overlays.
  5. Keep animated loops short and optimized.
  6. Test overlays while recording and live streaming, not only in preview.
  7. Test face-attached overlays with fast head movement.

A screen-anchored still overlay is the lightest option. Animated and face-attached overlays do more work per frame.

User interface guidance

For a movable sticker experience:

  • Use a drag gesture to update x and y.
  • Use a pinch gesture to update scale.
  • Use a rotation gesture to update rotation.
  • Give each sticker a unique identifier when it is added.
  • Bring the selected sticker to the front by increasing its z.
  • Provide a delete action that calls remove for that identifier.
  • Debounce very frequent gesture updates if the application sends more updates than the display can present.

Test cases

Test overlays with:

  • one screen sticker moved, scaled, and rotated
  • several stickers at once
  • a face-attached overlay on the nose, lips, eyes, and head
  • the face near each screen edge
  • fast head movement and head rotation
  • the face leaving and returning to the view
  • an animated overlay during a long session
  • a network overlay with a slow connection and a failed download
  • front and back camera where supported
  • camera switching
  • photo capture with overlays present
  • recording with overlays present
  • live streaming with overlays present
  • repeated add and remove actions

Watch for a sticker drifting away from a face point, a delay when the face moves, incorrect mirroring on the front camera, and a drop in preview frame rate.

Troubleshooting

The overlay does not appear

Confirm that:

  1. the preview is ready
  2. the image source is valid
  3. the opacity is greater than 0.0
  4. a screen overlay is inside the visible 0.0 to 1.0 range
  5. a face overlay has a detected face in view

A face overlay is not attached to the face

Confirm that:

  1. the anchor is a face anchor, not screen
  2. a face is visible and reasonably lit
  3. the offset values are small relative to the face

The overlay is mirrored on the front camera

Front-camera preview is often mirrored. Apply mirroring in one place so the overlay, the face, and the recording use the same setting. See the mirroring notes in Errors and troubleshooting.

The overlay appears in the preview but not in the recording

Confirm the overlay was added before recording started and that the recording uses the processed Nosmai output.

Production checklist

Before release:

  • initialize Nosmai before adding an overlay
  • wait for preview readiness
  • give each overlay a unique identifier
  • keep overlay images at a reasonable resolution
  • reuse downloaded or decoded images
  • update transforms for gestures instead of re-adding overlays
  • handle a failed network image and offer retry
  • test face-attached overlays with movement and no face
  • verify overlays in photo capture, recording, and live streaming
  • test front and back cameras and camera switching
  • test supported low-end and high-end devices

Next steps

Nosmai

We make advanced camera and AI technology accessible to every developer. By packaging hard problems into simple

developers
legal
newsletter

Product updates and release notes. No spam.

© 2026 nosmai, inc · all rights reserved