# Facial data capture (/en/realtime-media/interactive-live-streaming/build/apply-effects-and-enhancements/face-capture/android)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

The Facial Capture extension collects quantitative data such as facial feature points, head rotation, and head translation. You can use this data to drive 3D facial stickers, headgear, pendant applications, or digital humans, adding more vivid expressions to virtual images.

This guide is intended for use-cases where the facial capture extension is used independently to capture facial data, while a third-party rendering engine is used to animate a virtual human.

<CalloutContainer type="info">
  <CalloutDescription>
    To avoid collecting facial data through callbacks and building your own collection, encoding, and transmission framework, use the Agora [MetaKit extension](metakit.mdx) for facial capture.
  </CalloutDescription>
</CalloutContainer>

      
    ## Prerequisites [#prerequisites]

    Ensure that you have:

    * Implemented the [SDK quickstart](../../index.mdx) in your project.
    * Integrated Video SDK version 4.3.0 or later with the Facial Capture extension dynamic library for your platform.
    * Obtained the face capture authentication parameters `authentication_information` and `company_id` by contacting [Agora technical support](mailto\:extensions.marketplace@agora.io).

    ## Implement the logic [#implement-the-logic]

    This section shows you how to integrate the Facial Capture extension in your app to capture facial data.

    ### Use facial information to drive virtual humans [#use-facial-information-to-drive-virtual-humans]

    The output facial data is in JSON format and includes quantitative information such as facial feature points, head rotation, and head translation. This data follows the Blend Shape (BS) format in compliance with the ARKit standard. You can use a third-party 3D rendering engine to further process the BS data. The key elements are:

    * `faces`: An array of objects, each representing recognized facial information for one face.
      * `detected`: A float representing the confidence level of face recognition, ranging from `0.0` to `1.0`.
      * `blendshapes`: An object containing the face capture coefficients. The keys follow the ARKit standard, with each key-value pair representing a blendshape coefficient, where the value is a float between `0.0` and `1.0`.
      * `rotation`: An array of objects representing head rotation. It contains three key-value pairs. All values are floating points between `-180.0` and `180.0`.
        * `pitch`: The pitch angle of the head. Positive values represent head lowering, negative values represent head raising.
        * `yaw`: The angle of head rotation. Positive values represent left rotation, negative values represent right rotation.
        * `roll`: The tilt angle of the head. Positive values represent right tilt, negative values represent left tilt.
    * `translation`: An object representing head translation, with three key-value pairs: `x`, `y`, and `z`. The values are floats between `0.0` and `1.0`.
    * `faceState`: An integer indicating the current face capture control state:
      * `0`: The algorithm is in surface capture control.
      * `1`: The algorithm control returns to the center.
      * `2`: The algorithm is restored and not in control.
    * `timestamp`: A string representing the output result's timestamp, in milliseconds.

    This data can be used to animate virtual humans by applying the `blendshape` coefficients and head movement data to a 3D model.

    ```json
    {
      "faces": [
        {
          "detected": 0.98,
          "blendshapes": {
            "eyeBlinkLeft": 0.9,
            "eyeLookDownLeft": 0.0,
            "eyeLookInLeft": 0.0,
            "eyeLookOutLeft": 0.0,
            "eyeLookUpLeft": 0.0,
            "eyeSquintLeft": 0.0,
            "eyeWideLeft": 0.0,
            "eyeBlinkRight": 0.0,
            "eyeLookDownRight": 0.0,
            "eyeLookInRight": 0.0,
            "eyeLookOutRight": 0.0,
            "eyeLookUpRight": 0.0,
            "eyeSquintRight": 0.0,
            "eyeWideRight": 0.0
          },
          "rotation": {
            "pitch": 30.0,
            "yaw": 25.5,
            "roll": -15.5
          },
          "translation": {
            "x": 0.5,
            "y": 0.3,
            "z": 0.5
          },
          "faceState": 1
        }
      ],
      "timestamp": "654879876546"
    }
    ```

    <CalloutContainer type="warning">
      <CalloutTitle>
        Important
      </CalloutTitle>

      <CalloutDescription>
        Currently, the facial capture function outputs data for only one face at a time. After the callback is triggered, allocate memory separately to store the facial data and process it in a separate thread. Otherwise, the raw data callback may lead to frame loss.
      </CalloutDescription>
    </CalloutContainer>

    ### Enable the extension [#enable-the-extension]

    To enable the Facial Capture extension, call `enableExtension`:

    <CodeBlockTabs defaultValue="Java">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="Java">
          Java
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="Kotlin">
          Kotlin
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="Java">
        ```java  tabGroup="face-capture-android"
        rtcEngine.enableExtension(
          "agora_video_filters_face_capture",
          "face_capture",
          true,
          Constants.MediaSourceType.PRIMARY_CAMERA_SOURCE
        );
        ```
      </CodeBlockTab>

      <CodeBlockTab value="Kotlin">
        ```kotlin  tabGroup="face-capture-android"
        rtcEngine.enableExtension(
          "agora_video_filters_face_capture",
          "face_capture",
          true,
          Constants.MediaSourceType.PRIMARY_CAMERA_SOURCE
        )
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    <CalloutContainer type="info">
      <CalloutDescription>
        When you enable the Facial Capture extension for the first time, a delay may occur. To ensure smooth operation during a session, call `enableExtension` before joining a channel.
      </CalloutDescription>
    </CalloutContainer>

    ### Set authentication parameters [#set-authentication-parameters]

    To ensure that the extension functions properly, call `setExtensionProperty` to pass the necessary authentication parameters.

    <CodeBlockTabs defaultValue="Java">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="Java">
          Java
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="Kotlin">
          Kotlin
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="Java">
        ```java  tabGroup="face-capture-auth-android"
        rtcEngine.setExtensionProperty(
          "agora_video_filters_face_capture",
          "face_capture",
          "authentication_information",
          "{\"company_id\":\"xxxxx\",\"license\":\"xxxxx\"}",
          Constants.MediaSourceType.PRIMARY_CAMERA_SOURCE
        );
        ```
      </CodeBlockTab>

      <CodeBlockTab value="Kotlin">
        ```kotlin  tabGroup="face-capture-auth-android"
        rtcEngine.setExtensionProperty(
          "agora_video_filters_face_capture",
          "face_capture",
          "authentication_information",
          "{\"company_id\":\"xxxxx\",\"license\":\"xxxxx\"}",
          Constants.MediaSourceType.PRIMARY_CAMERA_SOURCE
        )
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    ### Retrieve facial data [#retrieve-facial-data]

    Retrieve raw video data containing facial information through the `onCaptureVideoFrame` callback.

    ```java
    public boolean onCaptureVideoFrame(int sourceType, VideoFrame videoFrame) {
      if (videoFrame.getMetaInfo() != null) {
        VideoFrameMetaInfo metaInfo = videoFrame.getMetaInfo();
        SparseArray<IMetaInfo> customMetaInfo =
            metaInfo.getCustomMetaInfo("FaceCaptureInfo");
        if (customMetaInfo != null && customMetaInfo.size() >= 1) {
          String faceInfo = ((FaceCaptureInfo) customMetaInfo.get(0)).getInfoStr();
          Log.d(TAG, "Face Info: " + faceInfo);
        }
      }
      return true;
    }
    ```

    ### Disable the extension [#disable-the-extension]

    To disable the Facial Capture extension, call `enableExtension`:

    ```java
    rtcEngine.enableExtension(
      "agora_video_filters_face_capture",
      "face_capture",
      false,
      Constants.MediaSourceType.PRIMARY_CAMERA_SOURCE
    );
    ```

    ## Reference [#reference]

    ### Sample project [#sample-project]

    * [Face Capture for Android](https://github.com/AgoraIO/API-Examples/blob/main/Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/FaceCapture.java)

    ### API reference [#api-reference]

    * [`addExtension`](https://api-ref.agora.io/en/video-sdk/android/4.x/API/class_irtcengine.html#api_irtcengine_addextension)
    * [`registerExtension`](https://api-ref.agora.io/en/video-sdk/android/4.x/API/class_irtcengine.html#api_irtcengine_registerextension)
    * [`setExtensionProperty`](https://api-ref.agora.io/en/video-sdk/android/4.x/API/class_irtcengine.html#api_irtcengine_setextensionproperty)
    * [`enableExtension`](https://api-ref.agora.io/en/video-sdk/android/4.x/API/class_irtcengine.html#api_irtcengine_enableextension)
    * [`onCaptureVideoFrame`](https://api-ref.agora.io/en/video-sdk/android/4.x/API/class_ivideoframeobserver.html#callback_ivideoframeobserver_oncapturevideoframe)

    
  
      
  
      
  
      
  
