# 活体检测（NELiveDetection）

## 简介

`NELiveDetection` 为支持活体检测 h5 的 JS SDK，根据提示做出相应动作，SDK 实时采集动态信息，判断用户是否为活体、真人。

## 浏览器支持

pc 浏览器需内置 chromium 内核且保证版本符合如下要求：

| 浏览器  | 最低版本 |
| ------- | -------- |
| Chrome  | 56       |
| Edge    | 12       |
| Firefox | 36       |
| Opera   | 40       |
| Safari  | 11       |
| IE      | 不支持   |

移动端浏览器：

| 浏览器                 | 最低版本 |
| ---------------------- | -------- |
| Safari in iOS          | 14.3       |
| Android Browser        | 99       |
| Opera Mobile           | 64       |
| Chrome for Android     | 99       |
| Firefox for Android    | 96       |
| UC Browser for Android | 12.12    |
| Samsung Internet       | 6.2      |
| QQ Browser             | 10.4     |
| Opera Mini             | 不支持   |
 
浏览器不支持时，会自动降级方式到视频活体，若不需要自动降级，可设置 `fallback` 为 `false`。

## 快速上手

按照以下步骤快速调用示例。

### 资源引入

安装 `npm` 包：

```bash
# npm
npm install @yidun/livedetect-sdk-h5@latest
# yarn
yarn add @yidun/livedetect-sdk-h5@latest
# pnpm
pnpm add @yidun/livedetect-sdk-h5@latest
```

在代码中使用包

```js
import NELiveDetection from '@yidun/livedetect-sdk-h5';
import '@yidun/livedetect-sdk-h5/dist/es/NELiveDetection.css';
```

## 快速调用示例

请注意，示例需要启动一个本地服务（比如 vscode 的 LiveServer、vue-cli 的 serve 或 webpack 的 devServer，并且必须是 https 方式，不然会提示`浏览器不支持`。

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, viewport-fit=cover" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <meta name="referrer" content="origin" />
    <title>活体检测H5接入示例</title>
    <style>
      #NELiveDetection {
        width: 100%;
        height: 100%;
      }
    </style>
    <!-- 引入 sdk 样式文件 -->
    <link rel="stylesheet" href="NELiveDetection.min.css" />
  </head>
  <body>
    <div id="root">
      <div id="NELiveDetection"></div>
    </div>

    <!-- 引入 sdk -->
    <script src="NELiveDetection.umd.js"></script>

    <script>
      (function () {
        const neLiveDetection = new NELiveDetection({
          businessKey: '易盾申请的 businessKey（传入业务ID，非密钥信息）',
          container: '#NELiveDetection',
          diameter: 220,
          onMount: (instance) => {},
          // 等价于 instance.on('ready', () => {})
          onReady: (instance) => {},
        });

        // 实例化后必须调用 mount 方法
        neLiveDetection && neLiveDetection.mount();

        // 调用 start 方法开始活体检测流程
        neLiveDetection.on('ready', () => {
          neLiveDetection.start();
        });

        // 流程走完并检验完成
        neLiveDetection.on('verify', (token) => {
          console.log('token:', token);
          // 在校验成功后拿到 token 去做服务端校验
        });

        // 发生错误
        neLiveDetection.on('error', (err) => {
          console.log('err:', err);
          switch (err.name) {
            case '10000': // 校验未通过错误码
              // 如果校验未成功，会返回 err 对象，做后续处理
              break;
            // 其他错误码
            default:
              break;
          }
        });
      })();
    </script>
  </body>
</html>
```

## 配置说明

在初始化实例时，可以传入以下配置：

| 参数        | 类型                  | 默认值  | 描述                             | 是否必填 |
| ----------- | --------------------- | ------- | -------------------------------- | -------- |
| businessKey | String                | -       | 从易盾申请的 `bussinessKey`      | 是       |
| container   | String \| HTMLElement | -       | SDK 挂载的容器                   | 是       |
| diameter    | Number                | `220`   | 图像显示区域大小，单位为 `px`    | 否       |
| audio       | Boolean               | `false` | 摄像头唤起时是否开启声音录制     | 否       |
| footerTip   | Boolean               | `true`  | 是否显示底部图像和文字提示       | 否       |
| lang        | string                | `zh-CN` | 语言，支持列表见下方语言支持列表 | 否       |
| fallback        | Boolean                | `true` | 是否降级到视频录制上传（2.1.0支持） | 否       |
| preload	    | Boolean	              | `false`	  | 初始化是否开启预加载，开启后模型会提前加载和解析| 否 |
| onMount     | Function              | -       | 初始化实例挂载完成回调           | 否       |
| onReady     | Function              | -       | 活体检测前的准备工作已完成回调   | 否       |

<md-attention>

特别说明

`onMount` 和 `onReady` 的区别：

`onMount` 和 `onReady` 触发时，均会返回活体检测的实例，即传入的第一个参数；二者触发时机有所不同：

`onMount` 触发时，初始化函数结束和完成实例的生成，注意这并不代表活体检测是可用的（比如不能调用 `.start()` 开启流程），此方法只触发一次；

`onReady` 触发时，说明活体检测准备就绪，可以开始流程，所有实例方法都可调用，`onReady` 初始化时会触发一次，之后每次调用 `.restart()` 都会再次调用。

</md-attention>

## 实例方法

你可以在实例完成创建之后，调用以下方法：

- `instance.start()`：

开始验证，此时会唤起摄像头，该⽅法只会在⾸次验证的时候调⽤，后续需要⽤ `restart` ⽅法。

- `instance.restart()`：

当动作超时或者采集流程超时，需要重新发起认证，这时候⽤ `restart` ⽅法。

- `instance.dispose()`：

销毁验证流程，建议在组件卸载时调⽤。

## 事件回调

在验证过程中会抛出⼀些回调事件，⽤户可以监听这些事件，⾃⾏做⼀些处理，⽐如 ready，校验通过，超时...

- **ready 事件**

```js
instance.on('ready', () => {
  // 活体验证已准备好
  // 可在此调用 .start() 方法
});
```

- **timeout 事件**

```js
instance.on('timeout', () => {
  // 检测超时，可提示用户重新开始流程
});
```

- **checking 事件**

```js
instance.on('checking', () => {
  // 流程走完后，进行校验的开始回调
  // 可在页面显示 loading 状态
});
```

- **check-done 事件**

```js
instance.on('check-done', () => {
  // 校验完成，可在页面关闭 loading 状态，进行后续操作
});
```

- **verify 事件**

```js
instance.on('verify', (token) => {
  console.log(token);
  // 在验证成功后才会触发，拿到 token，进行后续的服务端校验（recheck）
});
```

- **error 事件**

```js
instance.on('error', (err) => {
  // 发生错误
  // err.name 为错误码，字符串类型；
  // err.message 为错误信息，字符串类型
  console.log(err);
});
```

## 支持语言

| 语言 | 参数值  |
| ---- | ------- |
| 中文 | `zh-CN` |
| 英文 | `en-US` |

## 错误码

| 错误码 | 错误信息                             |
| ------ | ------------------------------------ |
| 10000  | 校验不通过                           |
| 10001  | 校验接口网络错误                     |
| 11000  | 获取相机权限失败                     |
| 11001  | 鉴权不通过                           |
| 11002  | 浏览器不支持，默认降级到视频活体，如不需要，可以将初始化参数 fallback 设置为 false |
| 11003  | 用户拒绝相机权限授权                 |
| 11004  | 找不到摄像头                         |
| 11005  | 异常硬件导致无法读取摄像头           |
| 11006  | 摄像头分辨率过低                     |
| 11007  | 未知问题导致摄像头无法被使用         |
| 11008  | 炫瞳检测失败                         |
| 12000  | 获取配置接口网络错误                 |
| 12001  | 获取配置失败，请检查接入配置是否正确 |

## 常⻅问题

#### 1. 提示「浏览器不⽀持」：

- 先检查下部署是否为 `https` 协议；
- 然后检查当前使⽤的浏览器是否⽀持 `webrtc`。

#### 2. 提示「没有摄像头权限」：

- 检查客户是否开启相机授权，没有开启权限可根据错误回调做提示用户。
