Руководство по Отправка, кодировка и потоковая передача видео с помощью Служб мультимедиа версии 3

Логотип Служб мультимедиа версии 3


Ищете документацию по Службам мультимедиа версии 2?

Примечание

Несмотря на то, что в этом учебнике используются примеры для пакета SDK для .NET , общие шаги одинаковы для REST API, CLI или других поддерживаемых пакетов SDK.

Службы мультимедиа Azure позволяют кодировать файлы мультимедиа в форматы, пригодные для воспроизведения в разных браузерах и на различных устройствах. Например, можно организовать потоковую передачу содержимого в форматах HLS или MPEG DASH от Apple. Перед тем как передавать файл мультимедиа высокого качества, его нужно закодировать. Справку по кодированию см. в разделе Концепция кодирования. В этом руководстве описана отправка локального файла видео и кодирование загруженного файла. Также можно закодировать содержимое, которое доступно через URL-адрес HTTPS. Дополнительные сведения см. в разделе Создание входных данных задания из URL-адреса HTTP (HTTPS).

Воспроизведение видео с помощью Проигрывателя мультимедиа Azure

В этом учебнике описаны следующие процедуры.

  • Скачивание примера приложения, описанного в этой статье.
  • Проверка кода, который загружает, кодирует и выполняет потоковую передачу.
  • Запустите приложение.
  • Тестирование URL-адреса потоковой передачи.
  • Очистка ресурсов.

Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начать работу.

Предварительные требования

Скачивание и настройка примера

Клонируйте репозиторий GitHub, содержащий пример потоковой передачи данных .NET на компьютер с помощью следующей команды:

git clone https://github.com/Azure-Samples/media-services-v3-dotnet-tutorials.git

Этот образец находится в папке UploadEncodeAndStreamFiles.

Откройте файл appsettings.json в скачанном проекте. Замените значения учетными данными, которые вы получили, выполнив действия из статьи Доступ к API Служб мультимедиа Azure с помощью Azure CLI.

Примечание

Можно также использовать ENV-файл в корне проекта, чтобы единоразово задать переменные среды для всех проектов в репозитории примеров .NET. Просто скопируйте файл sample.env и затем добавьте в него сведения, полученные на странице Доступ к API Служб мультимедиа на портале Azure или посредством Azure CLI. Переименуйте файл sample.env в .env, чтобы использовать его во всех проектах.

Файл с расширением .gitignore уже настроен, чтобы не публиковать содержимое этого файла в разветвленном репозитории.

Проверка кода, который загружает, кодирует и выполняет потоковую передачу

В этом разделе рассматриваются функции, определенные в файле Program.cs проекта UploadEncodeAndStreamFiles.

Этот пример выполняет следующие действия:

  1. Создает новое преобразование (сначала проверяет, существует ли указанное преобразование).
  2. Создает выходной ресурс, который используется в качестве выходных данных задания кодирования.
  3. Создает входной ресурс и передает в него указанный локальный файл видео. Ресурс используется в качестве входных данных задания.
  4. Отправляет задание кодирования с использованием входных и выходных данных, которые были созданы.
  5. Проверяет состояние задания.
  6. Создает указатель потоковой передачи.
  7. компиляция URL-адресов потоковой передачи.

Начало использования интерфейсов API Служб мультимедиа с пакетом SDK для .NET

Чтобы начать использовать API Служб мультимедиа с .NET, создайте объект AzureMediaServicesClient. Чтобы создать объект, введите учетные данные, необходимые клиенту для подключения к Azure с помощью Azure Active Directory. Другой вариант — использовать интерактивную проверку подлинности, реализованную в GetCredentialsInteractiveAuthAsync.

public static async Task<IAzureMediaServicesClient> CreateMediaServicesClientAsync(ConfigWrapper config, bool interactive = false)
{
    ServiceClientCredentials credentials;
    if (interactive)
        credentials = await GetCredentialsInteractiveAuthAsync(config);
    else
        credentials = await GetCredentialsAsync(config);

    return new AzureMediaServicesClient(config.ArmEndpoint, credentials)
    {
        SubscriptionId = config.SubscriptionId,
    };
}

В коде, клонированном в начале этой статьи, функция GetCredentialsAsync создает объект ServiceClientCredentials на основе учетных данных, предоставленных в локальном файле конфигурации (appsettings.json) или ENV-файле переменных среды в корне репозитория.

private static async Task<ServiceClientCredentials> GetCredentialsAsync(ConfigWrapper config)
{
    // Use ConfidentialClientApplicationBuilder.AcquireTokenForClient to get a token using a service principal with symmetric key

    var scopes = new[] { config.ArmAadAudience + "/.default" };

    var app = ConfidentialClientApplicationBuilder.Create(config.AadClientId)
        .WithClientSecret(config.AadSecret)
        .WithAuthority(AzureCloudInstance.AzurePublic, config.AadTenantId)
        .Build();

    var authResult = await app.AcquireTokenForClient(scopes)
                                             .ExecuteAsync()
                                             .ConfigureAwait(false);

    return new TokenCredentials(authResult.AccessToken, TokenType);
}

В случае интерактивной проверки подлинности функция GetCredentialsInteractiveAuthAsync создает объект ServiceClientCredentials на основе интерактивной проверки подлинности и параметров подключения, переданных в локальном файле конфигурации (appsettings.json) или в ENV-файле переменных среды в корне репозитория. В этом случае не требуется указывать AADCLIENTID и AADSECRET в файле конфигурации или переменных среды.

private static async Task<ServiceClientCredentials> GetCredentialsInteractiveAuthAsync(ConfigWrapper config)
{
    var scopes = new[] { config.ArmAadAudience + "/user_impersonation" };

    // client application of Az Cli
    string ClientApplicationId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46";

    AuthenticationResult result = null;

    IPublicClientApplication app = PublicClientApplicationBuilder.Create(ClientApplicationId)
        .WithAuthority(AzureCloudInstance.AzurePublic, config.AadTenantId)
        .WithRedirectUri("http://localhost")
        .Build();

    var accounts = await app.GetAccountsAsync();

    try
    {
        result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
    }
    catch (MsalUiRequiredException ex)
    {
        try
        {
            result = await app.AcquireTokenInteractive(scopes).ExecuteAsync();
        }
        catch (MsalException maslException)
        {
            Console.Error.WriteLine($"ERROR: MSAL interactive authentication exception with code '{maslException.ErrorCode}' and message '{maslException.Message}'.");
        }
    }
    catch (MsalException maslException)
    {
        Console.Error.WriteLine($"ERROR: MSAL silent authentication exception with code '{maslException.ErrorCode}' and message '{maslException.Message}'.");
    }

    return new TokenCredentials(result.AccessToken, TokenType);
}

Создание входного ресурса и отправка в него локального файла

Функция CreateInputAsset создает входной ресурс и отправляет в него определенный локальный видеофайл. Этот ресурс используется в качестве входных данных для задания кодирования. В Службах мультимедиа версии 3 входные данные для задания могут быть либо ресурсом, либо содержимым, доступным в учетной записи Служб мультимедиа через URL-адрес HTTPS. Сведения о кодировании URL-адреса HTTPS см. в этой статье.

В Службах мультимедиа версии 3 для отправки файлов используются API службы хранилища. В следующих фрагментах кода .NET показано, как это сделать.

Следующая функция выполняет такие действия:

  • создает ресурс;

  • получает записываемый URL-адрес SAS в контейнере в хранилище ресурса;

    При использовании функции ListContainerSas ресурса для получения URL-адресов SAS обратите внимание, что функция возвращает несколько URL-адресов SAS, так как для каждой учетной записи хранения существует два ключа. Учетная запись хранения имеет два ключа, чтобы обеспечить легкую смену ключей (например, можно использовать первый ключ и в это время заменить второй ключ, а затем начать использовать новый ключ, а в это время заменить первый ключ). Первый URL-адресом SAS представляет собой ключ к хранилищу данных 1, а второй — ключ к хранилищу данных 2.

  • отправляет файл в контейнер в хранилище через URL-адрес SAS.

private static async Task<Asset> CreateInputAssetAsync(
    IAzureMediaServicesClient client,
    string resourceGroupName,
    string accountName,
    string assetName,
    string fileToUpload)
{
    // In this example, we are assuming that the asset name is unique.
    //
    // If you already have an asset with the desired name, use the Assets.Get method
    // to get the existing asset. In Media Services v3, the Get method on entities returns null 
    // if the entity doesn't exist (a case-insensitive check on the name).

    // Call Media Services API to create an Asset.
    // This method creates a container in storage for the Asset.
    // The files (blobs) associated with the asset will be stored in this container.
    Asset asset = await client.Assets.CreateOrUpdateAsync(resourceGroupName, accountName, assetName, new Asset());

    // Use Media Services API to get back a response that contains
    // SAS URL for the Asset container into which to upload blobs.
    // That is where you would specify read-write permissions 
    // and the exparation time for the SAS URL.
    var response = await client.Assets.ListContainerSasAsync(
        resourceGroupName,
        accountName,
        assetName,
        permissions: AssetContainerPermission.ReadWrite,
        expiryTime: DateTime.UtcNow.AddHours(4).ToUniversalTime());

    var sasUri = new Uri(response.AssetContainerSasUrls.First());

    // Use Storage API to get a reference to the Asset container
    // that was created by calling Asset's CreateOrUpdate method.  
    BlobContainerClient container = new BlobContainerClient(sasUri);
    BlobClient blob = container.GetBlobClient(Path.GetFileName(fileToUpload));

    // Use Strorage API to upload the file into the container in storage.
    await blob.UploadAsync(fileToUpload);

    return asset;
}

Создание выходного ресурса для хранения результатов задания

Выходной ресурс сохраняет результаты задания кодирования. Проект определяет функцию DownloadResults, которая скачивает результаты из выходного ресурса в папку output, чтобы вы могли просмотреть их.

private static async Task<Asset> CreateOutputAssetAsync(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string assetName)
{
    bool existingAsset = true;
    Asset outputAsset;
    try
    {
        // Check if an Asset already exists
        outputAsset = await client.Assets.GetAsync(resourceGroupName, accountName, assetName);
    }
    catch (ErrorResponseException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
    {
        existingAsset = false;
    }

    Asset asset = new Asset();
    string outputAssetName = assetName;

    if (existingAsset)
    {
        // Name collision! In order to get the sample to work, let's just go ahead and create a unique asset name
        // Note that the returned Asset can have a different name than the one specified as an input parameter.
        // You may want to update this part to throw an Exception instead, and handle name collisions differently.
        string uniqueness = $"-{Guid.NewGuid():N}";
        outputAssetName += uniqueness;

        Console.WriteLine("Warning – found an existing Asset with name = " + assetName);
        Console.WriteLine("Creating an Asset with this name instead: " + outputAssetName);
    }

    return await client.Assets.CreateOrUpdateAsync(resourceGroupName, accountName, outputAssetName, asset);
}

Создание преобразования и задания, которое кодирует отправленный файл

При кодировании или обработке содержимого в Службах мультимедиа параметры кодировки часто задают в качестве набора инструкций. Затем необходимо отправить задание, чтобы применить этот набор к видео. Отправляя новые задания для каждого нового видео, вы применяете этот набор ко всем видео в своей библиотеке. Набор инструкций в Службах мультимедиа называется Преобразование. Дополнительные сведения см. в статье Преобразования и задания. Пример кода, описанный в руководстве, определяет набор инструкций, которые кодируют видео для его потоковой передачи на различные устройства под управлением iOS и Android.

Преобразование

При создании нового экземпляра преобразования необходимо указать, что требуется создать в качестве выходных данных. Обязательный параметр — это объект TransformOutput, как показано в приведенном ниже примере кода. Каждый объект TransformOutput содержит предустановку (Preset). Предустановка описывает пошаговые инструкции для операций обработки видео и звука, которые будут использоваться для создания нужного объекта TransformOutput. Пример, описанный в этой статье, использует встроенную предустановку, называемую AdaptiveStreaming. Предустановка кодирует входное видео в автоматически созданную схему скоростей и разрешений (пары "скорость — разрешение") на основе входного разрешения и скорости и создает файлы ISO MP4 с видео H.264 и аудио AAC, соответствующие каждой паре "скорость — разрешение". Дополнительные сведения об этой предустановке см. в этой статье.

Вы можете использовать встроенную предустановку кодирования или пользовательскую предустановку. Дополнительные сведения см. в разделе How to customize encoder presets (Настройка предустановки кодировщика).

При создании преобразования сначала проверьте, существует ли оно, с помощью метода Get, как показано в следующем коде. В Службах мультимедиа версии 3 методы Get, отправленные к сущностям, возвращают значение NULL, если сущность не существует (проверка по имени без учета регистра).

private static async Task<Transform> GetOrCreateTransformAsync(
    IAzureMediaServicesClient client,
    string resourceGroupName,
    string accountName,
    string transformName)
{
    bool createTransform = false;
    Transform transform = null;
    try
    {
        // Does a transform already exist with the desired name? Assume that an existing Transform with the desired name
        // also uses the same recipe or Preset for processing content.
        transform = client.Transforms.Get(resourceGroupName, accountName, transformName);
    }
    catch (ErrorResponseException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
    {
        createTransform = true;
    }

    if (createTransform)
    {
        // You need to specify what you want it to produce as an output
        TransformOutput[] output = new TransformOutput[]
        {
            new TransformOutput
            {
                // The preset for the Transform is set to one of Media Services built-in sample presets.
                // You can  customize the encoding settings by changing this to use "StandardEncoderPreset" class.
                Preset = new BuiltInStandardEncoderPreset()
                {
                    // This sample uses the built-in encoding preset for Adaptive Bitrate Streaming.
                    PresetName = EncoderNamedPreset.AdaptiveStreaming
                }
            }
        };

        // Create the Transform with the output defined above
        transform = await client.Transforms.CreateOrUpdateAsync(resourceGroupName, accountName, transformName, output);
    }

    return transform;
}

Задание

Как было указано выше, объект преобразования является набором инструкций, а задание — фактическим запросом к Службам мультимедиа для применения этого преобразования к данному видео и аудио. Задание указывает такую информацию, как расположение входного и выходного видео.

В этом примере входное видео было отправлено с локального компьютера. Дополнительные сведения о кодировании из URL-адреса HTTPS см. в этой статье.

private static async Task<Job> SubmitJobAsync(IAzureMediaServicesClient client,
    string resourceGroupName,
    string accountName,
    string transformName,
    string jobName,
    string inputAssetName,
    string outputAssetName)
{
    // Use the name of the created input asset to create the job input.
    JobInput jobInput = new JobInputAsset(assetName: inputAssetName);

    JobOutput[] jobOutputs =
    {
        new JobOutputAsset(outputAssetName),
    };

    // In this example, we are assuming that the job name is unique.
    //
    // If you already have a job with the desired name, use the Jobs.Get method
    // to get the existing job. In Media Services v3, the Get method on entities returns null 
    // if the entity doesn't exist (a case-insensitive check on the name).
    Job job = await client.Jobs.CreateAsync(
        resourceGroupName,
        accountName,
        transformName,
        jobName,
        new Job
        {
            Input = jobInput,
            Outputs = jobOutputs,
        });

    return job;
}

Ожидание завершения задания

Выполнение задания занимает некоторое время. По его завершению вы будете уведомлены. В примере кода ниже показано, как опрашивать службу о состоянии задания. Опрос не рекомендуется для приложений рабочей среды из-за потенциальной задержки. Его можно регулировать при чрезмерном использовании в учетной записи. Вместо этого разработчики должны использовать службу "Сетка событий".

Служба "Сетка событий" предназначена для обеспечения высокого уровня доступности, стабильной производительности и динамического масштабирования. С помощью службы "Сетка событий Azure" приложения могут ожидать передачи данных и реагировать на события, поступающие буквально из всех служб Azure и пользовательских источников. Простая реактивная обработка событий на основе HTTP позволяет создавать эффективные решения с использованием интеллектуальной фильтрации и маршрутизации событий. Дополнительные сведения см. в статье Route Azure Media Services events to a custom web endpoint using CLI (Маршрутизация событий Служб мультимедиа в пользовательскую конечную точку с помощью CLI).

Для задания обычно последовательно устанавливаются следующие состояния: Запланировано, В очереди, Идет обработка, Завершено (конечное состояние). Если в задании обнаружена ошибка, вы получите состояние Ошибка. Если задание находится в процессе отмены, вы получите состояние Выполнение отмены и Отменено по завершении.

private static async Task<Job> WaitForJobToFinishAsync(IAzureMediaServicesClient client,
    string resourceGroupName,
    string accountName,
    string transformName,
    string jobName)
{
    const int SleepIntervalMs = 20 * 1000;

    Job job;
    do
    {
        job = await client.Jobs.GetAsync(resourceGroupName, accountName, transformName, jobName);

        Console.WriteLine($"Job is '{job.State}'.");
        for (int i = 0; i < job.Outputs.Count; i++)
        {
            JobOutput output = job.Outputs[i];
            Console.Write($"\tJobOutput[{i}] is '{output.State}'.");
            if (output.State == JobState.Processing)
            {
                Console.Write($"  Progress (%): '{output.Progress}'.");
            }

            Console.WriteLine();
        }

        if (job.State != JobState.Finished && job.State != JobState.Error && job.State != JobState.Canceled)
        {
            await Task.Delay(SleepIntervalMs);
        }
    }
    while (job.State != JobState.Finished && job.State != JobState.Error && job.State != JobState.Canceled);

    return job;
}

Коды ошибок задания

См. статью о кодах ошибок.

Создание указателя потоковой передачи

После выполнения кодирования необходимо сделать видео в выходном ресурсе доступным для воспроизведения клиентами. Это можно сделать в два этапа. Сначала создайте указатель потоковой передачи, а затем URL-адреса потоковой передачи, которые могут использовать клиенты.

Процесс создания указателя потоковой передачи называется публикацией. По умолчанию указатель потоковой передачи допустим сразу после выполнения вызова API и действует, пока не будет удален, если не настроить дополнительное начальное и конечное время.

При создании StreamingLocator необходимо указать желаемое имя StreamingPolicyName. В этом примере выполняется потоковая передача незашифрованного содержимого, поэтому используется предварительно определенная политика прозрачной потоковой передачи (PredefinedStreamingPolicy.ClearStreamingOnly).

Важно!

При использовании пользовательской политики потоковой передачи следует разработать ограниченный набор таких политик для учетной записи Служб мультимедиа и повторно использовать их для компонентов StreamingLocator каждый раз, когда требуются те же параметры шифрования и протоколы. У вашей учетной записи служб мультимедиа есть квота на количество входов в политику потоковой передачи. Вам не нужно создавать новую политику потоковой передачи для каждого указателя потоковой передачи.

В следующем коде предполагается, что вы вызываете функцию с уникальным locatorName.

private static async Task<StreamingLocator> CreateStreamingLocatorAsync(
    IAzureMediaServicesClient client,
    string resourceGroup,
    string accountName,
    string assetName,
    string locatorName)
{
    StreamingLocator locator = await client.StreamingLocators.CreateAsync(
        resourceGroup,
        accountName,
        locatorName,
        new StreamingLocator
        {
            AssetName = assetName,
            StreamingPolicyName = PredefinedStreamingPolicy.ClearStreamingOnly
        });

    return locator;
}

Хотя пример в этом разделе рассматривает потоковую передачу, этот же вызов можно использовать, чтобы создать указатель потоковой передачи для передачи видео с помощью поэтапной загрузки.

Получение URL-адресов потоковой передачи

После создания указателя потоковой передачи можно получить URL-адреса потоковой передачи, как показано в разделе GetStreamingURLs. Чтобы создать URL-адрес, необходимо сцепить имя узла конечной точки потоковой передачи и путь указателя потоковой передачи. В этом примере используется конечная точка потоковой передачи по умолчанию. При первом создании учетной записи Служб мультимедиа эта конечная точка потоковой передачи по умолчанию будет находиться в состоянии "Остановлено", поэтому вам необходимо вызвать функцию Start.

Примечание

В этом методе вам необходим locatorName, который использовался при создании указателя потоковой передачи для выходного ресурса.

private static async Task<IList<string>> GetStreamingUrlsAsync(
    IAzureMediaServicesClient client,
    string resourceGroupName,
    string accountName,
    String locatorName)
{
    const string DefaultStreamingEndpointName = "default";

    IList<string> streamingUrls = new List<string>();

    StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(resourceGroupName, accountName, DefaultStreamingEndpointName);

    if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running)
    {
        await client.StreamingEndpoints.StartAsync(resourceGroupName, accountName, DefaultStreamingEndpointName);
    }

    ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName);

    foreach (StreamingPath path in paths.StreamingPaths)
    {
        UriBuilder uriBuilder = new UriBuilder
        {
            Scheme = "https",
            Host = streamingEndpoint.HostName,

            Path = path.Paths[0]
        };
        streamingUrls.Add(uriBuilder.ToString());
    }
    return streamingUrls;
}

Очистка ресурсов в учетной записи Служб мультимедиа

Как правило, необходимо очистить все, кроме объектов, которые вы планируете использовать повторно. Обычно повторно используются преобразования и сохраняются StreamingLocators и т. д. Если учетную запись требуется очистить после эксперимента, удалите ресурсы, которые не планируется использовать повторно. Удалить задание, созданные ресурсы и политику ключа содержимого можно с помощью следующего кода:

private static async Task CleanUpAsync(
   IAzureMediaServicesClient client,
   string resourceGroupName,
   string accountName,
   string transformName,
   string jobName,
   List<string> assetNames,
   string contentKeyPolicyName = null
   )
{
    await client.Jobs.DeleteAsync(resourceGroupName, accountName, transformName, jobName);

    foreach (var assetName in assetNames)
    {
        await client.Assets.DeleteAsync(resourceGroupName, accountName, assetName);
    }

    if (contentKeyPolicyName != null)
    {
        client.ContentKeyPolicies.Delete(resourceGroupName, accountName, contentKeyPolicyName);
    }
}

Запуск примера приложения

  1. Нажмите клавиши CTRL+F5, чтобы выполнить приложение EncodeAndStreamFiles.
  2. Скопируйте URL-адрес потоковой передачи из консоли.

В этом примере отображаются URL-адреса, которые можно использовать для воспроизведения видео с помощью различных протоколов:

Пример вывода URL-адресов для потоковой передачи видео в Службу мультимедиа

Тестирование URL-адреса потоковой передачи.

Для тестирования потоковой передачи в этой статье используется Проигрыватель мультимедиа Azure.

Примечание

Если проигрыватель размещен на сайте HTTPS, обновите URL-адрес до HTTPS.

  1. Откройте браузер и перейдите по ссылке https://aka.ms/azuremediaplayer/.
  2. В поле URL: (URL-адрес:) вставьте одно из значений URL-адресов потоковой передачи, полученных при работе приложения.
  3. Выберите Update Player (Обновить проигрыватель).

Проигрыватель мультимедиа Azure можно использовать для тестирования, но его нельзя применять в рабочей среде.

Очистка ресурсов

Если вам больше не нужны какие-либо ресурсы в группе ресурсов, включая Службы мультимедиа и учетные записи хранения, созданные для этого руководства, удалите группу ресурсов, созданную ранее.

Выполните следующую команду CLI:

az group delete --name amsResourceGroup

Многопоточность

Пакеты SDK для Служб мультимедиа Azure версии 3 не являются потокобезопасными. При разработке многопоточного приложения необходимо создать и использовать новый объект AzureMediaServicesClient для каждого потока.

Получение справки, отправка отзывов, получение обновлений

Прочитайте статью сообщества Служб мультимедиа Azure, чтобы узнать, как задавать вопросы, оставлять отзывы и получать новости о Службах мультимедиа.

Дальнейшие действия

Теперь, когда вы знаете, как отправлять, кодировать и выполнять потоковую передачу своего видео, перейдите к следующей статье: