L'interactivité et l'imprévisibilité des plateformes de contenu généré par les utilisateurs (UGC) de diffusion en direct expliquent en grande partie pourquoi elles sont si populaires. Mais cette imprévisibilité signifie que les communautés doivent faire preuve de diligence dans la surveillance de leur contenu pour s'assurer qu'il respecte leurs directives communautaires ou leur politique d'utilisation acceptable et qu'il est approprié, sûr et accueillant pour tous les utilisateurs. Cela se traduit souvent par un système de modération dans lequel les utilisateurs signalent les infractions potentielles aux directives de la communauté et les modérateurs ou administrateurs prennent les mesures nécessaires. Il s'agit souvent d'un processus manuel qui laisse beaucoup à désirer.
Les outils d'intelligence artificielle (IA) et d'apprentissage automatique (ML) se sont améliorés ces dernières années, et les développeurs peuvent utiliser ces outils pour aider à modérer leurs communautés. Dans cet article, nous examinerons une manière de procéder avec Amazon Interactive Video Service (Amazon IVS) et Amazon Rekognition.
Analyser chaque image de chaque flux en direct dans une application avec AI/ML serait une tâche très coûteuse et difficile. Au lieu de cela, les développeurs peuvent analyser des échantillons des flux en direct dans leurs applications à une fréquence spécifiée pour aider leurs modérateurs en les alertant s'il y a du contenu nécessitant un examen plus approfondi par un modérateur humain. Ce n'est pas une solution parfaite à 100 %, mais c'est un moyen d'automatiser la modération de contenu et de faciliter le travail des modérateurs.
Cette solution implique les étapes suivantes :
Nous utiliserons AWS Serverless Application Model (SAM) pour faciliter la création de la règle et des fonctions. Voici l'intégralité du fichier template.yaml
qui décrit les autorisations nécessaires, la règle Amazon EventBridge, la couche AWS Lambda (pour la dépendance AWS SDK) et les définitions de fonction. Nous allons détailler cela ci-dessous.
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/"
Il se passe beaucoup de choses dans ce dossier, alors décomposons-le un peu. Tout d'abord, nous créons une couche pour permettre l'inclusion du kit AWS SDK pour JavaScript (v3) dans notre fonction.
IvsChatLambdaRefLayer: Type: AWS::Serverless::LayerVersion Properties: LayerName: sam-app-dependencies Description: Dependencies for sam app ContentUri: dependencies/ CompatibleRuntimes: - nodejs18.x LicenseInfo: "MIT" RetentionPolicy: Retain
Dans le répertoire dependencies/nodejs
, il y a un fichier package.json
qui inclut les modules dont notre fonction a besoin.
{ "dependencies": { "@aws-sdk/client-ivs": "^3.289.0", "@aws-sdk/client-ivschat": "^3.289.0", "@aws-sdk/client-rekognition": "^3.289.0" } }
La section suivante, identifiée par les clés IVSAccessPolicy
et APIAccessPolicy
donne à notre application sans serveur la possibilité d'accéder aux API nécessaires ( s3:GetObject
, s3:GetObjectAcl
, ivschat:SendEvent
, ivs:StopStream
et rekognition:DetectModerationLabels
) et d'exposer la méthode stop stream que nous allons créer ci-dessous via Amazon API Gateway.
Ensuite, nous créons la règle Amazon EventBridge. La propriété name
sous bucket
doit correspondre au nom du compartiment Amazon S3 que vous avez configuré dans votre configuration d'enregistrement. L'enregistrement sur Amazon S3 crée divers fichiers, y compris des listes de lecture et des médias HLS, nous pouvons donc filtrer cette règle pour qu'elle ne se déclenche que pour nos vignettes en définissant la key
sous object
sur le 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
Ensuite, nous donnons à la règle les autorisations nécessaires pour appeler la fonction AWS Lambda.
PermissionForEventsToInvokeLambda: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref ModerateImage Action: lambda:InvokeFunction Principal: events.amazonaws.com SourceArn: !GetAtt EventRule.Arn
Nous pouvons maintenant définir notre fonction qui sera invoquée par la règle 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/
Remarque : je déclare DEMO_CHAT_ARN
et DEMO_CHANNEL_ARN
en tant que variables d'environnement, mais votre application dériverait probablement les valeurs ARN de l'événement transmis à la fonction, car vous utiliseriez probablement cette fonctionnalité avec plusieurs canaux Amazon IVS.
Enfin, nous pouvons définir la fonction qui sera utilisée pour arrêter un flux, si nécessaire.
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
Maintenant que nous avons décrit notre infrastructure avec AWS SAM, créons les fonctions que nous avons décrites. Dans index.mjs
, nous import
les classes SDK, récupérons les valeurs Arn des variables d'environnement que nous avons transmises et créons des instances des clients nécessaires à nos fonctions.
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();
La fonction moderateImage
recevra l'événement Amazon EventBridge, extraira le bucket
et key
de l'événement, et enverra une DetectModerationLabelsCommand
via le rekognitionClient
pour détecter tout contenu inapproprié ou offensant dans les images en fonction des catégories.
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); } };
Si nécessaire, la fonction moderateImage
appelle sendEvent
pour publier un événement personnalisé sur n'importe quel client frontal connecté à une salle de discussion Amazon IVS donnée.
const sendEvent = async (eventName, eventDetails) => { const sendEventInput = { roomIdentifier: chatArn, attributes: { streamModerationEvent: JSON.stringify(eventDetails), }, eventName, }; const sendEventRequest = new SendEventCommand(sendEventInput); await ivsChatClient.send(sendEventRequest); };
Votre frontal peut décider comment gérer cet événement et la logique de publication de cet événement dépendra des besoins de votre entreprise. Peut-être préférez-vous déclencher une alarme personnalisée dans CloudWatch, envoyer un e-mail ou publier une notification via Amazon SNS ? Les besoins de chaque application diffèrent, mais les données de modération sont disponibles à ce stade pour en faire ce dont vous avez besoin.
La méthode stopStream
utilise ivsClient
pour envoyer un StopStreamCommand
. Encore une fois, la mise en œuvre de cela dépend de vous. Vous pouvez même potentiellement automatiser entièrement cette commande si le résultat d'Amazon Rekognition correspond à une certaine catégorie ou dépasse un niveau de confiance.
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; };
Dans ma démo, j'ai décidé d'écouter les événements personnalisés et d'afficher les résultats dans une vue de modérateur qui montre l'élément détecté et le niveau de confiance. Je présente également au modérateur un bouton "Stop Stream" qui invoque la méthode stopStream
via la passerelle d'API Amazon exposée.
Dans cet article, nous avons appris à utiliser Amazon Rekognition pour aider les modérateurs humains à modérer le contenu des applications qu'ils créent à l'aide d'Amazon IVS. Si vous souhaitez en savoir plus sur la façon dont Amazon IVS peut aider à créer des communautés UGC plus sûres, consultez les articles de blog suivants :