Android开发文档
视频通话
鉴黄

1. 功能概述

1.1 需求介绍

在视频通话过程中,需要对主播端和用户端画面进行截屏,但不对鉴黄结果处理,而在匹配通话过程中公共房间同样开启视频鉴黄,对不合规进行挂断处理,进入私密房间后和普通通话处理一致,该功能旨在通过整合即构SDK和网易IM SDK,结合网易易盾来实现。具体实现思路是通过即构SDK按照后台返回配置的频率截取对端画面图片,然后通过IM SDK将图片发送到预先设置好的系统IM账号,图片消息最终会经易盾审核后,将审核结果返回给前端并做后续处理。

1.2 业务流程

  1. 主播端和用户端接通视频通话
  2. 双方开始按照后端配置频率截对端图并发送图片,最后到易盾审核
  3. 根据审核结果和后端配置来确定是否模糊画面或者挂断通话

1.3 目标步骤

  1. 通过后端鉴黄配置接口获取鉴黄配置参数,从而控制前台鉴黄截图频率
  2. 将该图片临时存储本地,通过网易IM SDK发送图片消息API,设置相关易盾参数后并按照后台返回配置的频率发送给指定系统账号。
  3. 易盾通过回调返回给前端,前端根据结果来进行处理
  4. 善后处理,比如清理本地临时图片,从会话列表过滤掉上面指定系统账号(10000)等等

2. 准备条件

在开始实现该功能前,请确保以下条件已满足:

  • 实现音视频通话
  • 接入最新网易IM SDK
  • 易盾后台开启功能并配置相关包名

3.技术方案

3.1 技术原理

易盾

开通安全通服务后,调用发送图片消息方法时传入相关参数(NIMAntiSpamOption)可实现消息内容过安全通审核。

在 Android 平台中,如果需要对自定义消息进行安全通检测,需要对即将发送的消息调用 IMMessagesetNIMAntiSpamOption 方法,传递参数为 NIMAntiSpamOption 对象,开发者需要构造这个 NIMAntiSpamOption 对象。其中,content 参数用于说明自定义消息的内容是文本还是图片,以便安全通按照相应类型进行内容安全检测处理。NIMAntiSpamOption 参数说明及示例如下:

  • NIMAntiSpamOption 参数说明:
参数说明
enableboolean,是否过安全通检测,若 App 并没有开通安全通,则设置无效。若设置为 false,则不使用反垃圾
contentString,自定义内容安全字段,仅对自定义消息有效
antiSpamConfigIdString,可选项,安全通配置 id,可以指定此消息过安全通某个检测配置。支持文本和图片两种消息类型

content 必须传递 JSON 对象,长度不超过 5000 字节,格式如下

{
    "type": 1, //1:文本,2:图片
    "data": "" //文本内容or图片地址
}

4. 功能实现

4.1 获取接口配置参数

调用/api/v3/startApp接口,在返回结果里面通过解析获取screenshotsFrequency的值,格式如下:

"screenshotsFrequency": {
      "0-1": 10,
      "1-3": 20,
      "3-999": 30
 },

例如上面格式代表含义:通话第1分钟内每隔10秒截屏一次,1到3分钟内,每隔20秒截屏一次,3到999分钟内,每隔30秒截屏一次

4.2 视频截图

Android对于每次间隔时间执行某个任务有很多方法,可以结合需求和场景选择一个合适的,但需要注意的是频率,避免重复多次执行后,截图频率发生变化,所以释放资源就显得尤为重要,这一点可以重点测试下,另外,即构也提供了对应的推流画面截图和拉流画面截图,分别是:

// 推流画面截图
engine.takePublishStreamSnapshot(object : IZegoPublisherTakeSnapshotCallback {
    override fun onPublisherTakeSnapshotResult(errorCode: Int, image: Bitmap?) {
    //保存图片到本地
    }
})
 
// 拉流画面截图
engine.takePlayStreamSnapshot(streamID, object : IZegoPlayerTakeSnapshotCallback {
    override fun onPlayerTakeSnapshotResult(errorCode: Int, image: Bitmap?) {
    //保存图片到本地
    }
})

