您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

在 C# 中分析令人反感的视频内容Analyze video content for objectionable material in C#

本文中的信息和代码示例可帮助你快速开始使用适用于 .NET 的内容审查器 SDK 来扫描视频中的成人或猥亵内容。This article provides information and code samples to help you get started using the Content Moderator SDK for .NET to scan video content for adult or racy content.

如果没有 Azure 订阅,请在开始之前创建一个免费帐户If you don't have an Azure subscription, create a free account before you begin.

必备组件Prerequisites

设置 Azure 资源Set up Azure resources

内容审查器的视频审查功能可以在 Azure 媒体服务 (AMS) 中免费提供公共预览版的媒体处理器The Content Moderator's video moderation capability is available as a free public preview media processor in Azure Media Services (AMS). Azure 媒体服务是用于存储和流式传输视频内容的专业 Azure 服务。Azure Media Services is a specialized Azure service for storing and streaming video content.

创建 Azure 媒体服务帐户Create an Azure Media Services account

遵照创建 Azure 媒体服务帐户中的说明订阅 AMS,并创建关联的 Azure 存储帐户。Follow the instructions in Create an Azure Media Services account to subscribe to AMS and create an associated Azure storage account. 在该存储帐户中,创建新的 Blob 存储容器。In that storage account, create a new Blob storage container.

创建 Azure Active Directory 应用程序Create an Azure Active Directory application

在 Azure 门户中导航到新的 AMS 订阅,并从菜单中选择“API 访问”。Navigate to your new AMS subscription in the Azure portal and select API access from the side menu. 选择“通过服务主体连接到 Azure 媒体服务”。Select Connect to Azure Media Services with service principal. 记下“REST API 终结点”字段中的值,因为稍后需要用到。Note the value in the REST API endpoint field; you will need this later.

在“Azure AD 应用程序”部分,选择“新建”并为新的 Azure AD 应用程序注册命名(例如“VideoModADApp”)。In the Azure AD app section, select Create New and name your new Azure AD application registration (for example, "VideoModADApp"). 单击“保存”并等待几分钟时间,让应用程序配置完成。Click Save and wait a few minutes while the application is configured. 然后,页面的“Azure AD 应用”部分下应会显示新的应用注册。Then, you should see your new app registration under the Azure AD app section of the page.

选择该应用注册,并单击其下面的“管理应用程序”按钮。Select your app registration and click the Manage application button below it. 记下“应用程序 ID”字段中的值,因为稍后需要用到。Note the value in the Application ID field; you will need this later. 选择“设置” > “密钥”,并输入新密钥的说明(例如“VideoModKey”)。Select Settings > Keys, and enter a description for a new key (such as "VideoModKey"). 单击“保存”,然后注意新密钥值。Click Save, and then notice the new key value. 复制此字符串并将其保存到安全的位置。Copy this string and save it somewhere secure.

有关上述过程的全面演练,请参阅 Azure AD 身份验证入门For a more thorough walkthrough of the above process, See Get started with Azure AD authentication.

完成上述操作后,可通过两种不同的方式使用视频审查媒体处理器。Once you've done this, you can use the video moderation media processor in two different ways.

使用 Azure 媒体服务资源管理器Use Azure Media Services Explorer

Azure 媒体服务资源管理器是 AMS 的用户友好前端。The Azure Media Services Explorer is a user-friendly frontend for AMS. 使用它可以浏览 AMS 帐户、上传视频,以及通过内容审查器媒体处理器扫描内容。Use it to browse your AMS account, upload videos, and scan content with the Content Moderator media processor. GitHub 下载并安装此工具,或参阅 Azure 媒体服务资源管理器博客文章了解详细信息。Download and install it from GitHub, or see the Azure Media Services Explorer blog post for more information.

带有内容审查器的 Azure 媒体服务资源管理器

创建 Visual Studio 项目Create the Visual Studio project

  1. 在 Visual Studio 中创建新的控制台应用 (.NET Framework) 项目并将其命名为 VideoModerationIn Visual Studio, create a new Console app (.NET Framework) project and name it VideoModeration.
  2. 如果解决方案中有其他项目,请将此项目选为单一启动项目。If there are other projects in your solution, select this one as the single startup project.
  3. 获取所需的 NuGet 包。Get the required NuGet packages. 右键单击解决方案资源管理器中的项目,选择“管理 NuGet 包”,然后找到并安装以下包:Right-click on your project in the Solution Explorer and select Manage NuGet Packages; then find and install the following packages:
    • windowsazure.mediaserviceswindowsazure.mediaservices
    • windowsazure.mediaservices.extensionswindowsazure.mediaservices.extensions

添加视频审查代码Add video moderation code

接下来,将代码从本指南复制并粘贴到项目中,以便实施基本的内容审查方案。Next, you'll copy and paste the code from this guide into your project to implement a basic content moderation scenario.

更新程序的 using 语句Update the program's using statements

将以下 using 语句添加到 Program.cs 文件顶部。Add the following using statements to the top of your Program.cs file.

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;

设置资源引用Set up resource references

向 Program.cs 中的 Program 类添加以下静态字段。Add the following static fields to the Program class in Program.cs. 这些字段包含连接到 AMS 订阅所需的信息。These fields hold the information necessary for connecting to your AMS subscription. 请在这些字段内填充在上述步骤中获取的值。Fill them in with the values you got in the steps above. 请注意,CLIENT_ID 是 Azure AD 应用的“应用程序 ID”值,CLIENT_SECRET 是为该应用创建的“VideoModKey”的值。Note that CLIENT_ID is the Application ID value of your Azure AD app, and CLIENT_SECRET is the value of the "VideoModKey" that you created for that app.

// 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";

若要使用本地视频文件(最简单的情况),请将其添加到项目,并以 INPUT_FILE 值的形式输入其路径(相对路径相对于执行目录)。If you wish to use a local video file (simplest case), add it to the project and enter its path as the INPUT_FILE value (relative paths are relative to the execution directory).

还需要在当前目录中创建 preset.json 文件,并使用它来指定版本号。You will also need to create the preset.json file in the current directory and use it to specify a version number. 例如:For example:

{
    "version": "2.0"
}

加载输入视频Load the input video(s)

Program 类的 Main 方法依次创建 Azure 媒体上下文和 Azure 存储上下文(如果视频位于 Blob 存储中)。The Main method of the Program class will create an Azure Media Context and then an Azure Storage Context (in case your videos are in blob storage). 剩余代码会扫描本地文件夹、Azure 存储容器内的一个或多个 blob 中的视频。The remaining code scans a video from a local folder, blob, or multiple blobs within an Azure storage container. 你可以通过注释掉其他代码行来尝试所有选项。You can try all options by commenting out the other lines of code.

// 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();

创建 Azure 媒体上下文Create an Azure Media Context

将以下方法添加到 Program 类。Add the following method to the Program class. 这会使用你的 AMS 凭据来实现与 AMS 通信。This uses your AMS credentials to allow communication with 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);
}

添加代码以创建 Azure 存储上下文Add the code to create an Azure Storage Context

将以下方法添加到 Program 类。Add the following method to the Program class. 使用从存储凭据创建的存储上下文来访问 Blob 存储。You use the Storage Context, created from your storage credentials, to access your blob storage.

// 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);
}

添加代码以从本地文件和 blob 创建 Azure 媒体资产Add the code to create Azure Media Assets from local file and blob

内容审查器媒体处理器对 Azure 媒体服务平台内的“资产”上运行作业。The Content Moderator media processor runs jobs on Assets within the Azure Media Services platform. 这些方法会从本地文件或关联的 blob 创建资产。These methods create the Assets from a local file or an associated blob.

// 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);
}

添加代码以扫描容器内的视频集合(作为 blob)Add the code to scan a collection of videos (as blobs) within a container

// 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;
}

添加方法以运行内容审查器作业Add the method to run the Content Moderator Job

// 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);
}

添加帮助程序函数Add helper functions

这些方法会从 Azure 媒体服务资产中下载内容审查器输出文件 (JSON) 并帮助跟踪审查作业的状态,以便该程序可以将运行状态记录到控制台。These methods download the Content Moderator output file (JSON) from the Azure Media Services asset, and help track the status of the moderation job so that the program can log a running status to the console.

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;
    }
}

运行程序并检查输出Run the program and review the output

内容审查作业完成后,分析 JSON 响应。After the Content Moderation job is completed, analyze the JSON response. 它由以下元素组成:It consists of these elements:

  • 视频信息摘要Video information summary
  • 截图作为“片段”Shots as "fragments"
  • 基于“成人”和“不雅”分数,关键帧作为具有 reviewRecommended“(= true 或 false)”标志的“事件”Key frames as "events" with a reviewRecommended" (= true or false)" flag based on Adult and Racy scores
  • “开始时间”、“持续时间”、“总持续时间”和“时间戳”以“刻度”为单位。start, duration, totalDuration, and timestamp are in "ticks". 除以“时间刻度”以获得数字(以秒为单位)。Divide by timescale to get the number in seconds.

备注

  • adultScore 表示可能存在某些情况下可能被视为色情或成人性质的内容以及预测分数。adultScore represents the potential presence and prediction score of content that may be considered sexually explicit or adult in certain situations.
  • racyScore 表示可能存在某些情况下可能被视为性暗示或过于成熟的内容以及预测分数。racyScore represents the potential presence and prediction score of content that may be considered sexually suggestive or mature in certain situations.
  • adultScoreracyScore 介于 0 和 1 之间。adultScore and racyScore are between 0 and 1. 分数越高,模型预测类别可能适用的可能性越高。The higher the score, the higher the model is predicting that the category may be applicable. 此预览版依赖于统计模型,而不是人工编码结果。This preview relies on a statistical model rather than manually coded outcomes. 我们建议你对自己的内容进行测试,以确定每个类别是否符合要求。We recommend testing with your own content to determine how each category aligns to your requirements.
  • reviewRecommended 为 true 或 false,具体情况取决于内部评分阈值。reviewRecommended is either true or false depending on the internal score thresholds. 客户应评估是使用该值,还是根据他们的内容策略确定自定义阈值。Customers should assess whether to use this value or decide on custom thresholds based on their content policies.
{
"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
        }
    ]
    ]
}
]
}

后续步骤Next steps

了解如何从你的审查输出生成视频评论Learn how to generate video reviews from your moderation output.

脚本审查添加到你的视频评论中。Add transcript moderation to your video reviews.

了解有关如何生成完整视频和脚本审查解决方案的详细教程。Check out the detailed tutorial on how to build a complete video and transcript moderation solution.

为适用于 .NET 的此内容审查器快速入门以及其他内容审查器快速入门下载 Visual Studio 解决方案Download the Visual Studio solution for this and other Content Moderator quickstarts for .NET.