实现 Web 美颜
集成 SDK
通过 npm 安装:
bash
npm install facebetter使用 ES Module(推荐):
javascript
import {
BeautyEffectEngine,
EngineConfig,
BeautyType,
BasicParam,
ReshapeParam,
MakeupParam,
BackgroundMode,
VirtualBackgroundOptions,
ProcessMode
} from 'facebetter';使用 CommonJS:
javascript
const { BeautyEffectEngine, EngineConfig } = require('facebetter');日志配置
默认日志是关闭的,可以按需开启:
javascript
await engine.setLogConfig({
consoleEnabled: true, // 控制台日志
fileEnabled: false, // 文件日志(浏览器环境不支持)
level: 0, // 日志级别:0=DEBUG, 1=INFO, 2=WARN, 3=ERROR
fileName: 'facebetter.log' // 日志文件名(可选,仅当 fileEnabled 为 true 时有效)
});注意:日志配置需要在引擎初始化之前调用。
创建配置引擎
按照 此页面 指引,获取 appId 和 appKey
javascript
import { BeautyEffectEngine, EngineConfig } from 'facebetter';
const config = new EngineConfig({
appId: 'your appId', // 配置你的 appid
appKey: 'your appKey' // 配置你的 appkey
});
const engine = new BeautyEffectEngine(config);错误处理
创建引擎后建议检查是否成功:
javascript
try {
await engine.init();
console.log('引擎初始化成功');
} catch (error) {
console.error('引擎初始化失败:', error);
// 处理错误
}启用特效类型
美颜功能可以按类型开启关闭,根据订阅版本启用相应的美颜类型,每种类型还有对应的参数可以调节
javascript
import { BeautyType } from 'facebetter';
// 所有订阅版本都支持
engine.setBeautyTypeEnabled(BeautyType.Basic, true);
// Pro, Pro+ 版本支持
engine.setBeautyTypeEnabled(BeautyType.Reshape, true);
// Pro, Pro+ 版本支持
engine.setBeautyTypeEnabled(BeautyType.Makeup, true);
// 仅 Pro+ 版本支持
engine.setBeautyTypeEnabled(BeautyType.VirtualBackground, true);检查操作结果
所有 API 调用都应该检查返回值或使用 try-catch:
javascript
import { BeautyType } from 'facebetter';
try {
engine.setBeautyTypeEnabled(BeautyType.Basic, true);
console.log('成功启用基础美颜');
} catch (error) {
console.error('启用基础美颜失败:', error);
}调节美颜参数
设置美肤参数
通过 setBasicParam 接口,设置美肤参数,参数范围 [0.0, 1.0](浮点数);
javascript
import { BasicParam } from 'facebetter';
engine.setBasicParam(
BasicParam.Smoothing,
0.5 // 0.0-1.0
);支持的美肤参数:
javascript
BasicParam = {
Smoothing: 0, // 磨皮
Sharpening: 1, // 锐化
Whitening: 2, // 美白
Rosiness: 3 // 红润
};设置美型参数
通过 setReshapeParam 接口,设置美型参数,参数范围 [0.0, 1.0](浮点数);
javascript
import { ReshapeParam } from 'facebetter';
engine.setReshapeParam(
ReshapeParam.FaceThin,
0.5 // 0.0-1.0
);支持的美型参数:
javascript
ReshapeParam = {
FaceThin: 0, // 瘦脸
FaceVShape: 1, // V脸
FaceNarrow: 2, // 窄脸
FaceShort: 3, // 短脸
Cheekbone: 4, // 颧骨
Jawbone: 5, // 下颌骨
Chin: 6, // 下巴
NoseSlim: 7, // 瘦鼻梁
EyeSize: 8, // 大眼
EyeDistance: 9 // 眼距
};设置美妆参数
通过 setMakeupParam 接口,设置美妆参数,参数范围 [0.0, 1.0](浮点数);
javascript
import { MakeupParam } from 'facebetter';
engine.setMakeupParam(
MakeupParam.Lipstick,
0.5 // 0.0-1.0
);支持的美妆参数:
javascript
MakeupParam = {
Lipstick: 0, // 口红
Blush: 1 // 腮红
};设置虚拟背景
通过 setBeautyTypeEnabled 接口启用虚拟背景:
javascript
engine.setBeautyTypeEnabled(BeautyType.VirtualBackground, true);通过 setVirtualBackground 接口设置虚拟背景(统一接口,与其他平台一致):
javascript
import { VirtualBackgroundOptions, BackgroundMode } from 'facebetter';
// 设置模糊背景
const blurOptions = new VirtualBackgroundOptions({
mode: BackgroundMode.Blur
});
engine.setVirtualBackground(blurOptions);
// 设置图片背景
const bgImage = new Image();
bgImage.onload = () => {
const imageOptions = new VirtualBackgroundOptions({
mode: BackgroundMode.Image,
backgroundImage: bgImage
});
engine.setVirtualBackground(imageOptions);
};
bgImage.src = 'background.jpg';
// 关闭虚拟背景
const noneOptions = new VirtualBackgroundOptions({
mode: BackgroundMode.None
});
engine.setVirtualBackground(noneOptions);简化写法(也支持):
javascript
// 直接传对象,不需要 new VirtualBackgroundOptions
engine.setVirtualBackground({
mode: BackgroundMode.Blur
});
// 设置图片背景
bgImage.onload = () => {
engine.setVirtualBackground({
mode: BackgroundMode.Image,
backgroundImage: bgImage
});
};处理图像
从 Canvas 获取图像数据
javascript
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);从图片元素获取图像数据
javascript
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 处理图像...
};
img.src = 'image.jpg';处理图像
processImage 方法支持多种输入类型,processMode 包括 Video 和 Image 两种,Video 适合直播、视频等场景使用,效率更高,Image 模式适合图片处理场景。
javascript
import { ProcessMode } from 'facebetter';
// 方式一:传入 ImageData 和尺寸
const result = engine.processImage(
imageData,
canvas.width,
canvas.height,
ProcessMode.Video // 或 ProcessMode.Image
);
// 方式二:传入 HTMLImageElement(自动获取尺寸,width/height 可省略)
const result = engine.processImage(
imageElement,
undefined,
undefined,
ProcessMode.Image
);
// 方式三:传入 HTMLVideoElement(自动获取尺寸,width/height 可省略)
const result = engine.processImage(
videoElement,
undefined,
undefined,
ProcessMode.Video
);
// 方式四:传入 Uint8ClampedArray(必须提供 width/height)
const result = engine.processImage(
uint8Array,
640, // 必需
480, // 必需
ProcessMode.Video
);绘制处理后图像
javascript
// 将处理后的图像数据绘制到 Canvas
ctx.putImageData(result, 0, 0);保存处理后的图片
处理后的图像数据可以保存为图片文件:
方式一:使用 Canvas.toDataURL()
javascript
// 将处理后的图像数据绘制到 Canvas
ctx.putImageData(result, 0, 0);
// 转换为 Data URL
const dataURL = canvas.toDataURL('image/png');
// 创建下载链接
const link = document.createElement('a');
link.download = 'beauty-result.png';
link.href = dataURL;
link.click();方式二:使用 Canvas.toBlob()
javascript
// 将处理后的图像数据绘制到 Canvas
ctx.putImageData(result, 0, 0);
// 转换为 Blob
canvas.toBlob(function(blob) {
// 创建下载链接
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = 'beauty-result.png';
link.href = url;
link.click();
// 释放 URL 对象
URL.revokeObjectURL(url);
}, 'image/png');方式三:保存为不同格式
javascript
// 保存为 PNG(无损,文件较大)
const pngDataURL = canvas.toDataURL('image/png');
// 保存为 JPEG(有损,文件较小,可设置质量)
const jpegDataURL = canvas.toDataURL('image/jpeg', 0.9); // 质量 0-1
// 创建下载
function downloadImage(dataURL, filename, mimeType) {
const link = document.createElement('a');
link.download = filename;
link.href = dataURL;
link.click();
}
// 使用
downloadImage(pngDataURL, 'beauty-result.png', 'image/png');
downloadImage(jpegDataURL, 'beauty-result.jpg', 'image/jpeg');完整示例:保存处理后的图片
javascript
function processAndSaveImage(imageData, engine) {
try {
// 处理图像(同步方法)
const result = engine.processImage(
imageData,
imageData.width,
imageData.height,
ProcessMode.Image
);
// 创建临时 Canvas
const canvas = document.createElement('canvas');
canvas.width = imageData.width;
canvas.height = imageData.height;
const ctx = canvas.getContext('2d');
// 绘制处理后的图像
ctx.putImageData(result, 0, 0);
// 保存为图片
canvas.toBlob(function(blob) {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = `beauty-${Date.now()}.png`;
link.href = url;
link.click();
URL.revokeObjectURL(url);
}, 'image/png');
console.log('图片保存成功');
} catch (error) {
console.error('处理或保存图片失败:', error);
}
}生命周期管理
释放资源
在页面卸载或不再使用时,务必释放引擎资源:
javascript
// 页面卸载时
window.addEventListener('beforeunload', () => {
if (engine) {
engine.destroy();
engine = null;
}
});
// 或在组件销毁时(Vue/React)
onUnmounted(() => { // Vue
if (engine) {
engine.destroy();
engine = null;
}
});
useEffect(() => { // React
return () => {
if (engine) {
engine.destroy();
engine = null;
}
};
}, []);内存管理
- 及时释放不再使用的 ImageData 对象
- 避免在循环中重复创建大量图像对象
- 建议复用 Canvas 和 ImageData 对象
javascript
// 复用 Canvas 和 ImageData
let canvas = null;
let imageData = null;
function processFrame() {
if (!canvas) {
canvas = document.createElement('canvas');
canvas.width = 640;
canvas.height = 480;
}
const ctx = canvas.getContext('2d');
// 绘制图像到 canvas
ctx.drawImage(video, 0, 0);
// 获取图像数据
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 处理图像
const result = engine.processImage(
imageData,
canvas.width,
canvas.height,
ProcessMode.Video
);
// 绘制结果
ctx.putImageData(result, 0, 0);
}