Skip to content

Meishe AR Face Filter

This topic describes how to integrate and use the Meishe AR Face Filter plugin in Agroa WebRTC project.

Precondition

Before you begin, ensure that the following requirements are met:

  • For Windows or macOS computers, the following requirements must be met:
    • PC browser version: ipad and pad devices are not supported.
    • Chrome,Opera,360 browser: the kernel is Chrome, version 75 includes more than support;
    • Firefox browser: The kernel version is greater than 58, including the above support (special cases: version 72 is not supported);
    • Safari browser: minimum 15.4, 17.0 and above the best performance, recommended to the latest version
    • Physical audio and video acquisition equipment.
    • Internet connection possible. If you have a firewall deployed in your network environment, see Dealing with Firewall restrictions to use the sound network service normally.
  • Installed Node.js and npm

Integration And Invocation

1. Integrate SDK and plugin

To get started, you need to integrate the Agora SDK and Meishe AR Face Filter plug-ins into your project.

tip: The authentication files, template package files, model package files, and packet files in all the following examples can be obtained by contacting meishe Business.

1.1 Integration with Agora Video SDK

The Meishe AR Face Filter plugin needs to work with the Agora Web SDK 4.x (v4.10.0 or later). Refer to the following documentation to integrate the Web SDK and implement basic video calling:

Implement audio and video calls

1.2 Integrated plugin

Follow these steps to integrate plug-ins:

Integrate the Meishe AR Face Filter plugin into your project via npm.

  1. Run the following command to install the plug-in:

    typescript
    npm i agora-meishe-effect-sdk
  2. Add the following code to your .ts file to import the plug-in module:

    typescript
    import { EffectSDKExtension, EffectSDKProcessor } from 'agora-meishe-effect-sdk'

2. Configure Meishe AR Face Filter plugin environment

The Meishe AR Face Filter plugin needs to configure the response header to make the SharedArrayBuffer available.

2.1 Vite environment

The following configuration is added to the configuration plugins in vite.config.ts:

typescript
plugins:[
    {
      name: 'configure-response-headers',
      configureServer: (server) => {
        server.middlewares.use((_req, res, next) => {
          res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
          res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
          res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')
          next()
        })
      },
      configurePreviewServer: (server) => {
        server.middlewares.use((_req, res, next) => {
          res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
          res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
          res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')
          next()
        })
      },
    },
    ...
]

2.2 Webpack environment

Add the following configuration to webpack.config.ts configuration plugins:

typescript
devServer:{
	headers: {
      'Cross-Origin-Opener-Policy':'same-origin',
      'Cross-Origin-Embedder-Policy':'require-corp',
      'Cross-Origin-Resource-Policy': 'cross-origin'
    },
    ...
}

The purpose of adding the above configuration is to add the above setting to the request header to notify the browser to open the SharedArrayBuffer.

The above syntax is affected by webpack and vite versions, and the specific API can be configured according to their respective versions.

3. Register plugin

Follow these steps to register the plugin:

  1. CreateeffectSDKExtension instance.

    typescript
    const effectSDKExtension = new EffectSDKExtension()
  2. Call AgoraRTC. RegisterExtensions and to create a effectSDKExtension instance.

    AgoraRTC.registerExtensions([effectSDKExtension])

4. Initialize the Meishe AR Face Filter plugin

The purpose of initializing the smart beauty effects plugin is to load the sdk and a series of model packages and data packages. To realize the recognition/loading of beauty, makeup, face, avatar, portrait, stickers, subtitles, background segmentation, special effects props and other functions.

The specific configurations are as follows:

typescript
const effectSDKProcessor = effectSDKExtension.createProcessor()
// arSceneRenderer is the Meishe AR Face Filter instance and needs to be saved
const arSceneRenderer = await effectSDKProcessor.init({
  faceModelUrl: 'https://xxx',
  eyecontourModelUrl: 'https://xxx',
  avatarModelUrl: 'https://xxx',
  segmentationModelUrl: 'https://xxx',
  makeupDataUrl: 'https://xxx',
  fakefaceDataUrl: 'https://xxx',
  faceCommonDataUrl: 'https://xxx',
  advancedBeautyDataUrl: 'https://xxx',
  detectionMode: 32768 | 32, //Flag,fixed configuration
  ratio: width + ':' + height,
  sdkCDNUrl: 'https://xxx', //CDN link
  licFileUrl: 'xxx.lic', //Authorization file address
  mirror: true, //or false
})

The type of arSceneRenderer returned after initializing the Meishe AR Face Filter plug-in is NveARSceneRenderer, and various attribute methods can be found from the type document.

5. Open Meishe AR Face Filter plugin special effects

Follow these steps to enable special effects:

  1. Invoke the RTC SDK AgoraRTC. CreateCameraVideoTrack method to create local camera video track:

    typescript
    // Create a video using the RTC SDK
    const videoTrack = await AgoraRTC.createCameraVideoTrack()
  2. Call Meishe AR Face Filter skin care effects plug-ins EffectSDKExtension. CreateProcessor create beauty plug-in processor processor instances:

    typescript
    // Processor to create beauty plugin
    const effectSDKProcessor = EffectSDKExtension.createProcessor()
  3. Invoke the RTC SDK videoTrack. Pipe method and specify videoTrack. ProcessorDestination attribute, the plug-in into the SDK camera data stream processing pipeline:

    typescript
    // Set up the video processing pipeline
    videoTrack.pipe(effectSDKProcessor).pipe(videoTrack.processorDestination)
  4. Invoke the enableBeauty method of the Meishe AR Face Filter plugin to enable basic beauty functions:

    typescript
    // Enable basic beauty function
    arSceneRenderer.enableBeauty(true)

Sample code

A piece of code that implements the plug-in's functionality is listed below for your reference.

  1. vite.config.ts

    typescript
    export default defineConfig({
      plugins: [
        react(),
        {
          name: 'configure-response-headers',
          configureServer: (server) => {
            server.middlewares.use((_req, res, next) => {
              res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
              res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
              res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')
              next()
            })
          },
          configurePreviewServer: (server) => {
            server.middlewares.use((_req, res, next) => {
              res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
              res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
              res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin')
              next()
            })
          },
        },
      ],
    })
  2. Function code

    typescript
    import AgoraRTC from 'agora-rtc-sdk-ng'
    import { EffectSDKExtension, EffectSDKProcessor } from 'agora-meishe-effect-sdk'
    
    const effectSDKExtension = new EffectSDKExtension()
    AgoraRTC.registerExtensions([effectSDKExtension])
    const effectSDKProcessor = effectSDKExtension.createProcessor()
    // arSceneRenderer is the Meishe AR Face Filter plugin instance and needs to be saved
    const arSceneRenderer = await effectSDKProcessor.init({
      faceModelUrl: 'https://xxx',
      eyecontourModelUrl: 'https://xxx',
      avatarModelUrl: 'https://xxx',
      segmentationModelUrl: 'https://xxx',
      makeupDataUrl: 'https://xxx',
      fakefaceDataUrl: 'https://xxx',
      faceCommonDataUrl: 'https://xxx',
      advancedBeautyDataUrl: 'https://xxx',
      detectionMode: 32768 | 32, //Flag,fixed configuration
      ratio: width + ':' + height,
      sdkCDNUrl: 'https://xxx', //CDN link
      licFileUrl: 'xxx.lic', //Authorization file address
      mirror: true, //or false
    })
    // Create a video using the RTC SDK
    const videoTrack = await AgoraRTC.createCameraVideoTrack()
    // Set up the video processing pipeline
    videoTrack.pipe(effectSDKProcessor).pipe(videoTrack.processorDestination)
    
    // Enable basic beauty function
    arSceneRenderer.enableBeauty(true)
    
    // Set beauty
    const effectList = [
      {
        key: 'Advanced Beauty Intensity',
        intensity: 1,
      },
      {
        key: 'Beauty Whitening',
        intensity: 1,
      },
    ]
    
    // Set makeup
    effectList.push([
      {
        url: 'https://xxx.makeup', //makeup package address
        licUrl: 'xxxx',
        intensity: 1,
      },
    ])
    
    // Set
    effectList.push([
      {
        url: 'https://xxxx',
        licUrl: 'xxxx',
        intensity: 1,
      },
    ])
    
    arSceneRenderer.setEffectList(effectList)
    
    videoTrack.play(document.getElementById('video-container'))

API Reference

Meishe AR Face Filter API

EffectSDKExtension

typescript
new EffectSDKExtension()

Create an example of a plug-in extender. This method is an export method of a Meishe AR Face Filter plug-in.

createProcessor

typescript
createProcessor()

Creates a plug-in processor, returning an instance of EffectSDKProcessor. This method is located under the EffectSDKExtension class.

init

typescript
effectSDKProcessor.init()

Initialize the plug-in and return the plug-in instance, whose class is NveARSceneRenderer. The init method is located under the EffectSDKProcessor class.

enableBeauty

typescript
enableBeauty()

Turn on/off beauty effects to control only the built-in beauty effects. This method is located under the 'NveARSceneRenderer' plug-in instance

Turn on/off beauty effects to control only the built-in beauty effects. This method is located under the NveARSceneRenderer plug-in instance.

setEffectList

typescript
setEffectList()

Set the list of effects. You can set beauty, beauty makeup, beauty type, filter, props, background. This method is located under the NveARSceneRenderer plug-in instance.

getEffectList

typescript
getEffectList()

Gets a list of all the effects that have been set, including added beauty, filters, props, and more. This method is located under the NveARSceneRenderer plug-in instance.

createExternalEffectInstance

typescript
createExternalEffectInstance()

Create extended effects instances for creating captions and stickers instances. This method is located under the NveARSceneRenderer plug-in instance.

appendExternalEffectInstance

typescript
appendExternalEffectInstance()

Add an extended effects instance to the plugin instance. This method is located under the NveARSceneRenderer plug-in instance.

setExternalEffectInstanceList

typescript
setExternalEffectInstanceList()

Gets a list of all added extension effects. This method is located under the NveARSceneRenderer plug-in instance.

Special effect setting

Beauty

  1. Built-in effects

    Built-in special effects do not need special effects package, which belongs to the built-in ability of the smart beauty effects plug-in, but you need to know the key name. The specific content can be viewed in the Meishu SDK Web document, which is roughly as follows:

    typescript
    // key is the built-in special effects keyword used to distinguish special effects functions
    // intensity indicates the specific intensity. The value ranges from [-1,1] to [0,1]
    // sdk built-in hundreds of built-in effects, range and key values can be found by yourself
    const beautyArray = [
    	{
    		key:'Advanced Beauty Intensity',
    		intensity:1
    	},
        {
    		key:'Beauty Whitening',
    		intensity:1
    	},
        {
    		key:'Beauty Reddening',
    		intensity:1
    	},
        {
    		key:'Face Mesh Face Width Degree',
    		intensity:1
    	},
        {
    		key:'Face Mesh Face Length Degree',
    		intensity:1
    	},
        {
    		key:'Face Mesh Face Size Degree',
    		intensity:1
    	},
        {
    		key:'Face Mesh Forehead Height Degree',
    		intensity:1
    	},
        ...
    ]
    
    arSceneRenderer.setEffectList(beautyArray)
  2. Beauty template

    Unlike built-in effects, beauty templates need to be passed into the template package, not the key value. The code is as follows:

    typescript
    const templateArray = [
      {
        url: 'https://xxxx',
        licUrl: 'xxxx',
        intensity: 1,
      },
      {
        url: 'https://xxxx',
        licUrl: 'xxxx',
        intensity: 1,
      },
    ]
    arSceneRenderer.setEffectList(templateArray)

Makeup

  1. normal package

    Ordinary beauty bags have lipstick, eyeshadow, eyebrows, eyelashes, eyeliner, blush, shine, shadow, contact lenses, makeup and a series of categories. The configuration method is the same as the beauty template, and the code is as follows:

    typescript
    const makeupArray = [
      {
        url: 'https://xxx.makeup',
        licUrl: 'xxxx',
        intensity: 1,
      },
      {
        url: 'https://xxx.makeup',
        licUrl: 'xxxx',
        intensity: 1,
      },
    ]
    
    arSceneRenderer.setEffectList(makeupArray)
  2. Complete package

    The whole bag is the integration of a series of ordinary bags. The configuration method is as follows:

    typescript
    arSceneRenderer.setEffectList([
      {
        url: 'https://xxx.zip',
      },
    ])

Filter

Filters are configured in the same way as beauty bags, and the code is as follows:

typescript
const filterArray = [
  {
    url: 'https://xxxx',
    licUrl: 'xxxx', // lic File url
    intensity: 1,
  },
]
arSceneRenderer.setEffectList(filterArray)

Virtual background

  1. background blur

    You need to specify the background blur special effects package, as follows:

    typescript
    arSceneRenderer.setEffectList([
      {
        url: 'https://xxx.videofx',
        licUrl: '',
      },
    ])
  2. Background substitution

    Background The replacement configuration is as follows:

    typescript
    arSceneRenderer.setEffectList([
      { segmentationBackgroundUrl: 'https://xxx.png' }, //image url
    ])

AR scene

The configuration method is the same as the filter, and the code is as follows:

typescript
arSceneRenderer.setEffectList([
  {
    url: 'https://xxx.arscene', // AR scene package Url
    licUrl: '', // AR scene license Url
  },
])

Caption

1 common caption

Common subtitling categories include flower characters, dynamic subtitling, word-for-word subtitling, bubble subtitling and so on. The configuration method is not the same as beauty makeup.

createExternalEffectInstance method parameter information table:

ParameterTypeMustDefaultDescription
modularBooleannofalseWhether it is module captioning, the module captioning type can add effects such as bubbles and animations.
textStringyestext
inPointNumberyesbegin time.The unit is microsecond
durationNumberyesThe unit is microsecond,set to Number.MAX_SAFE_INTEGER indicates continuous display.
urlStringnocommon caption package address
licUrlStringnoAddress of the ordinary package authorization file
fontFileUrlStringnoIf the font file address is not set, the non-English text will be displayed incorrectly because the corresponding font cannot be found.
captionRendererUrlStringnoFloral effect style package address.
captionRendererLicUrlStringnoThe address of the license file corresponding to the flower effect style package.
captionContextUrlStringnoBubble effect style pack ground
captionContextLicUrlStringnoBubble effect style package address.
captionAnimationUrlStringnoAnimation effects style package address.
captionAnimationLicUrlStringnoLicense file address corresponding to the animation effects style package.
animationPeriodNumbernoLicense file address corresponding to the animation effects style package. Animation effect period, in milliseconds.
captionInAnimationUrlStringnoEnter the license file address corresponding to the animation effects style package.
captionInAnimationLicUrlStringnoEnter animation style package address.
inAnimationDurationNumbernoEnter the duration of the animation effect in milliseconds.
captionOutAnimationUrlStringnoCreate animation style package address.
captionOutAnimationLicUrlStringnoThe address of the license file corresponding to the animation style package.
outAnimationDurationNumbernoDuration of the animation, in milliseconds.
positionXNumbernoHorizontal position, normalized value, range [-1, 1], center 0, positive direction to the right.
positionYNumbernoVertical position, normalized value, range [-1, 1], center is 0, upward is positive direction.
positionStringnoFor orientation information, the values that can be set include top-left, top, top-right, left, center, right, bottom-left, bottom, and bottom-right.
  1. add

    Subtitle creation method for createExternalEffectInstance, subtitles add methods for appendExternalEffectInstance.

    In the following example, the various subtitle effects are created using the same API with different parameters. Refer to the above parameter table for specific parameters

    typescript
    // common caption
    const caption = await arSceneRenderer.createExternalEffectInstance({
      text: 'caption',
      inPoint: 0,
      duration: 5000000,
    })
    
    // Create regular subtitles with subtitles style
    const caption = await arSceneRenderer.createExternalEffectInstance({
      text: 'caption',
      inPoint: 0,
      duration: 5000000,
      url: 'https://xxx.captionstyle',
      licUrl: '',
    })
    
    // Create regular captions with captioning styles and a splash effect
    const caption = await arSceneRenderer.createExternalEffectInstance({
      text: 'caption',
      inPoint: 0,
      duration: 5000000,
      url: 'https://xxx.captionstyle',
      licUrl: '',
      captionRendererUrl: 'https://xxx.captionrenderer',
      captionRendererLicUrl: '',
    })
    
    // Create regular captions with location information
    const caption = await arSceneRenderer.createExternalEffectInstance({
      text: 'caption',
      inPoint: 0,
      duration: 5000000,
      positionX: -0.6,
      positionY: 0.9,
    })
    
    // Create regular captions with orientation information
    const caption = await arSceneRenderer.createExternalEffectInstance({
      text: 'caption',
      inPoint: 0,
      duration: 5000000,
      position: 'top-right',
    })
    
    // Create plain subtitles with fonts
    const caption = await arSceneRenderer.createExternalEffectInstance({
      text: 'caption',
      inPoint: 0,
      duration: 5000000,
      fontFileUrl: 'https://xxx.ttf',
    })
    
    // Create unstyled module captions
    const caption = await arSceneRenderer.createExternalEffectInstance({
      modular: true,
      text: 'modularCaption',
      inPoint: 0,
      duration: 5000000,
    })
    
    // Create module captions with a splash effect
    const caption = await arSceneRenderer.createExternalEffectInstance({
      modular: true,
      text: 'modularCaption',
      inPoint: 0,
      duration: 5000000,
      captionRendererUrl: 'https://xxx.captionrenderer',
      captionRendererLicUrl: '',
    })
    
    // Create a module caption with a bubble effect
    const caption = await arSceneRenderer.createExternalEffectInstance({
      modular: true,
      text: 'modularCaption',
      inPoint: 0,
      duration: 5000000,
      captionContextUrl: 'https://xxx.captioncontext',
      captionContextLicUrl: '',
    })
    
    // Create module captions with animated effects
    const caption = await arSceneRenderer.createExternalEffectInstance({
      modular: true,
      text: 'modularCaption',
      inPoint: 0,
      duration: 5000000,
      captionAnimationUrl: 'https://xxx.captionanimation',
      captionAnimationLicUrl: '',
      animationPeriod: 2500,
    })
    
    // Use the interface of the caption instance to modify the other attributes of the caption
    caption.scaleCaption2(0.8)
    caption.setUnderline(true)
    
    // Adding a caption instance
    arSceneRenderer.appendExternalEffectInstance(caption)

    The normal subtitle instance type is NveCaption, and various attributes and methods are configured. You can refer to the linked document.

  2. get

    To obtain a list of current setting all extension effects, use getExternalEffectInstanceList method. The code is as follows:

    typescript
    // Get a list of all expanded effects.Note that the expanded effects are not just captions.There may be other effects that need to be filtered
    // You can also maintain your own list of already set subtitle instances
    let instanceList = arSceneRenderer.getExternalEffectInstanceList()
    let captionInstanceList = instanceList.filter((instance) => instance instanceof NveCaption)
  3. delete

    Through getExternalEffectInstanceList access list, find the same as the current subtitle instance id item and delete. Through setExternalEffectInstanceList resetting list. The code is as follows:

    typescript
    let deleteInstanceId = 'xxxx' // The id of the subtitle instance to remove
    let instanceList = arSceneRenderer.getExternalEffectInstanceList() // Get a list of extended effects on deletion without filtering
    let index = instanceList.findIndex((instance) => instance.id !== deleteInstanceId) // Gets the index of the deleted child
    if (index !== -1) {
      instanceList[index].release() // release resource
      instanceList.splice(index, 1)
      arSceneRenderer.setExternalEffectInstanceList(instanceList) // Resets the list of extended effects
    }
2 Compound caption

createExternalEffectInstance parameters listed in reference ordinary subtitles form.

The code is as follows:

typescript
const compoundCaption = await arSceneRenderer.createExternalEffectInstance({
  inPoint: 0,
  duration: 5000000,
  url: 'https://xxx.compoundcaption',
  licUrl: '',
})

// Create compound captions with location information
const compoundCaption = await arSceneRenderer.createExternalEffectInstance({
  inPoint: 0,
  duration: 5000000,
  url: 'https://xxx.compoundcaption',
  licUrl: '',
  positionX: -0.6,
  positionY: 0.9,
})

// Create a composite caption with location information Create a composite caption with orientation location information
const compoundCaption = await arSceneRenderer.createExternalEffectInstance({
  inPoint: 0,
  duration: 5000000,
  url: 'https://xxx.compoundcaption',
  licUrl: '',
  position: 'top-right',
})

// Modify other properties using the interface of the composite caption instance
compoundCaption.scaleCaption2(0.8)
compoundCaption.setText(0, 'caption0')

// Add a composite caption instance
arSceneRenderer.appendExternalEffectInstance(compoundCaption)

The instance type of the combined caption is NveCompoundCaption, which can be configured in the same way as normal captions

Animated Sticker

Stickers are created in a similar way to captions, but the parameters are somewhat different.The table of parameters is as follows:

ParameterTypeMustDefaultDescription
inPointNumberyesStart time of the animated sticker in microseconds.
durationNumberyesDuration of the animated sticker in microseconds, set to Number.MAX_SAFE_INTEGER to indicate continuous display.
urlStringnoAnimated sticker pack address.
licUrlStringnoThe address of the license file corresponding to the animation sticker package.
animatedStickerAnimationUrlStringnoAnimation style package address.
animatedStickerAnimationLicUrlStringnoThe license file address for the animation style pack.
animationPeriodNumbernoAnimation effect period in milliseconds.
animatedStickerInAnimationUrlStringnoEnter animation style package address.
animatedStickerInAnimationLicUrlStringnoEnter the animation style package corresponding to the license file address.
inAnimationDurationNumbernoEnter the duration of the animation effect in milliseconds.
animatedStickerOutAnimationUrlStringnoCreate animation style package address.
animatedStickerOutAnimationLicUrlStringnoThe address of the license file corresponding to the animation style package.
outAnimationDurationNumbernoDuration of the animation, in milliseconds.
positionXNumbernoHorizontal position, normalized value, range [-1, 1], center 0, positive direction to the right.
positionYNumbernoVertical position, normalized value, range [-1, 1], center is 0, upward is positive direction.
positionStringnoFor orientation information, the values that can be set include top-left, top, top-right, left, center, right, bottom-left, bottom, and bottom-right.

The code is as follows:

typescript
// Create stickers that don't animate
const sticker = await arSceneRenderer.createExternalEffectInstance({
  inPoint: 0,
  duration: 5000000,
  url: 'https://xxx.animatedsticker',
  licUrl: '',
})

// Create animated stickers
const sticker = await arSceneRenderer.createExternalEffectInstance({
  inPoint: 0,
  duration: 5000000,
  url: 'https://xxx.animatedsticker',
  licUrl: '',
  animatedStickerAnimationUrl: 'https://xxx.animatedstickeranimation',
  animatedStickerAnimationLicUrl: '',
  animationPeriod: 5000,
})

// Create stickers with location information
const sticker = await arSceneRenderer.createExternalEffectInstance({
  inPoint: 0,
  duration: 5000000,
  url: 'https://xxx.animatedsticker',
  licUrl: '',
  positionX: -0.6,
  positionY: 0.9,
})

// Create stickers with orientation information
const sticker = await arSceneRenderer.createExternalEffectInstance({
  inPoint: 0,
  duration: 5000000,
  url: 'https://xxx.animatedsticker',
  licUrl: '',
  position: 'top-right',
})

// Modify other properties using the interface of the animated sticker instance
sticker.scaleAnimatedSticker2(0.5)

// Add an instance of animated stickers
arSceneRenderer.appendExternalEffectInstance(sticker)

The instance type of the sticker is NveAnimatedSticker, which can be operated and configured according to the idea of subtitles.

RTC API

RTC Web SDK plugins related methods: