Sviluppare le Funzioni di Azure con Servizi multimedialiDevelop Azure Functions with Media Services

In questo argomento viene illustrato come iniziare a creare le Funzioni di Azure che usano i Servizi multimediali.This topic shows you how to get started with creating Azure Functions that use Media Services. La funzione di Azure definita in questo argomento consente di monitorare un contenitore di account di archiviazione denominato input per i nuovi file MP4.The Azure Function defined in this topic monitors a storage account container named input for new MP4 files. Una volta rilasciato un file nel contenitore di archiviazione, il trigger BLOB eseguirà la funzione.Once a file is dropped into the storage container, the blob trigger will execute the function. Per le funzioni di Azure, vedere Panoramica e altri argomenti della sezione Funzioni di Azure.To review Azure functions, see Overview and other topics in the Azure functions section.

Se si vuole esplorare e distribuire le Funzioni di Azure esistenti che usano i Servizi multimediali di Azure, estrarre Media Services Azure Functions (Funzioni di Azure di Servizi multimediali).If you want to explore and deploy existing Azure Functions that use Azure Media Services, check out Media Services Azure Functions. Questo repository contiene esempi che usano Servizi multimediali per visualizzare i flussi di lavoro correlati all'inserimento di contenuto direttamente dall'archiviazione BLOB, alla codifica e alla scrittura del contenuto nell'archiviazione BLOB.This repository contains examples that use Media Services to show workflows related to ingesting content directly from blob storage, encoding, and writing content back to blob storage. Include inoltre esempi su come monitorare le notifiche dei processi tramite i webhook e le code di Azure.It also includes examples of how to monitor job notifications via WebHooks and Azure Queues. È inoltre possibile sviluppare le funzioni in base agli esempi nel repository Funzioni di Azure dei Servizi multimediali.You can also develop your Functions based on the examples in the Media Services Azure Functions repository. Per distribuire le funzioni, premere il pulsante Distribuisci in Azure.To deploy the functions, press the Deploy to Azure button.

PrerequisitiPrerequisites

  • Per poter creare la prima funzione, è necessario avere un account Azure attivo.Before you can create your first function, you need to have an active Azure account. Se non si possiede già un account Azure, sono disponibili account gratuiti.If you don't already have an Azure account, free accounts are available.
  • Se si intende creare le Funzioni di Azure per eseguire azioni sull'account dei Servizi multimediali di Azure o ascoltare gli eventi inviati dai Servizi multimediali, è necessario creare un account AMS, come descritto qui.If you are going to create Azure Functions that perform actions on your Azure Media Services (AMS) account or listen to events sent by Media Services, you should create an AMS account, as described here.

Creare un'app per le funzioniCreate a function app

  1. Passare al portale di Azure e accedere con il proprio account Azure.Go to the Azure portal and sign-in with your Azure account.
  2. Creare un'app per le funzioni come descritto qui.Create a function app as described here.

Nota

Un account di archiviazione specificato nella variabile di ambiente StorageConnection (vedere il passaggio successivo) deve essere nella stessa area dell'app.A storage account that you specify in the StorageConnection environment variable (see the next step) should be in the same region as your app.

Configurare le impostazioni dell'app per le funzioniConfigure function app settings

Quando si sviluppano le funzioni di Servizi multimediali, è utile aggiungere variabili di ambiente che verranno usati nelle funzioni.When developing Media Services functions, it is handy to add environment variables that will be used throughout your functions. Per configurare le impostazioni dell'app, fare clic sul collegamento Configurare le impostazioni dell'app.To configure app settings, click the Configure App Settings link. Per altre informazioni, vedere Come configurare le impostazioni dell'app per le funzioni di Azure.For more information, see How to configure Azure Function app settings.

Per la funzione definita in questo articolo si presuppongono le seguenti variabili di ambiente nelle impostazioni dell'app:The function, defined in this article, assumes you have the following environment variables in your app settings:

AMSAADTenantDomain: endpoint tenant di Azure AD.AMSAADTenantDomain : Azure AD tenant endpoint. Per altre informazioni sulla connessione alle API di Servizi multimediali di Azure, vedere questo articolo.For more information about connecting to the AMS API, see this article.

AMSRESTAPIEndpoint: URI che rappresenta l'endpoint dell'API REST.AMSRESTAPIEndpoint : URI that represents the REST API endpoint.

AMSClientId: ID client dell'applicazione Azure AD.AMSClientId : Azure AD application client ID.

AMSClientSecret: segreto client dell'applicazione Azure AD.AMSClientSecret: Azure AD application client secret.

StorageConnection: connessione di archiviazione dell'account associato all'account di Servizi multimediali.StorageConnection : storage connection of the account associated with the Media Services account. Questo valore è usato nei file function.json e run.csx (descritti di seguito).This value is used in the function.json file and run.csx file (described below).

