Android

相芯美颜

更新时间: 2025/06/11 16:45:39

网易云信 NERTC SDK 支持接入 相芯 等第三方专业美颜滤镜厂商,实现美颜、美妆、滤镜、贴纸等美颜特效。在娱乐社交、在线教育等场景中,您可以快速构建具备美颜特效能力的应用,让用户在进行视频通话或直播时,呈现更良好的肌肤状态和精神面貌。

相芯美颜(Faceunity Nama SDK,下文简称 Nama SDK)的详细功能介绍请参考 人脸特效

准备工作

根据本文操作前,请确保您已经完成了以下设置:

  1. 下载相芯美颜 SDK(推荐使用 V8.3.0 版本)
  2. 获取相芯美颜 SDK 的证书,具体请联系 网易云信 商务经理。
  3. 获取相芯美颜资源文件,具体请联系 网易云信 商务经理。
  4. 集成 NERTC SDK,推荐使用 NERTC V4.6.50 及以后版本,V4.6.50 版本对相芯美颜进行了优化。

功能原理

相芯美颜原理.png
  1. NERTC SDK 提供了 setVideoCallback 采集数据回调的接口,将采集到的视频图像数据通过该接口回调出来。

  2. Nama SDK 通过回调获取视频图像数据,进行美颜处理后,通过参数返回给 NERTC SDK。

  3. NERTC SDK 将美颜后的数据进行编码和传输。

基本概念

  • 纹理(Texture):纹理指的是一张二维的图片,把它像贴纸一样贴在图元上面,让图元看起来像贴纸所要表现的效果那样。
  • NV21:NV21 是 YUV420SP 图像编码的一种类型。根据 YUV 来定义图像的颜色,其中 Y 表示明亮度,U 和 V 分别表示色调和饱和度。Android 系统的相机默认的图像格式是 NV21。它比 RGB 模型的图像更省存储空间和带宽。
  • 双输入:纹理+ YUV 双份数据输入。

注意事项

  • 美颜相关方法返回值为 false 时,表示方法调用失败。
  • 调用 enableLocalVideo 开启本地视频采集时,请设置 streamTypekNERtcVideoStreamTypeMain,否则美颜效果不会生效。

集成相芯美颜

  1. 将证书文件 authpack.java 放到本地项目的 faceunity/com/faceunity/fulivedemo 目录下。

  2. 将所需的美颜模型和道具放到本地项目的 assets 目录下,例如 /app/src/main/assets/Resource

  3. 通过 Gradle 集成相芯美颜 SDK。详细步骤请参考 Faceunity Nama 官网文档

    在项目对应模块的 build.gradle 中加入以下行。

    Groovy// allprojects 配置
    allprojects {
        repositories {
            ...
            maven { url 'http://maven.faceunity.com/repository/maven-public/' }
            ...
    }
    }
    
    // dependencies 导入依赖
    dependencies {
    ...
    implementation "com.faceunity:nama:8.3.0
    ...
    }
    
    

视频图像处理

根据不同的视频数据格式,分别介绍纹理渲染、NV21 渲染和双输入三种场景的视频图像处理,并提供相应的示例代码。

方案一:纹理渲染

  1. 设置 NERTC 的视频属性

    调用 setLocalVideoConfig 方法的 videoConfig 参数,设置视频的分辨率、图像的数据格式。

    在本示例中,视频的分辨率为 640 x 360 px,帧率为 15 fps,图像数据格式 colorFormatTEXTURE。示例代码如下:

    Java// NERTC SDK 默认设置,可以不调用
    NERtcVideoConfig videoConfig = new NERtcVideoConfig();
    config.width = 640;
    config.height = 360;
    videoConfig.colorFormat = NERtcConstants.VideoColorFormat.TEXTURE;   //在纹理渲染的场景中,请设置为 TEXTURE
    config.frameRate = NERtcVideoConfig.NERtcVideoFrameRate.FRAME_RATE_FPS_15;
    NERtcEx.getInstance().setLocalVideoConfig(videoConfig);
    
  2. 初始化相芯美颜 SDK

    初始化时,setInputTextureType 设置的图像数据格式需要和 NERTC 中设置的图像数据格式(colorFormat)保持一致。在本示例中,都采用 TEXTURE 渲染。

    JavaFURenderer.setup(this);
    mFURenderer = new FURenderer.Builder(this)
            .setInputTextureType(FURenderer.INPUT_TEXTURE_EXTERNAL_OES)     //在纹理渲染的场景中,指定输入格式为 TEXTURE
            .setCameraFacing(mCameraFacing)
            .setInputImageOrientation(CameraUtils.getCameraOrientation(mCameraFacing))
            .setRunBenchmark(true)
            .setOnDebugListener(new FURenderer.OnDebugListener() {
                @Override
                public void onFpsChanged(double fps, double callTime) {
                    final String FPS = String.format(Locale.getDefault(), "%.2f", fps);
                    Log.i(TAG, "onFpsChanged: FPS " + FPS + " callTime " + String.format(Locale.getDefault(), "%.2f", callTime));
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (mTvFps != null) {
                                mTvFps.setText("FPS: " + FPS);
                            }
                        }
                    });
                }
            }).build();
    
    
  3. 在成功加入房间后,调用 NERTC 的 enableLocalVideo 接口,开启本地视频采集,请设置 streamTypekNERtcVideoStreamTypeMain,否则美颜效果不会生效。

  4. 调用 NERTC 的 setVideoCallback 接口,设置摄像头采集数据的回调。在 onVideoCallback 回调中,将原始的视频图像数据发给相芯美颜 SDK,美颜 SDK 将美颜处理后的数据返回给 NERTC SDK,NERTC SDK 对美颜后的数据进行预览以及编码发送。

    JavaNERtcEx.getInstance().setVideoCallback(new NERtcVideoCallback() {
        @Override
        public boolean onVideoCallback(NERtcVideoFrame neRtcVideoFrame) {
            long start = System.nanoTime();
            int texId = 0;
            texId = mFURenderer.onDrawFrameSingleInput(neRtcVideoFrame.textureId, neRtcVideoFrame.width, neRtcVideoFrame.height);
            long renderTime = System.nanoTime() - start;
    
            neRtcVideoFrame.textureId = texId;
            neRtcVideoFrame.format = NERtcVideoFrame.Format.TEXTURE_RGB;       //在纹理渲染的场景中,请设置输出格式为 TEXTURE_RGB
            return true;
        }
    }, false);
    

方案二:NV21 渲染

  1. 设置 NERTC 的视频属性

    调用 setLocalVideoConfig 方法的 videoConfig 参数,设置视频的分辨率、图像的数据格式。

    在本示例中,视频的分辨率为 640 x 360 px,帧率为 15 fps,图像数据格式 colorFormatNV21。示例代码如下:

    JavaNERtcVideoConfig videoConfig = new NERtcVideoConfig();
    config.width = 640;
    config.height = 360;
    videoConfig.colorFormat = NERtcConstants.VideoColorFormat.NV21;
    config.frameRate = NERtcVideoConfig.NERtcVideoFrameRate.FRAME_RATE_FPS_15;
    NERtcEx.getInstance().setLocalVideoConfig(videoConfig);
    
  2. 初始化相芯美颜 SDK

    在 NV21 渲染的场景中,setInputTextureType 时不需要指定渲染模式,设置了也不起作用。

    JavaFURenderer.setup(this);
    mFURenderer = new FURenderer.Builder(this)
            .setCameraFacing(mCameraFacing)
            .setInputImageOrientation(CameraUtils.getCameraOrientation(mCameraFacing))
            .setRunBenchmark(true)
            .setOnDebugListener(new FURenderer.OnDebugListener() {
                @Override
                public void onFpsChanged(double fps, double callTime) {
                    final String FPS = String.format(Locale.getDefault(), "%.2f", fps);
                    Log.i(TAG, "onFpsChanged: FPS " + FPS + " callTime " + String.format(Locale.getDefault(), "%.2f", callTime));
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (mTvFps != null) {
                                mTvFps.setText("FPS: " + FPS);
                            }
                        }
                    });
                }
            }).build();
    
    
  3. 在成功加入房间后,调用 NERTC 的 enableLocalVideo 接口,开启本地视频采集,请设置 streamTypekNERtcVideoStreamTypeMain,否则美颜效果不会生效。

  4. 调用 NERTC 的 setVideoCallback 接口,设置摄像头采集数据的回调。在 onVideoCallback 回调中,将原始的视频图像数据发给相芯美颜 SDK,美颜 SDK 将美颜处理后的数据返回给 NERTC SDK,NERTC SDK 对美颜后的数据进行预览以及编码发送。

    JavaNERtcEx.getInstance().setVideoCallback(new NERtcVideoCallback() {
        @Override
        public boolean onVideoCallback(NERtcVideoFrame neRtcVideoFrame) {
            long start = System.nanoTime();
            int texId = 0;
            texId = mFURenderer.onDrawFrameSingleInput(neRtcVideoFrame.data, neRtcVideoFrame.width, neRtcVideoFrame.height, IFURenderer.INPUT_FORMAT_NV21_BUFFER);     //设置输入格式为 NV21
            long renderTime = System.nanoTime() - start;
    
            neRtcVideoFrame.textureId = texId;
            neRtcVideoFrame.format = NERtcVideoFrame.Format.TEXTURE_RGB;   //设置输出格式为 TEXTURE_RGB
            return true;
        }
    }, false);
    
    

方案三:双输入

在双输入模式中,您可以 1 路采用 I420 格式用于人脸检测,1 路采用纹理格式用于美颜。

  1. 设置 NERTC 的视频属性

    调用 setLocalVideoConfig 方法的 videoConfig 参数,设置视频的分辨率、图像的数据格式。

    在本示例中,视频的分辨率为 640 x 360 px,帧率为 15 fps,图像数据格式 colorFormatTEXTURE。示例代码如下:

    JavaNERtcVideoConfig videoConfig = new NERtcVideoConfig();
    config.width = 640;
    config.height = 360;
    videoConfig.colorFormat = NERtcConstants.VideoColorFormat.TEXTURE;   //在双输入模式下,推荐输入的格式为 TEXTURE
    config.frameRate = NERtcVideoConfig.NERtcVideoFrameRate.FRAME_RATE_FPS_15;
    NERtcEx.getInstance().setLocalVideoConfig(videoConfig);
    
  2. 初始化相芯美颜 SDK

    初始化时,setInputTextureType 设置的图像数据格式需要和 NERTC 中设置的图像数据格式(colorFormat)保持一致。在本示例中,都采用 TEXTURE 渲染。

    JavaFURenderer.setup(this);
    mFURenderer = new FURenderer.Builder(this)
            .setInputTextureType(FURenderer.INPUT_TEXTURE_EXTERNAL_OES)     //在双输入场景中,指定输入格式为 TEXTURE
            .setCameraFacing(mCameraFacing)
            .setInputImageOrientation(CameraUtils.getCameraOrientation(mCameraFacing))
            .setRunBenchmark(true)
            .setOnDebugListener(new FURenderer.OnDebugListener() {
                @Override
                public void onFpsChanged(double fps, double callTime) {
                    final String FPS = String.format(Locale.getDefault(), "%.2f", fps);
                    Log.i(TAG, "onFpsChanged: FPS " + FPS + " callTime " + String.format(Locale.getDefault(), "%.2f", callTime));
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (mTvFps != null) {
                                mTvFps.setText("FPS: " + FPS);
                            }
                        }
                    });
                }
            }).build();
    
    

    FuRenderer.java 中修改如下代码,设置输入格式。

    Javaprivate int createFlags() {
        int inputTextureType = mInputTextureType;
        int flags = inputTextureType | mInputImageFormat;
        if (mCameraFacing != CAMERA_FACING_FRONT) {
            flags |= faceunity.FU_ADM_FLAG_FLIP_X;
            flags |= faceunity.FU_ADM_FLAG_TEXTURE_AND_READBACK_BUFFER_OPPOSITE_Y;
        }
        flags |= faceunity.FU_ADM_FLAG_EXTERNAL_OES_TEXTURE | faceunity.FU_ADM_FLAG_ENABLE_READBACK;
        return flags;
    }
    
  3. 在成功加入房间后,调用 NERTC 的 enableLocalVideo 接口,开启本地视频采集,请设置 streamTypekNERtcVideoStreamTypeMain,否则美颜效果不会生效。

  4. 调用 NERTC 的 setVideoCallback 接口,设置摄像头采集数据的回调。通过 onVideoCallback 回调,将原始的视频图像数据发给相芯美颜 SDK,美颜 SDK 将美颜处理后的数据返回给 NERTC SDK,NERTC SDK 对美颜后的数据进行预览以及编码发送。

    JavaNERtcEx.getInstance().setVideoCallback(new NERtcVideoCallback() {
        @Override
        public boolean onVideoCallback(NERtcVideoFrame neRtcVideoFrame) {
            long start = System.nanoTime();
            int texId = 0;
            texId = mFURenderer.onDrawFrameDualInput(neRtcVideoFrame.data, neRtcVideoFrame.textureId, neRtcVideoFrame.width, neRtcVideoFrame.height);
            long renderTime = System.nanoTime() - start;
    
            //输出 NV21 格式:两种输出格式二选一即可
            neRtcVideoFrame.format = NERtcVideoFrame.Format.NV21;
    
            //输出 TEXTURE_RGB:
            neRtcVideoFrame.textureId = texId;
            neRtcVideoFrame.format = NERtcVideoFrame.Format.TEXTURE_RGB;
            return true;
        }
    }, false);
    
    

设置美颜效果

美颜、美妆、滤镜、贴纸效果的具体参数设置,请参考 Faceunity Nama 相关文档

示例项目源码

网易云信提供 相芯美颜的示例项目源码,您可以参考该源码实现相芯美颜。

API 参考

方法 功能描述
enableLocalVideo 开启本地视频采集。
setVideoCallback 设置摄像头采集数据的回调。
NERtcVideoCallback 视频帧数据回调。

常见问题

使用美颜后画面会闪一下,怎么办?

  • 可能原因:相芯 7.x.x 版本 SDK 前 5 帧存在渲染问题。

  • 解决方案

    • 升级相芯版本至 8.x.x 版本。
    • 若不想升级相芯版本,在美颜处理时,建议您丢弃前 5 帧。

使用美颜后画面出现闪屏、黑屏,怎么办?

  • 可能原因:美颜拿到了采集的过程数据没拿到结果数据。
  • 解决方案
    • 初始化相芯 SDK 时,调用 fuSetUseTexAsync(true) 方法。
    • 升级 NERTC SDK 至 4.6.50 及以后的版本。详情请参考 升级指南

使用美颜后出现画面卡顿,怎么办?

  • 可能原因 1:采集帧率设置太高,例如 30 帧,美颜也会按照 30 帧率进行处理。在一些低端机上,高帧率会对整个系统产生较大的压力,美颜处理时间可能会超过每一帧预期的帧间隔,引发画面卡顿。

  • 解决方案:降低采集帧率,在 NERTC SDK 的视频配置中,将帧率设置为 15。

  • 可能原因 2:相芯 SDK 日志级别太低,导致每处理一帧都会打印大量日志,影响整体性能。

  • 解决方案:在初始化时,关闭相芯 SDK 日志,将日志级别设置为 OFF

    JavaFURenderManager.setKitDebug(FULogger.LogLevel.OFF);
    FURenderManager.setCoreDebug(FULogger.LogLevel.OFF);
    

Android 支持的最低系统版本是多少

推荐使用 V4.3 及以上版本。

是否需要设置 OpenGL 环境,创建 EGL context

不需要,虽然 NERTC SDK 的 view 继承自 SurfaceView,不具备系统自带的 GL 环境,但是网易云信在 setVideoCallback 的回调中设定了 GL 环境,并创建了相应的 EGL context,生命周期同 NERTC。

FURenderer(Nama SDK)的生命周期

FURenderer 的生命周期是独立的,和 NERTC 无关,但是两者通过 setVideoCallback 共享了 EGL context 的生命周期,因此需要 FURenderer 美颜相关接口的调用在 NERTC 的 initrelease 之间,并且 确保 NERTC 在 release 之后,FURenderer 也需要释放

1 对 1 视频通话场景中接入美颜,第一次打开本地预览正常,第二次打开本地预览画面闪一下后黑屏/花屏

排查思路:

  1. 先注释掉 setVideoCallback 相关代码,检查本地预览是否正常。如果预览正常,继续执行后续步骤排查接口调用逻辑。

  2. 如果第一次预览结束后,调用了 NERtcEx.getInstance().release() 接口去释放 NERTC SDK,则也需要调用 destroyFU() 去释放相芯资源。因为 NERTC 已经被释放,EGL Context 已经失效,Nama SDK 默认丢掉前几帧画面,所以您可以看到前面几帧没有经过相芯处理的画面一闪而过,后面的数据无法正常拿到,所以显示黑屏。

解决方案:

  • 调用 release 释放 NERTC SDK 资源后,也需要调用 destroyFU() 去释放 Nama SDK。

  • 如果没有调用 release 释放 NERTC SDK 资源,则无需每次调用 destroyFU() 去释放 Nama SDK,Nama SDK 与 NERTC SDK 共享 EGL Context。

开启美颜后,预览画面绿屏

检查 NERtcEx.getInstance().setVideoCallback() 回调中,返回的 neRtcVideoFrame 的 format 是否正确。

Nama SDK 处理完之后的数据默认为 TEXTURE_RGB,需要正确设置纹理为 NERtcVideoFrame.Format.TEXTURE_RGB 才能正常渲染。

此文档是否对你有帮助?
有帮助
去反馈
  • 准备工作
  • 功能原理
  • 基本概念
  • 注意事项
  • 集成相芯美颜
  • 视频图像处理
  • 方案一:纹理渲染
  • 方案二:NV21 渲染
  • 方案三:双输入
  • 设置美颜效果
  • 示例项目源码
  • API 参考
  • 常见问题
  • 使用美颜后画面会闪一下,怎么办?
  • 使用美颜后画面出现闪屏、黑屏,怎么办?
  • 使用美颜后出现画面卡顿,怎么办?
  • Android 支持的最低系统版本是多少
  • 是否需要设置 OpenGL 环境,创建 EGL context
  • FURenderer(Nama SDK)的生命周期
  • 1 对 1 视频通话场景中接入美颜,第一次打开本地预览正常,第二次打开本地预览画面闪一下后黑屏/花屏
  • 开启美颜后,预览画面绿屏