实现 macOS 美颜
集成 SDK
下载 SDK
前往 下载 页面,获取最新版的 SDK,然后解压。
添加 Framework
将 SDK 包内 Facebetter.framework 库,拷贝到你的项目路径下。
打开 Xcode,参考这里添加 Facebetter.framework 动态库,确保添加的动态库 Embed 属性设置为 Embed & Sign

权限配置
确保开放联网权限,用于校验 appkey 
权限说明:
- 网络权限:必需。SDK 需要联网验证
appId和appKey,确保应用正常运行。
导入头文件
#import <Facebetter/FBBeautyEffectEngine.h>日志配置
默认日志是关闭的,可以按需开启,支持控制台日志和文件日志开关。开启日志要放到美颜引擎创建之前。
FBLogConfig* logConfig = [[FBLogConfig alloc] init];
// 日志级别
logConfig.level = FBLogLevel_Info;
// 控制台日志
logConfig.consoleEnabled = YES;
// 文件日志
logConfig.fileEnabled = YES;
logConfig.fileName = @"log path: xx/xx/facebetter.log";创建配置引擎
按照 此页面 指引,获取 appid 和 appkey
验证方式优先级:
- 如果提供了
licenseJson,使用授权数据验证(支持在线响应和离线授权) - 否则使用
appId和appKey进行自动联网验证
FBEngineConfig *engineConfig = [[FBEngineConfig alloc] init];
engineConfig.appId = @"your appId"; // 配置你的 appid(可选,如果提供了 licenseJson 则不需要)
engineConfig.appKey = @"your appkey"; // 配置你的 appkey(可选,如果提供了 licenseJson 则不需要)
// 可选:使用授权数据验证(如果提供则优先使用)
// engineConfig.licenseJson = @"your license json string";
self.beautyEffectEngine = [FBBeautyEffectEngine createEngineWithConfig:engineConfig];错误处理
创建引擎后建议检查是否成功:
if (self.beautyEffectEngine == nil) {
NSLog(@"Failed to create beauty engine");
return;
}启用特效类型
美颜功能可以按类型开启关闭,根据订阅版本启用相应的美颜类型,每种类型还有对应的参数可以调节
// 所有订阅版本都支持
[self.beautyEffectEngine setBeautyTypeEnabled:FBBeautyType_Basic enabled:TRUE];
// Pro, Pro+ 版本支持
[self.beautyEffectEngine setBeautyTypeEnabled:FBBeautyType_Reshape enabled:TRUE];
// Pro, Pro+ 版本支持
[self.beautyEffectEngine setBeautyTypeEnabled:FBBeautyType_Makeup enabled:TRUE];
// 仅 Pro+ 版本支持
[self.beautyEffectEngine setBeautyTypeEnabled:FBBeautyType_VirtualBackground enabled:TRUE];检查操作结果
所有 API 调用都应该检查返回值:
int ret = [self.beautyEffectEngine setBeautyTypeEnabled:FBBeautyType_Basic enabled:TRUE];
if (ret == 0) {
NSLog(@"Successfully enabled basic beauty");
} else {
NSLog(@"Failed to enable basic beauty, error code: %d", ret);
}调节美颜参数
设置美肤参数
通过 setBasicParam 接口,设置美肤参数,参数范围 [0.0, 1.0];
[self.beautyEffectEngine setBasicParam:FBBasicParam_Smoothing floatValue:0.5f];支持的美肤参数:
typedef NS_ENUM(NSInteger, FBBasicParam) {
FBBasicParam_Smoothing = 0, // 磨皮
FBBasicParam_Sharpening, // 锐化
FBBasicParam_Whitening, // 美白
FBBasicParam_Rosiness, // 红润
};设置美型参数
通过 setReshapeParam 接口,设置美型参数,参数范围 [0.0, 1.0];
[self.beautyEffectEngine setReshapeParam:FBReshapeParam_FaceThin floatValue:0.5f];支持从美型参数:
typedef NS_ENUM(NSInteger, FBReshapeParam) {
FBReshapeParam_FaceThin = 0, // 瘦脸
FBReshapeParam_FaceVShape, // V脸
FBReshapeParam_FaceNarrow, // 窄脸
FBReshapeParam_FaceShort, // 短脸
FBReshapeParam_Cheekbone, // 颧骨
FBReshapeParam_Jawbone, // 下颌骨
FBReshapeParam_Chin, // 下巴
FBReshapeParam_NoseSlim, // 瘦鼻梁
FBReshapeParam_EyeSize, // 大眼
FBReshapeParam_EyeDistance, // 眼距
};设置美妆参数
[self.beautyEffectEngine setMakeupParam:FBMakeupParam_Lipstick floatValue:0.5f];支持的美妆参数:
typedef NS_ENUM(NSInteger, FBMakeupParam) {
FBMakeupParam_Lipstick = 0, // 口红
FBMakeupParam_Blush, // 腮红
};设置虚拟背景
通过 setBeautyTypeEnabled 接口启用虚拟背景:
[self.beautyEffectEngine setBeautyTypeEnabled:FBBeautyType_VirtualBackground enabled:TRUE];通过 setVirtualBackground 接口设置虚拟背景:
// 设置背景模式
FBVirtualBackgroundOptions *options = [[FBVirtualBackgroundOptions alloc] initWithMode:FBBackgroundModeBlur];
[self.beautyEffectEngine setVirtualBackground:options];
// 设置背景图片(需要先设置为 Image 模式)
FBVirtualBackgroundOptions *imageOptions = [[FBVirtualBackgroundOptions alloc] initWithMode:FBBackgroundModeImage];
imageOptions.backgroundImage = backgroundImageFrame; // FBImageFrame 对象
[self.beautyEffectEngine setVirtualBackground:imageOptions];设置引擎回调
监听License验证和引擎初始化状态:
FBEngineCallbacks *callbacks = [[FBEngineCallbacks alloc] init];
callbacks.onEngineEvent = ^(FBEngineEventCode code, NSString* _Nullable message) {
if (code == FBEngineEventCodeLicenseValidationSuccess) {
// License验证成功
NSLog(@"License验证成功");
} else if (code == FBEngineEventCodeLicenseValidationFailed) {
// License验证失败
NSLog(@"License验证失败: %@", message);
} else if (code == FBEngineEventCodeInitializationComplete) {
// 引擎初始化完成
NSLog(@"引擎初始化完成");
} else if (code == FBEngineEventCodeInitializationFailed) {
// 引擎初始化失败
NSLog(@"引擎初始化失败: %@", message);
}
};
[self.beautyEffectEngine setCallbacks:callbacks];事件码:
FBEngineEventCodeLicenseValidationSuccess(0):License验证成功FBEngineEventCodeLicenseValidationFailed(1):License验证失败FBEngineEventCodeInitializationComplete(100):引擎初始化完成FBEngineEventCodeInitializationFailed(101):引擎初始化失败
处理图像
创建图像
图像数据通过 FBImageFrame 封装,支持格式: YUVI420, NV12, NV21, RGB, RGBA, BGR, BGRA
通过 rgba 创建 FBImageFrame
FBImageFrame *input_image = [FBImageFrame createWithRGBA:data width:width height:height stride:stride];通过图片创建 FBImageFrame
FBImageFrame *input_image = [FBImageFrame createWithFile:@"xxx.png"];旋转图像
FBImageFrame 内置图像旋转方法, 可根据需要使用
- (int)rotate:(FBImageRotation)rotation;旋转角度
typedef NS_ENUM(NSInteger, FBImageRotation) {
FBImageRotation0, // 0度
FBImageRotation90, // 顺时针旋转90度
FBImageRotation180, // 顺时针旋转180度
FBImageRotation270, // 顺时针旋转270度
};处理图像
processMode 包括 Video 和 Image 两种,Video 适合直播,视频等场景使用,效率更高,Image 模式适合图片处理场景
input_image.type = FBFrameTypeVideo;
FBImageFrame *output_image = [self.beautyEffectEngine processImage:input_image];获取处理后图像数据
FBImageFrame 现在直接提供了获取图像数据的方法,无需通过 FBImageBuffer。
获取 RGBA 格式数据:
// 如果输出格式是 RGBA,直接获取数据
if ([outputImage format] == FBImageFormatRGBA) {
const uint8_t* data = [outputImage data];
int dataSize = outputImage.size;
int width = outputImage.width;
int height = outputImage.height;
int stride = outputImage.stride;
}获取 I420 格式数据:
// 如果输出格式是 I420,直接获取 Y、U、V 分量数据
if ([outputImage format] == FBImageFormatI420) {
// 独立获取 Y, U, V 分量数据
const uint8_t* dataY = [outputImage dataY];
const uint8_t* dataU = [outputImage dataU];
const uint8_t* dataV = [outputImage dataV];
int strideY = [outputImage strideY];
int strideU = [outputImage strideU];
int strideV = [outputImage strideV];
int width = outputImage.width;
int height = outputImage.height;
}格式转换:
如果需要将 FBImageFrame 转换为其他格式,可以使用 convert: 方法:
// 转换为 I420 格式
FBImageFrame *i420Frame = [outputImage convert:FBImageFormatI420];
if (i420Frame) {
const uint8_t* dataY = [i420Frame dataY];
const uint8_t* dataU = [i420Frame dataU];
const uint8_t* dataV = [i420Frame dataV];
// 使用完毕后,ARC 会自动释放
}
// 转换为 RGBA 格式
FBImageFrame *rgbaFrame = [outputImage convert:FBImageFormatRGBA];
if (rgbaFrame) {
const uint8_t* data = [rgbaFrame data];
// 使用完毕后,ARC 会自动释放
}FBImageFrame 支持转换为以下格式: I420, NV12, NV21, RGB, RGBA, BGR, BGRA。
生命周期管理
释放资源
在 ViewController 销毁时,务必释放引擎资源:
- (void)dealloc {
if (self.beautyEffectEngine) {
// 注意:FBBeautyEffectEngine 是单例,通常不需要手动释放
// 但如果有自定义的清理逻辑,可以在这里处理
self.beautyEffectEngine = nil;
}
}内存管理
- 及时释放
FBImageFrame对象(ARC 会自动管理) - 避免在循环中重复创建大量图像对象
- 建议复用
FBImageFrame对象
// 使用完毕后释放资源
if (inputImage) {
inputImage = nil; // ARC 会自动释放
}
if (outputImage) {
outputImage = nil; // ARC 会自动释放
}
// 格式转换后的 frame,ARC 也会自动释放
if (i420Frame) {
i420Frame = nil; // ARC 会自动释放
}