Análisis de contenido de vídeo para detectar material inapropiado en C#

En este artículo se proporcionan información y ejemplos de código que le ayudarán a empezar a usar el SDK de Content Moderator para .NET para examinar contenido de vídeo a fin de detectar contenido para adultos o atrevido.

Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar.

Prerrequisitos

Configuración de los recursos de Azure

La funcionalidad de moderación de vídeo de Content Moderator está disponible de forma gratuita como un procesador de multimedia (en versión preliminar pública) para Azure Media Services (AMS). Azure Media Services es un servicio de Azure especializado para almacenar y transmitir contenido de vídeo.

Creación de una cuenta de Azure Media Services

Para suscribirse a ASM y crear una cuenta de almacenamiento de Azure asociada, siga las instrucciones que se indican en Creación de una cuenta de Azure Media Services. En esa cuenta de almacenamiento, cree un contenedor de almacenamiento de blobs.

Creación de una aplicación de Microsoft Entra

Vaya a la nueva suscripción de AMS en Azure Portal y seleccione Acceso de API en el menú lateral. Seleccione Connect to Azure Media Services with service principal (Conectarse a Azure Media Services con la entidad de servicio). Anote el valor del campo Punto de conexión de la API de REST; la necesitará más adelante.

En la sección Aplicación de Microsoft Entra, seleccione Crear nueva y asigne un nombre al nuevo registro de aplicación de Microsoft Entra, por ejemplo "VideoModADApp". Seleccione Guardar y espere unos minutos a que se configure la aplicación. A continuación, verá el nuevo registro de aplicación en la sección Aplicación de Microsoft Entra de la página.

Seleccione el registro de aplicación y haga clic en el botón Administrar aplicación que hay debajo. Anote el valor del campo Id. de aplicación; lo necesitará más adelante. Seleccione Configuración>Claves y escriba una descripción para una nueva clave (por ejemplo, "VideoModKey"). Seleccione Guardar y, luego, observe el nuevo valor de clave. Copie esta cadena y guárdela en un lugar seguro.

Si desea un tutorial más detallado del proceso anterior, consulte Introducción a la autenticación de Microsoft Entra.

Una vez hecho esto, puede usar el procesador de multimedia de moderación de vídeo de dos maneras diferentes.

Usar el explorador de Azure Media Services

Azure Media Services Explorer es un front-end fácil de usar de AMS. Úselo para examinar la cuenta de AMS, cargar vídeos y analizar el contenido con el procesador de multimedia de Content Moderator. Descárguelo e instálelo desde GitHub, o consulte la entrada de blog de Azure Media Services Explorer para más información.

Azure Media Services explorer with Content Moderator

Creación del proyecto de Visual Studio

  1. En Visual Studio, cree un proyecto de Aplicación de consola (.NET Framework) y asígnele el nombre VideoModeration.
  2. Si hay otros proyectos en la solución, seleccione este como proyecto de inicio único.
  3. Obtenga los paquetes NuGet requeridos. Haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione Administrar paquetes NuGet; a continuación, busque e instale los siguientes paquetes:
    • windowsazure.mediaservices
    • windowsazure.mediaservices.extensions

Incorporación del código de moderación de vídeo

A continuación, copiará y pegará el código de esta guía en el proyecto para implementar un escenario básico de moderación de contenido.

Actualizar las instrucciones using del programa

Agregue las siguientes instrucciones using al principio del archivo Program.cs.

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MediaServices.Client;
using System.IO;
using System.Threading;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using System.Collections.Generic;

Configuración de las referencias de recursos

Agregue los siguientes campos estáticos a la clase Program en Program.cs. Estos campos contienen la información necesaria para conectarse a su suscripción de AMS. Rellénelos con los valores que obtuvo en los pasos anteriores. Tenga en cuenta que CLIENT_ID es el valor de Id. de aplicación de la aplicación de Microsoft Entra, y que CLIENT_SECRET es el valor de "VideoModKey" que ha creado para esa aplicación.

// declare constants and globals
private static CloudMediaContext _context = null;
private static CloudStorageAccount _StorageAccount = null;

// Azure Media Services (AMS) associated Storage Account, Key, and the Container that has
// a list of Blobs to be processed.
static string STORAGE_NAME = "YOUR AMS ASSOCIATED BLOB STORAGE NAME";
static string STORAGE_KEY = "YOUR AMS ASSOCIATED BLOB STORAGE KEY";
static string STORAGE_CONTAINER_NAME = "YOUR BLOB CONTAINER FOR VIDEO FILES";

private static StorageCredentials _StorageCredentials = null;

// Azure Media Services authentication.
private const string AZURE_AD_TENANT_NAME = "microsoft.onmicrosoft.com";
private const string CLIENT_ID = "YOUR CLIENT ID";
private const string CLIENT_SECRET = "YOUR CLIENT SECRET";

// REST API endpoint, for example "https://accountname.restv2.westcentralus.media.azure.net/API".
private const string REST_API_ENDPOINT = "YOUR API ENDPOINT";

// Content Moderator Media Processor Nam
private const string MEDIA_PROCESSOR = "Azure Media Content Moderator";

// Input and Output files in the current directory of the executable
private const string INPUT_FILE = "VIDEO FILE NAME";
private const string OUTPUT_FOLDER = "";

// JSON settings file
private static readonly string CONTENT_MODERATOR_PRESET_FILE = "preset.json";

Importante

Recuerde quitar las claves del código cuando termine, y nunca las haga públicas. En el caso de producción, use una forma segura de almacenar sus credenciales y acceder a ellas, como Azure Key Vault. Consulte el artículo Seguridad de servicios de Azure AI para más información.

Si quiere usar un archivo de vídeo local (caso más sencillo), agréguelo al proyecto y escriba su ruta de acceso como el valor INPUT_FILE (las rutas de acceso relativas son relativas al directorio de ejecución).

También deberá crear el archivo preset.json en el directorio actual y usarlo para especificar un número de versión. Por ejemplo:

{
    "version": "2.0"
}

Carga del vídeo de entrada

El método Main de la clase Program crea un contexto multimedia de Azure y luego un contexto de almacenamiento de Azure (en caso de que los vídeos estén en Blob Storage). El código restante examina un vídeo de una carpeta local, blob o varios blobs dentro de un contenedor de almacenamiento de Azure. Puede probar todas las opciones si decide comentar las otras líneas de código.

// Create Azure Media Context
CreateMediaContext();

// Create Storage Context
CreateStorageContext();

// Use a file as the input.
IAsset asset = CreateAssetfromFile();

// -- OR ---

// Or a blob as the input
// IAsset asset = CreateAssetfromBlob((CloudBlockBlob)GetBlobsList().First());

// Then submit the asset to Content Moderator
RunContentModeratorJob(asset);

//-- OR ----

// Just run the content moderator on all blobs in a list (from a Blob Container)
// RunContentModeratorJobOnBlobs();

Creación de un contexto multimedia de Azure

Agregue el método siguiente a la clase Program. Se usarán sus credenciales de AMS para permitir la comunicación con AMS.

// Creates a media context from azure credentials
static void CreateMediaContext()
{
    // Get Azure AD credentials
    var tokenCredentials = new AzureAdTokenCredentials(AZURE_AD_TENANT_NAME,
        new AzureAdClientSymmetricKey(CLIENT_ID, CLIENT_SECRET),
        AzureEnvironments.AzureCloudEnvironment);

    // Initialize an Azure AD token
    var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

    // Create a media context
    _context = new CloudMediaContext(new Uri(REST_API_ENDPOINT), tokenProvider);
}

Agregar el código para crear un contexto de Azure Storage

Agregue el método siguiente a la clase Program. Usará el contexto de almacenamiento, creado con las credenciales de almacenamiento, para acceder al almacenamiento de blobs.

// Creates a storage context from the AMS associated storage name and key
static void CreateStorageContext()
{
    // Get a reference to the storage account associated with a Media Services account.
    if (_StorageCredentials == null)
    {
        _StorageCredentials = new StorageCredentials(STORAGE_NAME, STORAGE_KEY);
    }
    _StorageAccount = new CloudStorageAccount(_StorageCredentials, false);
}

Agregar el código para crear recursos de Azure Media a partir de un archivo local y un blob

El procesador de multimedia de Content Moderator ejecuta trabajos en la opción Recursos de la plataforma Azure Media Services. Estos métodos crean los recursos de un archivo local o un blob asociado.

// Creates an Azure Media Services Asset from the video file
static IAsset CreateAssetfromFile()
{
    return _context.Assets.CreateFromFile(INPUT_FILE, AssetCreationOptions.None); ;
}

// Creates an Azure Media Services asset from your blog storage
static IAsset CreateAssetfromBlob(CloudBlockBlob Blob)
{
    // Create asset from the FIRST blob in the list and return it
    return _context.Assets.CreateFromBlob(Blob, _StorageCredentials, AssetCreationOptions.None);
}

Agregar el código para examinar una colección de vídeos (como blobs) en un contenedor

// Runs the Content Moderator Job on all Blobs in a given container name
static void RunContentModeratorJobOnBlobs()
{
    // Get the reference to the list of Blobs. See the following method.
    var blobList = GetBlobsList();

    // Iterate over the Blob list items or work on specific ones as needed
    foreach (var sourceBlob in blobList)
    {
        // Create an Asset
        IAsset asset = _context.Assets.CreateFromBlob((CloudBlockBlob)sourceBlob,
                            _StorageCredentials, AssetCreationOptions.None);
        asset.Update();

        // Submit to Content Moderator
        RunContentModeratorJob(asset);
    }
}

// Get all blobs in your container
static IEnumerable<IListBlobItem> GetBlobsList()
{
    // Get a reference to the Container within the Storage Account
    // that has the files (blobs) for moderation
    CloudBlobClient CloudBlobClient = _StorageAccount.CreateCloudBlobClient();
    CloudBlobContainer MediaBlobContainer = CloudBlobClient.GetContainerReference(STORAGE_CONTAINER_NAME);

    // Get the reference to the list of Blobs
    var blobList = MediaBlobContainer.ListBlobs();
    return blobList;
}

Agregar el método para ejecutar el trabajo de Content Moderator

// Run the Content Moderator job on the designated Asset from local file or blob storage
static void RunContentModeratorJob(IAsset asset)
{
    // Grab the presets
    string configuration = File.ReadAllText(CONTENT_MODERATOR_PRESET_FILE);

    // grab instance of Azure Media Content Moderator MP
    IMediaProcessor mp = _context.MediaProcessors.GetLatestMediaProcessorByName(MEDIA_PROCESSOR);

    // create Job with Content Moderator task
    IJob job = _context.Jobs.Create(String.Format("Content Moderator {0}",
            asset.AssetFiles.First() + "_" + Guid.NewGuid()));

    ITask contentModeratorTask = job.Tasks.AddNew("Adult and racy classifier task",
            mp, configuration,
            TaskOptions.None);
    contentModeratorTask.InputAssets.Add(asset);
    contentModeratorTask.OutputAssets.AddNew("Adult and racy classifier output",
        AssetCreationOptions.None);

    job.Submit();


    // Create progress printing and querying tasks
    Task progressPrintTask = new Task(() =>
    {
        IJob jobQuery = null;
        do
        {
            var progressContext = _context;
            jobQuery = progressContext.Jobs
            .Where(j => j.Id == job.Id)
                .First();
                Console.WriteLine(string.Format("{0}\t{1}",
                DateTime.Now,
                jobQuery.State));
                Thread.Sleep(10000);
            }
            while (jobQuery.State != JobState.Finished &&
            jobQuery.State != JobState.Error &&
            jobQuery.State != JobState.Canceled);
    });
    progressPrintTask.Start();

    Task progressJobTask = job.GetExecutionProgressTask(
    CancellationToken.None);
    progressJobTask.Wait();

    // If job state is Error, the event handling
    // method for job progress should log errors.  Here we check
    // for error state and exit if needed.
    if (job.State == JobState.Error)
    {
        ErrorDetail error = job.Tasks.First().ErrorDetails.First();
        Console.WriteLine(string.Format("Error: {0}. {1}",
        error.Code,
        error.Message));
    }

    DownloadAsset(job.OutputMediaAssets.First(), OUTPUT_FOLDER);
}

Incorporación de funciones auxiliares

Estos métodos descargan el archivo de salida (JSON) de Content Moderator del recurso de Azure Media Services, y le permiten hacer un seguimiento del estado del trabajo de moderación para que el programa pueda registrar el estado de ejecución en la consola.

static void DownloadAsset(IAsset asset, string outputDirectory)
{
    foreach (IAssetFile file in asset.AssetFiles)
    {
        file.Download(Path.Combine(outputDirectory, file.Name));
    }
}

// event handler for Job State
static void StateChanged(object sender, JobStateChangedEventArgs e)
{
    Console.WriteLine("Job state changed event:");
    Console.WriteLine("  Previous state: " + e.PreviousState);
    Console.WriteLine("  Current state: " + e.CurrentState);
    switch (e.CurrentState)
    {
        case JobState.Finished:
            Console.WriteLine();
            Console.WriteLine("Job finished.");
            break;
        case JobState.Canceling:
        case JobState.Queued:
        case JobState.Scheduled:
        case JobState.Processing:
            Console.WriteLine("Please wait...\n");
            break;
        case JobState.Canceled:
            Console.WriteLine("Job is canceled.\n");
            break;
        case JobState.Error:
            Console.WriteLine("Job failed.\n");
            break;
        default:
            break;
    }
}

Ejecutar el programa y revisar la salida

Una vez completado el trabajo de moderación de contenido, analice la respuesta JSON. Esta consta de estos elementos:

  • Resumen de información del vídeo
  • Capturas denominadas "fragmentos".
  • Fotogramas clave denominados " eventos " con una marca reviewRecommended" (= true o false)" basada en puntuaciones de tipo Adultos e Inapropiado.
  • Los valores start, duration , totalDuration y timestamp están entrecomillados. Divida con el valor timescale para obtener el número en segundos.

Nota

  • adultScore representa la posible presencia y la puntuación de predicción de contenido que se pueda considerar sexualmente explícito o para adultos en ciertas situaciones.
  • racyScore representa la posible presencia y la puntuación de predicción de contenido que se pueda considerar sexualmente insinuante o para adultos en ciertas situaciones.
  • adultScore y racyScore están entre 0 y 1. Cuanto más alta sea la puntuación, mayor será la predicción del modelo sobre la aplicabilidad de la categoría. Esta versión preliminar usa un modelo estadístico, en lugar de resultados codificados manualmente. Se recomienda realizar pruebas con contenido propio para determinar cómo se alinea cada categoría en función de sus propios requisitos.
  • reviewRecommended es true o false según los umbrales de puntuación internos. Los clientes deben evaluar si quieren usar este valor o decidir si desean umbrales personalizados basados en sus directivas de contenido.
{
"version": 2,
"timescale": 90000,
"offset": 0,
"framerate": 50,
"width": 1280,
"height": 720,
"totalDuration": 18696321,
"fragments": [
{
    "start": 0,
    "duration": 18000
},
{
    "start": 18000,
    "duration": 3600,
    "interval": 3600,
    "events": [
    [
        {
        "reviewRecommended": false,
        "adultScore": 0.00001,
        "racyScore": 0.03077,
        "index": 5,
        "timestamp": 18000,
        "shotIndex": 0
        }
    ]
    ]
},
{
    "start": 18386372,
    "duration": 119149,
    "interval": 119149,
    "events": [
    [
        {
        "reviewRecommended": true,
        "adultScore": 0.00000,
        "racyScore": 0.91902,
        "index": 5085,
        "timestamp": 18386372,
        "shotIndex": 62
        }
    ]
    ]
}
]
}

Pasos siguientes

Descargue la solución de Visual Studio para este y otras guías de inicio rápido de Content Moderator para .NET.