Creare una funzioneCreate a function

In seguito alla distribuzione dell'app per le funzioni, questa verrà visualizzata tra le Funzioni di Azure dei Servizi app.Once your function app is deployed, you can find it among App Services Azure Functions.

  1. Selezionare l'app per le funzioni e fare clic su Nuova funzione.Select your function app and click New Function.
  2. Scegliere il linguaggio C# e lo scenario Elaborazione dati.Choose the C# language and Data Processing scenario.
  3. Scegliere il modello BlobTrigger.Choose BlobTrigger template. Questa funzione verrà attivata ogni volta che viene caricato un BLOB nel contenitore di input.This function will be triggered whenever a blob is uploaded into the input container. Il nome input è specificato nel percorso, nel passaggio successivo.The input name is specified in the Path, in the next step.

    input

  4. Dopo aver selezionato BlobTrigger, altri controlli verranno visualizzati nella pagina.Once you select BlobTrigger, some more controls will appear on the page.

    input

  5. Fare clic su Crea.Click Create.

FileFiles

La funzione di Azure è associata al file del codice e ad altri file descritti in questa sezione.Your Azure function is associated with code files and other files that are described in this section. Quando si usa il portale di Azure per creare una funzione, function.json e run.csx vengono creati automaticamente.When you use the Azure portal to create a function, function.json and run.csx are created for you. Sarà necessario aggiungere o caricare un file project.json.You need to add or upload a project.json file. Il resto di questa sezione fornisce una breve spiegazione di ogni file e mostra le relative definizioni.The rest of this section gives a brief explanation of each file and shows their definitions.

input

function.jsonfunction.json

Il file function.json definisce le associazioni di funzione e altre impostazioni di configurazione.The function.json file defines the function bindings and other configuration settings. Il runtime usa questo file per determinare gli eventi da monitorare e come passare i dati e restituirli dall'esecuzione di funzioni.The runtime uses this file to determine the events to monitor and how to pass data into and return data from function execution. Per altre informazioni rivedere Associazioni HTTP e webhook in Funzioni di Azure.For more information, see Azure functions HTTP and webhook bindings.

Nota

Impostare la proprietà disattivato su vero per impedire l'esecuzione della funzione.Set the disabled property to true to prevent the function from being executed.

Sostituire il contenuto del file .json della funzione esistente con il codice seguente:Replace the contents of the existing function.json file with the following code:

{
  "bindings": [
    {
      "name": "myBlob",
      "type": "blobTrigger",
      "direction": "in",
      "path": "input/{filename}.mp4",
      "connection": "ConnectionString"
    }
  ],
  "disabled": false
}

project.jsonproject.json

Il file project.json contiene dipendenze.The project.json file contains dependencies. Di seguito è riportato un esempio del file project.json che include i pacchetti di Servizi multimediali di Azure .NET da Nuget.Here is an example of project.json file that includes the required .NET Azure Media Services packages from Nuget. Si noti che i numeri di versione cambieranno con gli aggiornamenti più recenti per i pacchetti, pertanto è consigliabile confermare le versioni più recenti.Note that the version numbers will change with latest updates to the packages, so you should confirm the most recent versions.

Aggiungere la seguente definizione .json.Add the following definition to project.json.

{
  "frameworks": {
    "net46":{
      "dependencies": {
        "windowsazure.mediaservices": "4.0.0.4",
        "windowsazure.mediaservices.extensions": "4.0.0.4",
        "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.13.1",
        "Microsoft.IdentityModel.Protocol.Extensions": "1.0.2.206221351"
      }
    }
   }
}

run.csxrun.csx

Questo è il codice C# per la funzione.This is the C# code for your function. La funzione definita di seguito monitora un contenitore dell'account di archiviazione denominato input (cioè quello specificato nel percorso) per i nuovi file MP4.The function defined below monitors a storage account container named input (that is what was specified in the path) for new MP4 files. Una volta rilasciato un file nel contenitore di archiviazione, il trigger BLOB eseguirà la funzione.Once a file is dropped into the storage container, the blob trigger will execute the function.

L'esempio viene definito in questa sezione illustraThe example defined in this section demonstrates

  1. come inserire un asset in un account di Servizi multimediali (copiando un BLOB in un asset AMS) ehow to ingest an asset into a Media Services account (by coping a blob into an AMS asset) and
  2. come inviare un processo di codifica che usa il set di impostazioni "Flusso adattivo" di Media Encoder Standard.how to submit an encoding job that uses Media Encoder Standard's "Adaptive Streaming" preset.

Nello scenario reale, è probabile che l'utente desideri tenere traccia dello stato dei processi e quindi pubblicare l'asset codificato.In the real life scenario, you most likely want to track job progress and then publish your encoded asset. Per altre informazioni, vedere Usare i webhook di Azure per monitorare le notifiche dei processi di Servizi multimediali con .NET.For more information, see Use Azure WebHooks to monitor Media Services job notifications. Per altri esempi, vedere Funzioni di Azure dei Servizi multimediali.For more examples, see Media Services Azure Functions.

Sostituire il contenuto del file run.csx esistente con il codice seguente.Replace the contents of the existing run.csx file with the following code. Al termine dell'operazione di definizione della funzione fare clic su Salva ed esegui.Once you are done defining your function click Save and Run.

#r "Microsoft.WindowsAzure.Storage"
#r "Newtonsoft.Json"
#r "System.Web"

using System;
using System.Net;
using System.Net.Http;
using Newtonsoft.Json;
using Microsoft.WindowsAzure.MediaServices.Client;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using System.Web;
using Microsoft.Azure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.Azure.WebJobs;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

// Read values from the App.config file.

static readonly string _AADTenantDomain = Environment.GetEnvironmentVariable("AMSAADTenantDomain");
static readonly string _RESTAPIEndpoint = Environment.GetEnvironmentVariable("AMSRESTAPIEndpoint");

static readonly string _mediaservicesClientId = Environment.GetEnvironmentVariable("AMSClientId");
static readonly string _mediaservicesClientSecret = Environment.GetEnvironmentVariable("AMSClientSecret");

static readonly string _connectionString = Environment.GetEnvironmentVariable("ConnectionString");  

private static CloudMediaContext _context = null;
private static CloudStorageAccount _destinationStorageAccount = null;

public static void Run(CloudBlockBlob myBlob, string fileName, TraceWriter log)
{
    // NOTE that the variables {fileName} here come from the path setting in function.json
    // and are passed into the  Run method signature above. We can use this to make decisions on what type of file
    // was dropped into the input container for the function. 

    // No need to do any Retry strategy in this function, By default, the SDK calls a function up to 5 times for a 
    // given blob. If the fifth try fails, the SDK adds a message to a queue named webjobs-blobtrigger-poison.

    log.Info($"C# Blob trigger function processed: {fileName}.mp4");
    log.Info($"Media Services REST endpoint : {_RESTAPIEndpoint}");

    try
    {
        AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(_AADTenantDomain,
                            new AzureAdClientSymmetricKey(_mediaservicesClientId, _mediaservicesClientSecret),
                            AzureEnvironments.AzureCloudEnvironment);

        AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials);

        _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);

        IAsset newAsset = CreateAssetFromBlob(myBlob, fileName, log).GetAwaiter().GetResult();

        // Step 2: Create an Encoding Job

        // Declare a new encoding job with the Standard encoder
        IJob job = _context.Jobs.Create("Azure Function - MES Job");

        // Get a media processor reference, and pass to it the name of the 
        // processor to use for the specific task.
        IMediaProcessor processor = GetLatestMediaProcessorByName("Media Encoder Standard");

        // Create a task with the encoding details, using a custom preset
        ITask task = job.Tasks.AddNew("Encode with Adaptive Streaming",
            processor,
            "Adaptive Streaming",
            TaskOptions.None); 

        // Specify the input asset to be encoded.
        task.InputAssets.Add(newAsset);

        // Add an output asset to contain the results of the job. 
        // This output is specified as AssetCreationOptions.None, which 
        // means the output asset is not encrypted. 
        task.OutputAssets.AddNew(fileName, AssetCreationOptions.None);

        job.Submit();
        log.Info("Job Submitted");

    }
    catch (Exception ex)
    {
        log.Error("ERROR: failed.");
        log.Info($"StackTrace : {ex.StackTrace}");
        throw ex;
    }
}

private static IMediaProcessor GetLatestMediaProcessorByName(string mediaProcessorName)
{
    var processor = _context.MediaProcessors.Where(p => p.Name == mediaProcessorName).
    ToList().OrderBy(p => new Version(p.Version)).LastOrDefault();

    if (processor == null)
    throw new ArgumentException(string.Format("Unknown media processor", mediaProcessorName));

    return processor;
}

public static async Task<IAsset> CreateAssetFromBlob(CloudBlockBlob blob, string assetName, TraceWriter log){
    IAsset newAsset = null;

    try{
        Task<IAsset> copyAssetTask = CreateAssetFromBlobAsync(blob, assetName, log);
        newAsset = await copyAssetTask;
        log.Info($"Asset Copied : {newAsset.Id}");
    }
    catch(Exception ex){
        log.Info("Copy Failed");
        log.Info($"ERROR : {ex.Message}");
        throw ex;
    }

    return newAsset;
}

/// <summary>
/// Creates a new asset and copies blobs from the specifed storage account.
/// </summary>
/// <param name="blob">The specified blob.</param>
/// <returns>The new asset.</returns>
public static async Task<IAsset> CreateAssetFromBlobAsync(CloudBlockBlob blob, string assetName, TraceWriter log)
{
     //Get a reference to the storage account that is associated with the Media Services account. 
    _destinationStorageAccount = CloudStorageAccount.Parse(_connectionString);

    // Create a new asset. 
    var asset = _context.Assets.Create(blob.Name, AssetCreationOptions.None);
    log.Info($"Created new asset {asset.Name}");

    IAccessPolicy writePolicy = _context.AccessPolicies.Create("writePolicy",
    TimeSpan.FromHours(4), AccessPermissions.Write);
    ILocator destinationLocator = _context.Locators.CreateLocator(LocatorType.Sas, asset, writePolicy);
    CloudBlobClient destBlobStorage = _destinationStorageAccount.CreateCloudBlobClient();

    // Get the destination asset container reference
    string destinationContainerName = (new Uri(destinationLocator.Path)).Segments[1];
    CloudBlobContainer assetContainer = destBlobStorage.GetContainerReference(destinationContainerName);

    try{
    assetContainer.CreateIfNotExists();
    }
    catch (Exception ex)
    {
    log.Error ("ERROR:" + ex.Message);
    }

    log.Info("Created asset.");

    // Get hold of the destination blob
    CloudBlockBlob destinationBlob = assetContainer.GetBlockBlobReference(blob.Name);

    // Copy Blob
    try
    {
    using (var stream = await blob.OpenReadAsync()) 
    {            
        await destinationBlob.UploadFromStreamAsync(stream);          
    }

    log.Info("Copy Complete.");

    var assetFile = asset.AssetFiles.Create(blob.Name);
    assetFile.ContentFileSize = blob.Properties.Length;
    assetFile.IsPrimary = true;
    assetFile.Update();
    asset.Update();
    }
    catch (Exception ex)
    {
    log.Error(ex.Message);
    log.Info (ex.StackTrace);
    log.Info ("Copy Failed.");
    throw;
    }

    destinationLocator.Delete();
    writePolicy.Delete();

    return asset;
}

Testare la funzioneTest your function

Per testare la funzione, è necessario caricare un file MP4 nel contenitore input dell'account di archiviazione specificato nella stringa di connessione.To test your function, you need to upload an MP4 file into the input container of the storage account that you specified in the connection string.

  1. Selezionare l'account di archiviazione specificato nella variabile di ambiente StorageConnection.Select the storage account that you specified in the StorageConnection environment variable.
  2. Fare clic su Blob.Click Blobs.
  3. Fare clic su + Contenitore.Click + Container. Denominare il contenitore input.Name the container input.
  4. Premere Upload e passare al file MP4 che si desidera caricare.Press Upload and browse to an .mp4 file that you want to upload.

Nota

Quando si usa un trigger di tipo BLOB in un piano a consumo, è possibile che si verifichi un ritardo di un massimo di 10 minuti per l'elaborazione di nuovi BLOB in caso di inattività di un'app per le funzioni.When you're using a blob trigger on a Consumption plan, there can be up to a 10-minute delay in processing new blobs after a function app has gone idle. Quando l'app per le funzioni è in esecuzione, i BLOB vengono elaborati immediatamente.After the function app is running, blobs are processed immediately. Per altre informazioni, vedere Trigger e associazioni di archiviazione BLOB.For more information, see Blob storage triggers and bindings.

Passaggi successiviNext steps

A questo punto, si è pronti per iniziare a sviluppare un'applicazione di Servizi multimediali.At this point, you are ready to start developing a Media Services application.

Per altri dettagli ed esempi o soluzioni complete di uso di Funzioni di Azure e delle App per la logica con Servizi multimediali di Azure per creare flussi di lavoro di creazione di contenuto personalizzato, vedere l'Esempio di integrazione delle funzioni di Servizi multimediali .NET su GitHubFor more details and complete samples/solutions of using Azure Functions and Logic Apps with Azure Media Services to create custom content creation workflows, see the Media Services .NET Functions Integration Sample on GitHub

Vedere anche Usare i webhook di Azure per monitorare le notifiche dei processi di Servizi multimediali con .NET.Also, see Use Azure WebHooks to monitor Media Services job notifications with .NET.

Fornire commenti e suggerimentiProvide feedback

Usare il forum di suggerimenti degli utenti per fornire commenti e suggerimenti su come migliorare Servizi multimediali di Azure.Use the User Voice forum to provide feedback and make suggestions on how to improve Azure Media Services. È anche possibile passare direttamente a una delle categorie seguenti:You also can go directly to one of the following categories: