Självstudie: Använda dynamisk DRM-kryptering och licensleveranstjänst

media services-logotyp v3


Letar du efter Media Services v2-dokumentation?

Anteckning

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

Du kan använda Azure Media Services till att leverera strömmar som krypterats med Microsoft PlayReady, Google Widevine eller Apple FairPlay-licenser. En detaljerad förklaring finns i Innehållsskydd med dynamisk kryptering.

Media Services också en tjänst för att leverera PlayReady-, Widevine- och FairPlay DRM-licenser. När en användare begär DRM-skyddat innehåll begär spelarappen en licens från Media Services licenstjänsten. Om spelarappen har auktoriserats utfärdar Media Services licenstjänsten en licens till spelaren. En licens innehåller en krypteringsnyckel som kan användas av klientspelaren för att dekryptera och direktuppspela innehållet.

Den här artikeln bygger på exemplet om kryptering med DRM.

Exemplet som beskrivs i den här artikeln ger följande resultat:

AMS med DRM-skyddad video i Azure Media Player

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

  • Skapa en kodningstransform.
  • Ställ in den signeringsnyckel som användes för att verifiera din token.
  • Ange krav för innehållsnyckelprincipen.
  • Skapa en StreamingLocator med den angivna direktuppspelningsprincipen.
  • Skapa en URL som används för att spela upp filen.

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

Förutsättningar

Följande krävs för att kunna genomföra vägledningen:

Ladda ned koden och konfigurera exemplet

Klona en GitHub-lagringsplats som innehåller hela det .NET-exempel som diskuteras i den här artikeln till din dator med följande kommando:

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

Du hittar exemplet om att kryptera med DRM i mappen EncryptWithDRM.

Ö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.

Anteckning

Exemplet skapar unika resurser varje gång du kör appen. Normalt återanvänder du befintliga resurser som transformeringar och principer (om en befintlig resurs har nödvändiga konfigurationer).

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 konfigurationsfilen (appsettings.jspå ) eller via miljövariablerfilen GetCredentialsAsync ServiceClientCredentials .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 anslutningsparametrarna som anges i den lokala konfigurationsfilen (appsettings.jspå ) eller via miljövariablerfilen GetCredentialsInteractiveAuthAsync ServiceClientCredentials .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 utdatatillgång

Utdatatillgången lagrar resultatet av kodningsjobbet.

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

Hämta eller skapa en kodtransformering

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 transformOutput ett -objekt, som du ser 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 till en autogenererad bithastighetsstege (par med bithastighetsupplösning) baserat på indataupplösning och bithastighet och skapar ISO MP4-filer med H.264-video och AAC-ljud som motsvarar varje par med bithastighetsupplösning.

Innan du skapar en ny 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;
}

Skicka 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. Jobbet anger information som platsen för indatavideon och platsen för utdata.

I den här självstudien skapar vi jobbets indata baserat på en fil som matas in direkt från en HTTPs-käll-URL.

private static async Task<Job> SubmitJobAsync(IAzureMediaServicesClient client,
    string resourceGroup,
    string accountName,
    string transformName,
    string outputAssetName,
    string jobName)
{
    // This example shows how to encode from any HTTPs source URL - a new feature of the v3 API.  
    // Change the URL to any accessible HTTPs URL or SAS URL from Azure.
    JobInputHttp jobInput =
        new JobInputHttp(files: new[] { SourceUri });

    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(
        resourceGroup,
        accountName,
        transformName,
        jobName,
        new Job
        {
            Input = jobInput,
            Outputs = jobOutputs,
        });

    return job;
}

Vänta tills jobbet är klart

Jobbet tar lite tid att slutföra. När det är det vill du få ett meddelande. 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. 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 stött på ett fel visas feltillståndet. 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;
}

Skapa en princip för innehållsnyckel

En innehållsnyckel ger säker åtkomst till dina tillgångar. Du måste skapa en princip för innehållsnyckel när du krypterar ditt innehåll med en DRM. Principen konfigurerar hur innehållsnyckeln levereras till slutklienter. Innehållsnyckeln är associerad med en positionerare för direktuppspelning. Media Services tillhandahåller också nyckelleveranstjänsten som levererar krypteringsnycklar och licenser till behöriga användare.

Du måste ange de krav (begränsningar) för innehållsnyckelprincipen som måste uppfyllas för att leverera nycklar med den angivna konfigurationen. I det här exemplet anger vi följande konfigurationer och krav:

  • Konfiguration

    Licenserna för PlayReady och Widevine är konfigurerade så att de kan levereras av Media Services-licensleveranstjänsten. Även om den här exempelappen inte konfigurerar FairPlay-licensen innehåller den en metod som du kan använda för att konfigurera FairPlay. Du kan lägga till FairPlay-konfiguration som ett annat alternativ.

  • Begränsning

    Appen anger en begränsning JSON Web Token JWT-tokentyp för principen.

När en ström begärs av en spelare krypterar Media Services innehållet med den angivna nyckeln. Om spelaren vill dekryptera dataströmmen begär hon eller han nyckeln från nyckelleveranstjänsten. För att avgöra om användaren är behörig för nyckeln utvärderas den innehållsnyckelprincip som du angav för nyckeln.

private static async Task<ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
    IAzureMediaServicesClient client,
    string resourceGroupName,
    string accountName,
    string contentKeyPolicyName,
    byte[] tokenSigningKey)
{
    bool createPolicy = false;
    ContentKeyPolicy policy = null;
    try
    {
        policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName);
    }
    catch (ErrorResponseException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
    {
        createPolicy = true;
    }

    if (createPolicy)
    {
        ContentKeyPolicySymmetricTokenKey primaryKey = new ContentKeyPolicySymmetricTokenKey(tokenSigningKey);
        List<ContentKeyPolicyTokenClaim> requiredClaims = new List<ContentKeyPolicyTokenClaim>()
        {
            ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim
        };
        List<ContentKeyPolicyRestrictionTokenKey> alternateKeys = null;
        ContentKeyPolicyTokenRestriction restriction
            = new ContentKeyPolicyTokenRestriction(Issuer, Audience, primaryKey, ContentKeyPolicyRestrictionTokenType.Jwt, alternateKeys, requiredClaims);

        ContentKeyPolicyPlayReadyConfiguration playReadyConfig = ConfigurePlayReadyLicenseTemplate();
        ContentKeyPolicyWidevineConfiguration widevineConfig = ConfigureWidevineLicenseTemplate();
        // ContentKeyPolicyFairPlayConfiguration fairplayConfig = ConfigureFairPlayPolicyOptions();

        List<ContentKeyPolicyOption> options = new List<ContentKeyPolicyOption>();

        options.Add(
            new ContentKeyPolicyOption()
            {
                Configuration = playReadyConfig,
                // If you want to set an open restriction, use
                // Restriction = new ContentKeyPolicyOpenRestriction()
                Restriction = restriction
            });

        options.Add(
            new ContentKeyPolicyOption()
            {
                Configuration = widevineConfig,
                Restriction = restriction
            });

        // add CBCS ContentKeyPolicyOption into the list
        //   options.Add(
        //       new ContentKeyPolicyOption()
        //       {
        //           Configuration = fairplayConfig,
        //           Restriction = restriction,
        //           Name = "ContentKeyPolicyOption_CBCS"
        //       });

        policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options);
    }
    else
    {
        // Get the signing key from the existing policy.
        var policyProperties = await client.ContentKeyPolicies.GetPolicyPropertiesWithSecretsAsync(resourceGroupName, accountName, contentKeyPolicyName);
        if (policyProperties.Options[0].Restriction is ContentKeyPolicyTokenRestriction restriction)
        {
            if (restriction.PrimaryVerificationKey is ContentKeyPolicySymmetricTokenKey signingKey)
            {
                TokenSigningKey = signingKey.KeyValue;
            }
        }
    }
    return policy;
}

Skapa en positionerare för direktuppspelning

När kodningen är klar och innehållsnyckelprincipen är inställd är nästa steg att göra videon i utdatatillgången tillgänglig för uppspelning av klienterna. Du gör videon tillgänglig i två steg:

  1. Skapa en positionerare för direktuppspelning.
  2. Skapa webbadresserna för direktuppspelning som klienter kan använda.

Processen att skapa positioneraren för direktuppspelning kallas för publicering. Som standard är positioneraren för direktuppspelning giltig omedelbart efter att du har anropat API:et. Den varar tills den har tagits bort, såvida du inte konfigurerar valfria start- och sluttider.

När du skapar en positionerare för direktuppspelning måste du ange önskad StreamingPolicyName . I den här självstudien använder vi en av de fördefinierade direktuppspelningsprinciperna, som Azure Media Services hur innehållet ska publiceras för strömning. I det här exemplet ställer vi in StreamingLocator.StreamingPolicyName för principen ”Predefined_MultiDrmCencStreaming”. PlayReady- och Widevine-krypteringarna tillämpas och nyckeln levereras till uppspelningsklienten baserat på de konfigurerade DRM-licenserna. Om du dessutom vill kryptera strömmen med CBCS (FairPlay) använder du ”Predefined_MultiDrmStreaming”.

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 StreamingPolicy-poster. Du bör inte skapa en ny StreamingPolicy för varje StreamingLocator.

private static async Task<StreamingLocator> CreateStreamingLocatorAsync(
    IAzureMediaServicesClient client,
    string resourceGroup,
    string accountName,
    string assetName,
    string locatorName,
    string contentPolicyName)
{
    // If you also added FairPlay, use "Predefined_MultiDrmStreaming
    StreamingLocator locator = await client.StreamingLocators.CreateAsync(
        resourceGroup,
        accountName,
        locatorName,
        new StreamingLocator
        {
            AssetName = assetName,
            // "Predefined_MultiDrmCencStreaming" policy supports envelope and cenc encryption
            // And sets two content keys on the StreamingLocator
            StreamingPolicyName = "Predefined_MultiDrmCencStreaming",
            DefaultContentKeyPolicyName = contentPolicyName
        });

    return locator;
}

Hämta en testtoken

I den här självstudien anger vi att innehållsnyckelprincipen ska ha en tokenbegränsning. Den tokenbegränsade principen måste åtföljas av en token utfärdad av en säker tokentjänst (Secure Token Service – STS). Media Services har stöd för token i JWT-format och det är det vi konfigurerar i exemplet.

ContentKeyIdentifierClaim används i ContentKeyPolicy, vilket innebär att den token som presenteras för nyckelleveranstjänst måste innehålla identifieraren för ContentKey. I exemplet anger vi inte någon innehållsnyckel när vi skapar positioneraren för direktuppspelning. Systemet skapar en slumpmässigt åt oss. För att generera testtoken måste vi hämta ContentKeyId att lägga till i ContentKeyIdentifierClaim-anspråket.

private static string GetTokenAsync(string issuer, string audience, string keyIdentifier, byte[] tokenVerificationKey)
{
    var tokenSigningKey = new SymmetricSecurityKey(tokenVerificationKey);

    SigningCredentials cred = new SigningCredentials(
        tokenSigningKey,
        // Use the  HmacSha256 and not the HmacSha256Signature option, or the token will not work!
        SecurityAlgorithms.HmacSha256,
        SecurityAlgorithms.Sha256Digest);

    Claim[] claims = new Claim[]
    {
        new Claim(ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim.ClaimType, keyIdentifier)
    };

    // To set a limit on how many times the same token can be used to request a key or a license.
    // add  the "urn:microsoft:azure:mediaservices:maxuses" claim.
    // For example, claims.Add(new Claim("urn:microsoft:azure:mediaservices:maxuses", 4));

    JwtSecurityToken token = new JwtSecurityToken(
        issuer: issuer,
        audience: audience,
        claims: claims,
        notBefore: DateTime.Now.AddMinutes(-5),
        expires: DateTime.Now.AddMinutes(60),
        signingCredentials: cred);

    JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();

    return handler.WriteToken(token);
}

Skapa en strömnings-URL

Nu när StreamingLocator har skapats kan du hämta direktuppspelningswebbadresserna. Om du vill skapa en URL måste du sammanfoga StreamingEndpoint-värdnamnet 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.

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

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

        // Look for just the DASH path and generate a URL for the Azure Media Player to playback the content with the AES token to decrypt.
        // Note that the JWT token is set to expire in 1 hour. 
        if (path.StreamingProtocol == StreamingPolicyStreamingProtocol.Dash)
        {
            uriBuilder.Path = path.Paths[0];

            dashPath = uriBuilder.ToString();

        }
    }
    return dashPath;
}

När du kör appen visas följande skärm:

Skydda med DRM

Du kan öppna en webbläsare och klistra in den webbadress som bildas för att starta Azure Media Player-demosidan där webbadressen en och token redan är ifyllda.

Rensa resurser på ditt Media Services-konto

I allmänhet bör du rensa bort allt utom objekt som du planerar att återanvända (vanligtvis återanvänder du transformeringar, StreamingLocators och så vidare). 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);
    }
}

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

Ytterligare information

  • Widevine är en tjänst som tillhandahålls av Google Inc. och omfattas av användningsvillkoren och sekretesspolicyn för Google, Inc.

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

Kolla in artikeln Azure Media Services community för att se olika sätt att ställa frågor, ge feedback och få uppdateringar om Media Services.

Nästa steg

Checka ut