用AI/ML内容管理创建更安全的网络社区

151 阅读8分钟

直播用户生成内容(UGC)平台的互动性和不可预测性是它们如此受欢迎的一个重要原因。但是,这种不可预测性意味着社区必须勤奋地监控他们的内容,以确保它符合他们的社区准则或可接受的使用政策,并对所有用户是适当的、安全的和受欢迎的。这通常会导致一个审核系统,用户报告潜在的违反社区准则的行为,而版主或管理员会根据需要采取行动。这通常是一个人工过程,有很多需要改进的地方。近年来,人工智能(AI)和机器学习(ML)工具已经得到了改善,开发者可以使用这些工具来帮助他们的社区进行管理。在这篇文章中,我们将看看用亚马逊互动视频服务(Amazon IVS)和亚马逊Rekognition的一种方法。

解决方案概述

用AI/ML分析应用程序中的每一帧直播流将是一项非常昂贵和困难的任务。相反,开发者可以按指定的频率分析其应用程序中的直播流样本,以协助其主持人,提醒他们是否有需要由人类主持人进一步审查的内容。这不是一个100%完美的解决方案,但它是自动化内容审核的一种方式,有助于使版主的工作更容易。

这个解决方案包括以下步骤:

  • 在你的亚马逊IVS频道上配置自动记录直播流到亚马逊简单存储服务(Amazon S3),在指定频率上保存缩略图
  • 创建一个亚马逊EventBridge规则,当亚马逊S3桶中创建一个新对象时,该规则就会启动
  • 创建一个AWS Lambda函数,由EventBridge规则触发,并使用Amazon Rekognition检测裸体、暴力或赌博等可能需要人工审核的内容。
  • 创建一个AWS Lambda函数,并通过亚马逊API网关将其公开,以便在必要时提供停止直播流的方法
  • 亚马逊IVS聊天室发送一个自定义事件,其中包含分析的结果

创建Amazon EventBridge规则和AWS Lambda函数

我们将使用AWS无服务器应用程序模型(SAM),以方便创建规则和函数。下面是整个template.yaml 文件,其中描述了必要的权限、Amazon EventBridge规则和AWS Lambda层(用于AWS SDK依赖)以及函数定义。下面我们将对此进行分解。

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Amazon IVS Moderation Functions
Globals:
  Function:
    Runtime: nodejs18.x
    Timeout: 30
    MemorySize: 128
  Api:
    EndpointConfiguration: 
      Type: REGIONAL
    Cors:
      AllowMethods: "'GET, POST, OPTIONS'"
      AllowHeaders: "'Content-Type'"
      AllowOrigin: "'*'"
      MaxAge: "'600'"
Resources:
  IvsChatLambdaRefLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: sam-app-dependencies
      Description: Dependencies for sam app
      ContentUri: dependencies/
      CompatibleRuntimes:
        - nodejs18.x
      LicenseInfo: "MIT"
      RetentionPolicy: Retain
  IVSAccessPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: IVSModerationAccessPolicy
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 's3:GetObject'
              - 's3:GetObjectAcl'
              - 'ivschat:SendEvent'
              - 'ivs:StopStream'
              - 'rekognition:DetectModerationLabels'
            Resource: '*'
      Roles:
        - Ref: ModerateImageRole
        - Ref: StopStreamRole
  ApiAccessPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: ApiAccessPolicy
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 'sts:AssumeRole'
            Resource: '*'
      Roles:
        - Ref: ModerateImageRole
        - Ref: StopStreamRole
  EventRule:
    Type: AWS::Events::Rule
    Properties:
      Description: EventRule
      State: ENABLED
      EventPattern: 
        source:
          - aws.s3
        detail-type:
          - "Object Created"
        detail:
          bucket:
            name:
              - ivs-demo-channel-stream-archive
          object:
            key:
              - suffix: .jpg
      Targets:
        - Arn: !GetAtt ModerateImage.Arn
          Id: MyLambdaFunctionTarget
  PermissionForEventsToInvokeLambda:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref ModerateImage
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt EventRule.Arn
  ModerateImage:
    Type: 'AWS::Serverless::Function'
    Properties:
      Environment:
        Variables:
          DEMO_CHAT_ARN: 'arn:aws:ivschat:us-east-1:[redacted]:room/[redacted]'
          DEMO_CHANNEL_ARN: 'arn:aws:ivs:us-east-1:[redacted]:channel/[redacted]'
      Handler: index.moderateImage
      Layers:
        - !Ref IvsChatLambdaRefLayer
      CodeUri: lambda/
  StopStream:
    Type: 'AWS::Serverless::Function'
    Properties:
      Environment:
        Variables:
          DEMO_CHAT_ARN: 'arn:aws:ivschat:us-east-1:[redacted]:room/[redacted]'
          DEMO_CHANNEL_ARN: 'arn:aws:ivs:us-east-1:[redacted]:channel/[redacted]'
      Handler: index.stopStream
      Layers:
        - !Ref IvsChatLambdaRefLayer
      CodeUri: lambda/
      Events:
        Api1:
          Type: Api
          Properties:
            Path: /stop-stream
            Method: POST
Outputs:
  ApiURL:
    Description: "API endpoint URL for Prod environment"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

进入全屏模式 退出全屏模式

这个文件里有很多东西,所以让我们把它分解一下。首先,我们创建一个层,使AWS SDK for JavaScript(v3)包含在我们的函数中。

IvsChatLambdaRefLayer:
  Type: AWS::Serverless::LayerVersion
  Properties:
    LayerName: sam-app-dependencies
    Description: Dependencies for sam app
    ContentUri: dependencies/
    CompatibleRuntimes:
      - nodejs18.x
    LicenseInfo: "MIT"
    RetentionPolicy: Retain

进入全屏模式 退出全屏模式

dependencies/nodejs 目录中,有一个package.json 文件,其中包括我们函数所需要的模块。

{
  "dependencies": {
    "@aws-sdk/client-ivs": "^3.289.0",
    "@aws-sdk/client-ivschat": "^3.289.0",
    "@aws-sdk/client-rekognition": "^3.289.0"
  }
}

进入全屏模式 退出全屏模式

接下来的部分,由键IVSAccessPolicyAPIAccessPolicy 识别,使我们的无服务器应用程序能够访问必要的API(s3:GetObject,s3:GetObjectAcl,ivschat:SendEvent,ivs:StopStream, 和rekognition:DetectModerationLabels ),并通过Amazon API Gateway暴露我们将在下面创建的停止流方法。

接下来,我们创建Amazon EventBridge规则。bucket 下的name 属性应该与你在录音配置中配置的Amazon S3桶的名称相匹配。录制到Amazon S3会创建各种文件,包括播放列表和HLS媒体,所以我们可以通过将object 下的key 设置为suffix: jpg 来过滤这个规则,只对我们的缩略图开火。

EventRule:
  Type: AWS::Events::Rule
  Properties:
    Description: EventRule
    State: ENABLED
    EventPattern: 
      source:
        - aws.s3
      detail-type:
        - "Object Created"
      detail:
        bucket:
          name:
            - ivs-demo-channel-stream-archive
        object:
          key:
            - suffix: .jpg
    Targets:
      - Arn: !GetAtt ModerateImage.Arn
        Id: MyLambdaFunctionTarget

进入全屏模式 退出全屏模式

接下来,我们给这个规则必要的权限来调用AWS Lambda函数。

PermissionForEventsToInvokeLambda:
  Type: AWS::Lambda::Permission
  Properties:
    FunctionName: !Ref ModerateImage
    Action: lambda:InvokeFunction
    Principal: events.amazonaws.com
    SourceArn: !GetAtt EventRule.Arn

进入全屏模式 退出全屏模式

现在我们可以定义我们的函数,它将被Amazon EventBridge规则所调用。

ModerateImage:
  Type: 'AWS::Serverless::Function'
  Properties:
    Environment:
      Variables:
        DEMO_CHAT_ARN: 'arn:aws:ivschat:us-east-1:[redacted]:room/[redacted]'
        DEMO_CHANNEL_ARN: 'arn:aws:ivs:us-east-1:[redacted]:channel/[redacted]'
    Handler: index.moderateImage
    Layers:
      - !Ref IvsChatLambdaRefLayer
    CodeUri: lambda/

进入全屏模式 退出全屏模式

**注意:**我把DEMO_CHAT_ARNDEMO_CHANNEL_ARN 声明为环境变量,但你的应用程序可能会从传入函数的事件中获得ARN值,因为你可能不止在一个亚马逊IVS通道上使用这个功能。

最后,我们可以定义用于停止流的函数,如果需要的话。

StopStream:
  Type: 'AWS::Serverless::Function'
  Properties:
    Environment:
      Variables:
        DEMO_CHAT_ARN: 'arn:aws:ivschat:us-east-1:[redacted]:room/[redacted]'
        DEMO_CHANNEL_ARN: 'arn:aws:ivs:us-east-1:[redacted]:channel/[redacted]'
    Handler: index.stopStream
    Layers:
      - !Ref IvsChatLambdaRefLayer
    CodeUri: lambda/
    Events:
      Api1:
        Type: Api
        Properties:
          Path: /stop-stream
          Method: POST

进入全屏模式 退出全屏模式

创建AWS Lambda函数

现在我们已经用AWS SAM描述了我们的基础设施,让我们来创建我们描述的函数。在index.mjs ,我们import SDK类,从我们传入的环境变量中获取Arn值,并为我们的函数创建所需的客户端实例。

import { IvsClient, StopStreamCommand } from "@aws-sdk/client-ivs";
import { IvschatClient, SendEventCommand } from "@aws-sdk/client-ivschat";
import { RekognitionClient, DetectModerationLabelsCommand } from "@aws-sdk/client-rekognition";

const chatArn = process.env.DEMO_CHAT_ARN;
const channelArn = process.env.DEMO_CHANNEL_ARN;

const ivsClient = new IvsClient();
const ivsChatClient = new IvschatClient();
const rekognitionClient = new RekognitionClient();

进入全屏模式 退出全屏模式

moderateImage 函数将接收Amazon EventBridge事件,从事件中提取bucketkey ,并通过rekognitionClient 发送一个DetectModerationLabelsCommand ,根据这里列出的类别检测图片中是否有不恰当或令人反感的内容。

export const moderateImage = async (event) => {
  console.log('moderateImage:', JSON.stringify(event, null, 2));
  const bucket = event.detail.bucket.name;
  const key = event.detail.object.key;

  const detectLabelsCommandInput = {
    Image: {
      S3Object: {
        Bucket: bucket,
        Name: key,
      }
    },
  };
  const detectLabelsRequest = new DetectModerationLabelsCommand(detectLabelsCommandInput);
  const detectLabelsResponse = await rekognitionClient.send(detectLabelsRequest);

  if (detectLabelsResponse.ModerationLabels) {
    sendEvent('STREAM_MODERATION', detectLabelsResponse.ModerationLabels);
  }
};

进入全屏模式 退出全屏模式

如果有必要,moderateImage 函数会调用sendEvent ,将一个自定义事件发布给任何连接到给定亚马逊IVS聊天室的前端客户。

const sendEvent = async (eventName, eventDetails) => {
  const sendEventInput = {
    roomIdentifier: chatArn,
    attributes: {
      streamModerationEvent: JSON.stringify(eventDetails),
    },
    eventName,
  };
  const sendEventRequest = new SendEventCommand(sendEventInput);
  await ivsChatClient.send(sendEventRequest);
};

进入全屏模式 退出全屏模式

你的前端可以决定如何处理这个事件,发布这个事件的逻辑取决于你的业务需求。也许你更愿意在CloudWatch中触发一个自定义的警报,发送一封电子邮件,或者通过Amazon SNS发布一个通知?每个应用程序的需求都不同,但此时的节制数据是可以用它来做你需要的事情。

stopStream 方法使用ivsClient 来发送一个StopStreamCommand 。同样,这个的实现由你决定。如果Amazon Rekognition的结果与某个类别相匹配或超过某个置信度,你甚至可以潜在地完全自动执行这个命令。

export const stopStream = async (event) => {
  console.log('stopStream:', JSON.stringify(event, null, 2));
  try {
    const stopStreamRequest = new StopStreamCommand({ channelArn });
    const stopStreamResponse = await ivsClient.send(stopStreamRequest);
    responseObject.body = JSON.stringify(stopStreamResponse);
  }
  catch (err) {
    responseObject.statusCode = err?.name === 'ChannelNotBroadcasting' ? 404 : 500;
    responseObject.body = JSON.stringify(err);
  }
  return responseObject;
};

进入全屏模式 退出全屏模式

演示

在我的演示中,我决定监听自定义事件,并将结果显示在主持人的视图中,显示检测到的项目和信心水平。我还为主持人提供了一个 "停止流 "按钮,通过暴露的亚马逊API网关调用stopStream 方法。

content moderation demo

总结

在这篇文章中,我们学习了如何使用Amazon Rekognition来协助人类版主对他们使用Amazon IVS构建的应用程序中的内容进行审核。如果你想了解更多关于亚马逊IVS如何帮助创建更安全的UGC社区,请查看以下博文: