## 视频直播离线接口方式获取

### 接口地址
[http://as.dun.163.com/v2/livevideo/callback/results](http://as.dun.163.com/v2/livevideo/callback/results)
### 接口描述
该接口用于获取直播流检测结果，检测结果包含截图证据信息及违规分类信息等。建议您使用POST请求, 且仅接受 application/x-www-form-urlencoded 编码格式。

### 接口请求频率
小于10s/20次，请求频率过快服务器会拒绝处理。

### 请求参数
该接口参数与请求公共参数一致，详细见 [请求公共参数](/help/documents/150439172888514560)


| 参数名称  |  类型 | 是否必选 | 最大长度 | 描述 |
|-----------|-------|------|------|-------|
| version | String | Y | 4 | 接口版本v2.1 |

### 响应结果
响应字段如下，响应通用字段已省略，详细见 [响应通用字段](/help/documents/150439250088873984) ：

| 参数名称 | 类型 | 描述 |
|----------|------|------|
| result | json数组 | 检测结果数组 |


result 数据结构

| 参数名称 | 类型 | 描述 |
|----------|------|------|
| status | Number | 视频处理状态码，定义为：101：检测中，102：检测结束 |
| taskId | String | 本次请求数据标识，可以根据该标识查询数据最新结果 |
| callback | String | 产品提交直播流信息时带的 callback 字段数据，用于标识直播流，产品根据业务情况自行设计 |
|censorSource|Number |审核来源，0：易盾人审，1：客户人审，2：易盾机审|
| duration | Number  | 直播时长字段，检测结束之后返回直播整体时长，单位s |
| evidence | json对象 | 证据信息 |
| labels | json数组 | 检测结果数组，如为空，则表示内容正常，如不为空，则表示检测到违规信息 |

evidence数据结构：


| 参数名称 | 类型 | 描述 |
|----------|------|------|
| beginTime | Number | 视频直播当前时间点，单位为毫秒，调用方获取后可自行格式化为可视化时间，如：1599205126000 转换为"2020-09-04 15:38:46"  |
| endTime | Number | 视频直播当前时间点，单位为毫秒，调用方获取后可自行格式化为可视化时间，如：1599205126000 转换为"2020-09-04 15:38:46"  |
| type | Number | 1：图片，2：视频 |
|suggestionLevel|Number|只有视频为嫌疑时才可能返回，表示嫌疑程度：1：低嫌疑，2：高嫌疑|
| url | String | 证据信息 |
| frontPics | json对象数组 | 关联信息-命中前截图信息 |


<md-attention>

#### 证据时间戳说明
	
◆ 证据信息命中黑屏挂机后，type为视频，开始时间和结束时间为证据采集时对应截帧一刻的本地时间。其他垃圾类别，证据开始时间与结束时间一致
	
</md-attention>


labels数据结构

| 参数名称 | 类型 | 描述 |
|----------|------|------|
| label | Number | 分类信息，100：色情，110：性感；200：广告，210：二维码，260：广告法，300：暴恐，400：违禁，500：涉政，800：恶心类，900：其他，1020：黑屏，1030：挂机，1100：涉价值观 |
| subLabels | json数组 | 细分类信息,可能包含多个，可能为空 |
| level | Number | 级别信息，分为1：不确定，2：确定 |
| rate | Number | 分数 |

subLabels 数据结构

| 参数名称 | 类型 | 描述 |
|----------|------|------|
| subLabel | Number | 细分类，详细编码请参考下方对应细分类编码[对应表](/help/documents/447229941660127232) |
| rate | Number | 置信度分数，0-1之间取值，1为置信度最高，0为置信度最低 |
| details | json数组 | htiInfos:命中详细信息 |

details 数据结构
	
| 参数名称 | 类型 | 描述 |
|----------|------|------|
| hitInfos | String | 针对命中sublabel的补充说明 |	
| imageTagInfo | json数组 | 命中标签详细信息，对于返回的hintInfo的解释说明，可能为空 |	
| imageListInfo | json数组 | 命中自定义关键词名单时返回|
| hitLocationInfos | json数组 | 命中详情位置信息，当前人脸、logo、关键词支持位置信息返回 |		
	
imageTagInfo 数据结构
	
| 参数名称 | 类型 | 描述 |
|----------|------|------|
| tagName | String | hinInfo中可返回的图片中包含的可识别内容 |	
| tagGroup | String | tagName对应的分组名称，用于对tageName的解释 |	

imageListInfo 数据结构

| 参数名称 | 类型 | 描述 |
|----------|------|------|
| type |  Number | type为2时为自定义敏感词名单 |	
| word | String | 该图片命中的自定义敏感词 |	
	
hitLocationInfos 数据结构
	
| 参数名称 | 类型 | 描述 |
|----------|------|------|
| hitInfo | String | 命中详情 |	
| x1 | Number | 位置信息，对应目标矩形左上角横坐标相对坐标 |
| y1 | Number | 位置信息，对应目标矩形左上角纵坐标相对坐标 |
| x2 | Number | 位置信息，对应目标矩形右下角横坐标相对坐标 |
| y2 | Number | 位置信息，对应目标矩形右下角纵坐标相对坐标 |


frontPics对象数据结构

| 参数名称 | 类型 | 描述 |
|----------|------|------|
| url | String | 命中截图前3个截图URL信息，不满3个按实际存在截图返回 |


<md-attention>

#### 自定义细分类

易盾支持subLabel自定义细分类过检并返回，如有需求，可联系您的专属运营经理添加。

</md-attention>

### 响应示例
输出结果：

```json
{
    "code": 200,
    "msg": "ok",
    "result": [
        {
            "status":102  //视频处理状态码，定义为：101：检测中，102：检测结束
            "taskId": "b82f6eb1de8d478196a73dd552b73226",  
	    "callback": "40d7e2fba1894512902e92928540a647",
            "duration";10,  //检测中不返回该字段，检测完成最后一次回调返回该字段
            "evidence": {
                "beginTime": 1469774975520,
                "endTime": 1469774975520,
                "type": 1,
                "url": "http://xxx.nos.netease.com/xxx.jpeg"
            },
            "labels": [
                {
                    "label": 500,
                    "level": 2,
                    "rate": 1,
		                 "subLabels": [{
		               		         "subLabel": 50003,
		               	         	"rate": 1.0,
				                      "details": {
				                    	"hitInfos": ["XXX"]
                             }
                            ]
                 }
        {
            "callback": "40d7e2fba1894512902e92928540a647",
            "evidence": {
                "beginTime": 1469775156321,
                "endTime": 1469775156321,
                "type": 1,
                "url": "http://xxx.nos.netease.com/xxxx.jpeg"
            },
            "labels": [
                
            ]
        }
    ]
}
```

## 视频直播回调方式获取结果

回调方式以数据为维度由客户设置回调地址;直播视频实时检测当检测到异常数据时，调用客户提供的回调接口。

### 回调接入说明

接入回调方式很简单，只需要在调用在线检测接口请求参数中指定了回调通知参数callbackUrl(即一个http(s)协议接口的URL)。需要您的回调接口支持http协议，支持POST方法，传输数据编码采用utf-8。


| 业务类型 | 回调参数名称 |  类型 | 最大长度 | 描述 |
|------|------|------|------|------|
| 直播视频 | callbackUrl | String | 256 | 直播视频提交接口添加callbackUrl字段 |

### 回调状态
您服务端接收到我们回调的结果后，返回的HTTP状态码为200时，表示推送成功，其他的HTTP状态码均视为您接收失败，我们将每隔10分钟推送一次，如果一直失败，持续一天后不再推送；回调接口超时时间设置为2s，为了保证顺利接收数据，客户需保证接收接口性能稳定并且保证幂等性。



### 请求公共参数

| 参数名称 | 类型 | 是否必传 | 描述 |
|----------|------|----------|------|
| secretId | String | Y | 产品秘钥 id ，由易盾反垃圾云服务分配，产品标识 |
| businessId | String | Y | 业务id ，由易盾反垃圾云服务分配，业务标识 |
| signature | String | Y | 请求签名，用来验证此次请求的合法性，具体算法见 [接口鉴权](#_9) |
| callbackData | String | Y | 主动推送推送数据，格式为json字符串 |

secretId，businessId，signature参数用来给数据接收接口做签名鉴权用

### 接口鉴权

回调结果可以通过业务开通时易盾分配的密钥信息字段进行接口鉴权，鉴权粒度是否要精确到业务级别，用户可以根据需要自行决定
```java
/**
 * 通过HttpServletRequest做签名验证
 * 
 * @param request
 * @return
 */
public static boolean verifySignature(HttpServletRequest request) {
    String secretId = request.getParameter("secretId");
    String businessId = request.getParameter("businessId");
    String signature = request.getParameter("signature");
    if (StringUtils.isEmpty(secretId) || StringUtils.isEmpty(signature)) {
        // 签名参数为空，直接返回失败
        return false;
    }
    Map<String, String> params = Maps.newHashMap();
    for (String paramName : request.getParameterMap().keySet()) {
        if (!"signature".equals(paramName)) {
            params.put(paramName, request.getParameter(paramName));
        }
    }
    // SECRETKEY:产品私有密钥 SECRETID:产品密钥ID BUSINESSID:业务ID,开通服务时，易盾会提供相关密钥信息
    String serverSignature = getSignature(SECRETKEY, params);
    return signature.equals(serverSignature) && SECRETID.equals(secretId) && BUSINESSID.equals(businessId);
}
```

```java
/**
* 生成签名信息
* @param secretKey 产品私钥
* @param params 接口请求参数名和参数值map，不包括signature参数名
* @return
* @throws UnsupportedEncodingException
*/
public static String genSignature(String secretKey, Map<String, String> params) throws UnsupportedEncodingException {
    // 1. 参数名按照ASCII码表升序排序
    String[] keys = params.keySet().toArray(new String[0]);
    Arrays.sort(keys);

    // 2. 按照排序拼接参数名与参数值
    StringBuffer paramBuffer = new StringBuffer();
    for (String key : keys) {
        paramBuffer.append(key).append(params.get(key) == null ? "" : params.get(key));
    }
    // 3. 将secretKey拼接到最后
    paramBuffer.append(secretKey);

    // 4. MD5是128位长度的摘要算法，用16进制表示，一个十六进制的字符能表示4个位，所以签名后的字符串长度固定为32个十六进制字符。
    return DigestUtils.md5Hex(paramBuffer.toString().getBytes("UTF-8"));
}
```

### 视频直播回调数据结构
callbackData为Json字符串，数据结构如下：
```json
{
    "taskId":"3845768daff04c90b281ad3450791b52",
    "callback":"1593744564",
    "status":102,
    "duration";10,  //检测中不返回该字段，检测完成最后一次回调返回该字段
    "labels":[
        {
            "label":500,
            "level":1,
            "rate":0.99687463,
            "subLabels":[
                {
                    "subLabel":50006,
                    "rate":0.99687463,
                    "details":{
                        "hitInfos":[
                            "banner"
                        ]
                    }
                }
            ]
        }
    ],
    "evidence":{
        "type":1,
        "url":"https://illegal-video.nosdn.127.net/3845768daff04c90b281ad3450791b52_1593744566780.jpg",
        "beginTime":1593744566780,
        "endTime":1593744566780
    }
}
```