对于用户端来讲,截对方视频流,即通过拉流画面截图API截取即可,完了之后保存图片到本地,这里需要注意图片的存储位置,Android对于不同系统版本,在存储这部分有变更,更多参考官方文档 (opens in a new tab)

4.3 发送消息

前端通过网易IM SDK结合上一步截取的图片构建图片消息,并设置反垃圾扩展字段和扩展参数:

// 创建一个图片消息
val imageMessage = MessageBuilder.createImageMessage(account, SessionTypeEnum.P2P, file, fileName)
 
// 构造反垃圾对象
val antiSpamOption = NIMAntiSpamOption()
antiSpamOption.enable = true
imageMessage.setNIMAntiSpamOption(antiSpamOption)
// extStr1为用户ID,extStr2为主播ID
val spamExt = "{"roomId": "sadkssjajdsla", "extStr1": "20001001", "extStr2": "20001002"}"
imageMessage.setYidunAntiSpamExt(spamExt)
 
// 发送给对方
NIMClient.getService(MsgService::class.java).sendMessage(imageMessage, false)

4.4 结果处理

对于普通视频通话,鉴黄结果不做处理,但是匹配视频通话,在公共房间如果图片不合规,需要挂断当前通话,挂断原因需要传指定的涉黄原因(10),进入私密通话后,则同普通视频通话,鉴黄结果不做任何处理

// Activity.onCreate
NIMClient.getService(MsgServiceObserve::class.java)
            .observeMsgStatus(messageStatusMsgObserver, true)
  
// Activity.onDestory
NIMClient.getService(MsgServiceObserve::class.java)
            .observeMsgStatus(MsgEventCenter.messageStatusMsgObserver, false)
  
val messageStatusMsgObserver = Observer { message: IMMessage ->
        if (message.msgType == MsgTypeEnum.image) {
            // 自行解析message是否有yidunAntiSpamRes字段
        }
    } as Observer<IMMessage>

只有被安全通拦截的消息才会有yidunAntiSpamRes返回。对于疑似消息根据云信控制台设置的策略来判断,如果疑似消息被拦截会有yidunAntiSpamRes返回,如果疑似消息放行则没有yidunAntiSpamRes返回。

返回的审核结果 yidunAntiSpamRes 为 JSON 字符串格式,请自行解析或者反转成 JSON 对象使用。yidunAntiSpamRes 字段定义如下:

名称类型说明
codeInteger状态码:200:易盾内容审核结果返回正常404:易盾反回的内容审核结果为空,该情况下 yidunAntiSpamRes 中无 code 以外的字段414:易盾返回的内容审核结果过长,该情况下 yidunAntiSpamRes 中无 ext 字段
typeString内容审核类型text:文本image:图片
versionString易盾内容审核的接口版本
taskIdString审核任务的 ID
suggestionInteger建议处理方式0:通过1:嫌疑,建议人工复审2:不通过
statusInteger内容审核请求结果2:检测成功3:检测失败只有图片审核(type="image")时才返回该字段。
extString内容审核结果,对应易盾的 result 字段,result 字段详情参见易盾文档 (opens in a new tab)(注:本链接仅以“单次同步文本检测的 result 字段说明”为例

4.5 收尾阶段

  1. 对于审核结果正常的图片,除了删除本地临时生成的截图图片以外,还需要撤回发送给指定系统账号(10000)的消息,这样做也是为了防止发送的图片过多占用网易远程存储空间,因为超过套餐外的空间需要附加收费
NIMClient.getService(MsgService::class.java).revokeMessage(imageMessage)
  1. 最近会话列表过滤掉与指定系统账号(10000)的会话消息入口

5. 常见问题

  1. 问题:多次执行代码,截图频率发生变化
  • 原因:可能是每次执行完定时任务,相关资源没有释放。
  • 解决方案:检查定时任务逻辑。
  1. 问题:会话列表/陌生人列表展示出来了指定系统账号(10000)的会话入口
  • 原因:会话列表没有过滤系统账号的会话入口。
  • 解决方案:获取会话列表后去除掉指定系统账号(10000)。

6. 参考引用