Skip to main content
This page matches SDK 2.0.0. Makeup / reshape enums: Parameter enums.

Choose the right frame type

Set FBImageFrame.type before processImage:. There is no process-mode argument on the engine.
  • FBFrameTypeVideo (1): camera preview, live, calls — lower latency.
  • FBFrameTypeImage (0): still photos — higher quality.

Large stills (preview vs export)

Do not feed full-resolution pixels into processImage: on every slider change, and do not throw the original away after scaling. When the photo opens, keep the full UIImage and build one preview frame (long edge about 1280–1440, createWithUIImage:). Slider changes process the preview (FBFrameTypeImage). Export processes a full-resolution frame with the same setters. Output size matches the input. Camera preview stays capture resolution + FBFrameTypeVideo.

Parameter ranges

  • Skin / makeup / filter intensity: [0.0, 1.0]. 0 turns that effect off.
  • Reshape (setReshape:intensity:): [-1.0, 1.0]. 0 is off. Positive and negative are opposite directions.
Start low on live video. Full enum meanings: Parameter enums.

One engine, one serial queue

createEngineWithConfig: returns an instance, not a process-wide singleton. Keep one engine per session and call it from a serial queue (or the GL thread when externalContext = YES).
Do not process frames on the main thread except for tiny stills. Do not share one engine across concurrent queues.

Memory

  • Prefer ARC. Drop FBImageFrame references when a frame is done.
  • Reuse pixel buffers from the camera; avoid allocating a new RGBA buffer every frame if the capture format is already NV12 / BGRA.
  • Filters and stickers load on the next processImage: (GL thread). Do not reload the same .fbd every frame — call setFilter: / setSticker: once, then setFilterIntensity: as needed.
  • Use clearFilter, clearSticker, clearVirtualBackground, and clearChromaKey instead of creating a second engine.

External OpenGL ES

When the app already owns a GL context:
  1. Set config.externalContext = YES.
  2. Create the engine on that GL thread.
  3. Wrap the texture with createWithTexture:width:height:stride:.
  4. Read the output with [output texture].
Input texture, engine, and output texture must stay in the same context.

Monitor with getStats

Prefer FBEngineStats over a homemade timer:
Aim for avgProcessTimeMs under ~33 ms at 30 fps. If it climbs, drop resolution, switch to FBFrameTypeVideo, or turn off unused makeup / stickers.

Lifecycle

Hold the engine as a strong property on the view controller (or a session object). Nil it in dealloc when the session ends. Pause capture in viewWillDisappear / applicationDidEnterBackground so you stop calling processImage: — you do not need a special “pause” API.
Use __weak in FBEngineCallbacks blocks to avoid retain cycles.

iOS capture

  • Camera preview is usually kCVPixelFormatType_420YpCbCr8BiPlanarFullRange (NV12) or BGRA. Create FBImageFrame with createWithNV12:... or createWithBGRA:... instead of converting to RGBA on the CPU.
  • Front camera: setMirror:@"horizontal" on the frame (or mirror: if you need the pixels flipped before the engine).
  • Camera permission: NSCameraUsageDescription in Info.plist. Photo library: NSPhotoLibraryUsageDescription if you pick stills.

Testing

  • Bind the test app’s Bundle ID and use a real appId / appKey or licenseToken. Dummy strings fail with license events 1 / 101.
  • Cover still (FBFrameTypeImage + createWithUIImage:) and live (FBFrameTypeVideo) paths.
  • Assert setter return codes are FBErrorCode_Success.