Självstudie: Upload, koda och strömma videor med Media Services v3

media services-logotyp v3


Letar du efter Media Services v2-dokumentation?

Anteckning

Även om den här självstudien använder .NET SDK-exempel är de allmänna stegen desamma för REST API, CLIeller andra SDK:er som stöds.

Azure Media Services kan du koda dina mediefiler till format som spelas upp på en mängd olika webbläsare och enheter. Du kanske vill strömma ditt innehåll i Apples HLS- eller MPEG DASH-formaten. Innan du strömmar, bör du koda dina högkvalitativa digitala mediafiler. Om du behöver hjälp med kodning kan du gå till Kodningsbegrepp. Den här självstudiekursen laddar upp en lokal videofil och kodar den överförda filen. Du kan också koda innehåll som du gör tillgängligt via en HTTPS-URL. Mer information finns i Skapa jobbindata från en HTTP(s)-URL.

Spela upp en video med Azure Media Player

I den här självstudiekursen lär du dig att:

  • Ladda ned exempelappen som beskrivs i avsnittet.
  • Granska koden som laddar upp, kodar och strömmar.
  • Kör appen.
  • Testa strömnings-URL:en.
  • Rensa resurser.

Om du inte har en Azure-prenumerationkan du skapa ett kostnads fritt konto innan du börjar.

Förutsättningar

Ladda ned och konfigurera exemplet

Klona GitHub lagringsplats som har det strömmande .NET-exemplet till datorn med följande kommando:

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

Du hittar exemplet i mappen UploadEncodeAndStreamFiles.

Öppna appsettings.jsi det nedladdade projektet. Ersätt värdena med autentiseringsuppgifterna som du fick från avsnittet om åtkomst till API:er.

Anteckning

Du kan också använda filformatet .env i roten av projektet för att ange dina miljövariabler bara en gång för alla projekt på lagringsplatsen för .NET-exempel. Kopiera bara filen sample.env och fyll sedan i informationen som du fick från Media Services API-åtkomstsidan i Azure Portal eller från Azure CLI. Byt namn på filen sample.env till bara .env för att använda den i alla projekt.

Filen .gitignore har redan konfigurerats för att förhindra att den här filen publiceras på den förked lagringsplatsen.

Granska koden som överför, kodar och strömmar

Det här avsnittet går igenom funktionerna som definierats i filen Program.cs för projektet UploadEncodeAndStreamFiles.

Exemplet utför följande åtgärder:

  1. Skapar en ny transformering (först kontrolleras om den angivna transformeringen finns).
  2. Skapar en utdatatillgång som används som kodningsjobbsutdata.
  3. Skapa en indatatillgång och ladda upp den angivna lokala videofilen till den. TIllgången används som jobbets indata.
  4. Skickar kodningsjobbet med de indata och utdata som skapades.
  5. Kontrollerar jobbets status.
  6. Skapa en positionerare för direktuppspelning.
  7. Skapar strömnings-URL:er.

Börja använda Media Services API:er med .NET SDK

Om du vill Media Services api:er med .NET måste du skapa ett AzureMediaServicesClient -objekt. För att skapa objektet måste du ange autentiseringsuppgifter för att klienten ska kunna ansluta till Azure med hjälp av Azure Active Directory. Ett annat alternativ är att använda interaktiv autentisering, som implementeras i 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,
    };
}

I den kod som du klonade i början av artikeln skapar funktionen objektet baserat på de autentiseringsuppgifter som anges i den lokala GetCredentialsAsync ServiceClientCredentials konfigurationsfilen ( appsettings.json) eller via miljövariablerfilen .env i lagringsplatsens rot.

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

När det gäller interaktiv autentisering skapar funktionen objektet baserat på en interaktiv autentisering och de anslutningsparametrar som anges i den lokala GetCredentialsInteractiveAuthAsync ServiceClientCredentials konfigurationsfilen (appsettings.json) eller via miljövariablerfilen .env i lagringsplatsens rot. I så fall behövs inte AADCLIENTID och AADSECRET i konfigurations- eller miljövariabelfilen.

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

Skapa en indatatillgång och ladda upp en lokal fil till den

Funktionen CreateInputAsset skapar en ny indatatillgång och laddar upp den angivna lokala videofilen till den. Den här tillgången används som indata för kodningsjobbet. I Media Services v3 kan indata för ett jobb antingen vara en tillgång eller ett innehåll som du gör tillgängligt för ditt Media Services-konto via HTTPS-URL:er. Information om hur du kodar från en HTTPS-URL finns i den här artikeln.

I Media Services v3 använder du Azure Storage-API:er till att ladda upp filer. I följande .NET-kodfragment visas hur du gör detta.

Den här funktionen utför följande åtgärder:

  • Skapar en tillgång.

  • Hämtar en skrivbar SAS-URL till tillgångens container i lagringen.

    Om du använder tillgångens ListContainerSas-funktion för att hämta SAS-URL:er ska du observera att funktionen returnerar flera SAS-URL:er eftersom det finns två lagringskontonycklar för varje lagringskonto. Ett lagringskonto har två nycklar eftersom det möjliggör sömlös rotation av lagringskontonycklar (ändra till exempel en när du använder den andra och börja sedan använda den nya nyckeln och rotera den andra nyckeln). Den första SAS-URL:en representerar lagringsnyckeln1 och den andra lagringsnyckeln2.

  • Laddar upp filen till containern i lagringen med hjälp av SAS-URL:en.

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

Skapa en utdatatillgång där resultatet av ett jobb lagras

Utdatatillgången lagrar resultatet av kodningsjobbet. Projektet definierar funktionen DownloadResults som laddar ner resultaten från den här utdatatillgången till mappen ”utdata”, så att du kan se vad du har fått.

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

Skapa en transformering och ett jobb som kodar den uppladdade filen

När du kodar eller bearbetar Media Services är det ett vanligt mönster att konfigurera kodningsinställningarna som ett recept. Du skickar sedan ett Jobb som tillämpar receptet på en video. Genom att skicka nya jobb för varje ny video tillämpar du receptet på alla videor i biblioteket. Ett recept i Media Services kallas för en transformering. Mer information finns i Transformeringar och jobb. Det exempel som beskrivs i självstudien definierar ett recept som kodar videon för att strömma den till olika iOS- och Android-enheter.

Transformering

När du skapar en ny instans för en Transformering, måste du ange vilken utdata du vill att den ska skapa. Den obligatoriska parametern är objektet TransformOutput som visas i koden nedan. Varje TransformOutput innehåller en Förinställning. I Förinställning finns stegvisa anvisningar för den video- och/eller ljudbearbetning som ska användas för att generera önskad TransformOutput. Det exempel som beskrivs i artikeln använder en inbyggd förinställning som kallas AdaptiveStreaming. Förinställningen kodar indatavideon i en automatiskt genererad bithastighetsstege (par för bithastighetsupplösning) som baseras på indatans upplösning och bithastighet, samt producerar ISO MP4-filer med H.264-video och AAC-ljud som motsvarar varje par för bithastighetsupplösningen. Information om denna förinställning finns i Automatisk generering av bithastighetsstege.

Du kan använda en inbyggd EncoderNamedPreset eller anpassade förinställningar. Mer information finns i Så här anpassar du förinställningar för kodning.

När du skapar en Transformering bör du först kontrollera om det redan finns en. Det gör du med metoden Get som visas i koden nedan. I Media Services v3 returnerar Get-metoderna i entiteter null om entiteten inte finns (skiftlägesokänslig kontroll av namnet).

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

Jobb

Som nämns ovan är objektet Transformering receptet och ett Jobb är det faktiska begärandet till Media Services om att tillämpa transformeringen på en indatavideo eller ett ljudinnehåll. Jobb anger information som platsen för indatavideon och platsen för utdatan.

I det här exemplet har indatavideon laddats upp från din lokala dator. Om du vill lära dig hur du kodar från en HTTPS-URL kan du läsa den här artikeln.

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

Vänta tills jobbet är klart

Jobbet tar en stund att slutföra och du meddelas när detta sker. Kodexe exemplet nedan visar hur du avsöker tjänsten efter status för jobbet. Avsökning rekommenderas inte för produktionsappar på grund av potentiell svarstid. Avsökningen kan begränsas om den överanvänds på ett konto. Utvecklare bör i stället använda Event Grid.

Event Grid är utformat för hög tillgänglighet, konsekvent prestanda och dynamisk skalning. Med Event Grid kan dina appar lyssna efter och reagera på händelser från i princip alla Azure-tjänster, samt även från anpassade källor. Med enkel och HTTP-baserad reaktiv händelsehantering blir det lättare att skapa effektiva lösningar med hjälp av intelligent filtrering och dirigering av händelser. Se Dirigera händelser till en anpassad webbslutpunkt.

Jobb har vanligtvis följande tillstånd: Schemalagd, I kö, Bearbetas, Slutförd (slutlig status). Om jobbet har påträffat ett fel visas tillståndet Fel. Om jobbet avbryts får du Avbryt och Avbruten när det är klart.

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

Jobbfelkoder

Se Felkoder.

Hämta en positionerare för direktuppspelning

När kodningen är klar är nästa steg att göra videon i utdatatillgången tillgänglig för uppspelning av klienterna. Du kan göra den tillgänglig i två steg: först skapar du en positionerare för direktuppspelning och sedan skapar du de strömnings-URL:er som klienter kan använda.

Processen att skapa en positionerare för direktuppspelning kallas för publicering. Som standard är positioneraren för direktuppspelning giltig omedelbart efter att du har gjort API-anropen och varar tills den tas bort, såvida du inte konfigurerar valfria start- och sluttider.

När du skapar en StreamingLocatormåste du ange önskat StreamingPolicyName. I det här exemplet strömmar du klart (eller icke-krypterat innehåll) så att den fördefinierade principen för klaruppspelning (PredefinedStreamingPolicy.ClearStreamingOnly) används.

Viktigt

Om du använder en anpassad strömningsprincip bör du skapa en begränsad uppsättning av sådana principer för ditt Media Service-konto, och återanvända dem för dina StreamingLocators när samma krypterings- och protokollalternativ krävs. Media Service-kontot har en kvot för antalet strömningsprincipposter. Du bör inte skapa en ny strömningsprincip för varje positionerare för direktuppspelning.

Följande kod förutsätter att du anropar funktionen med ett unikt 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;
}

Även om exemplet i det här avsnittet beskriver strömning, kan du använda samma anrop för att skapa en positionerare för direktuppspelning som levererar video via progressiv nedladdning.

Hämta strömnings-URL:er

Nu när positioneraren för direktuppspelning har skapats kan du hämta direktuppspelnings-URL:erna, som du ser i GetStreamingURLs. För att skapa en webbadress måste du sammanfoga strömningsslutpunktens värdnamn och sökvägen för positioneraren för direktuppspelning. I det här exemplet används standardslutpunkten för direktuppspelning. När du först skapar ett Media Service-konto är den här standardslutpunkten för direktuppspelning stoppad, så du måste anropa Starta.

Anteckning

I den här metoden behöver du det locatorName som användes när du skapade positioneraren för direktuppspelning för utdatatillgången.

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

Rensa resurser på ditt Media Services-konto

I allmänhet bör du rensa allt utom objekt som du planerar att återanvända (vanligtvis återanvänder du transformeringar och beständiga StreamingLocators osv.). Om du vill att ditt konto ska vara rensat efter experimentet tar du bort de resurser som du inte planerar att återanvända. Följande kod tar till exempel bort jobbet, skapade tillgångar och innehållsnyckelprincipen:

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

Kör exempelappen

  1. Tryck på Ctrl+F5 för att köra appen EncodeAndStreamFiles.
  2. Kopiera en av de strömmande URL:erna från konsolen.

I det här exemplet visas URL:er som kan användas för att spela upp videon med olika protokoll:

Exempelutdata som visar URL:er för Media Services strömmande video

Testa strömnings-URL:en

I den här artikeln används Azure Media Player till att testa strömningen.

Anteckning

Om en spelare finns på en HTTPS-webbplats uppdaterar du URL:en till ”HTTPS”.

  1. Öppna en webbläsare och gå till https://aka.ms/azuremediaplayer/ .
  2. I rutan URL: klistrar du in ett av de strömnings-URL-värden som du fick när du körde appen.
  3. Välj Uppdatera spelare.

Azure Media Player kan användas för testning men ska inte användas i en produktionsmiljö.

Rensa resurser

Om du inte längre behöver någon av resurserna i resursgruppen, inklusive Media Services och de lagringskonton som du skapade för självstudien, tar du bort resursgruppen som du skapade tidigare.

Kör följande CLI-kommando:

az group delete --name amsResourceGroup

Flertrådsteknik

De Azure Media Services v3-SDK:erna är inte trådsäkra. När du utvecklar en flertrådig app bör du generera och använda ett nytt AzureMediaServicesClient-objekt per tråd.

Ställ frågor, ge feedback, få uppdateringar

Ta en Azure Media Services community-artikeln om du vill se olika sätt att ställa frågor, ge feedback och få uppdateringar om Media Services.

Nästa steg

Nu när du vet hur du ska ladda upp, koda och strömma videon kan du läsa följande artikel: