Självstudie: Analysera videor med Media Services v3
Letar du efter Media Services v2-dokumentation?
Den här självstudien visar hur du analyserar videor med Azure Media Services. Det finns många scenarier där du kanske vill veta mer om inspelat video- eller ljudinnehåll. Organisationer kan till exempel för att uppnå högre kundnöjdhet köra tal-till-text-bearbetning och konvertera inspelningar från kundtjänst till en sökbar katalog med index och instrumentpaneler.
I den här självstudiekursen lär du dig att:
- Ladda ned exempelappen som beskrivs i avsnittet.
- Granska koden som analyserar den angivna videon.
- Kör appen.
- Granska resultatet.
- Rensa resurser.
Om du inte har en Azure-prenumerationkan du skapa ett kostnads fritt konto innan du börjar.
Efterlevnad, sekretess och säkerhet
Som en viktig påminnelse måste du följa alla tillämpliga lagar i din användning av Azure Video Analyzer for Media (tidigare Video Indexer). Du får inte använda Video Analyzer för media eller någon annan Azure-tjänst på ett sätt som strider mot andras rättigheter. Innan du laddar upp videor, inklusive biometriska data, till Video Analyzer for Media-tjänsten för bearbetning och lagring, måste du ha rätt rättigheter, inklusive alla lämpliga medgivanden, från personerna i videon. Mer information om efterlevnad, sekretess och säkerhet i Video Analyzer for Media finns i Azure Cognitive Services villkor. Microsofts sekretesskrav och hantering av dina data finns i Microsofts sekretesspolicy, Villkor för Onlinetjänster (OST) och tillägget för databehandling ("DPA"). Mer sekretessinformation, inklusive om databevarande, borttagning/destruktion, finns i OST och här. Genom att använda Video Analyzer för media samtycker du till att vara bunden av Cognitive Services villkor, OST, DPA och sekretesspolicyn.
Förutsättningar
- Installera Visual Studio Code för Windows/macOS/Linux eller Visual Studio 2019 för Windows eller Mac.
- Installera .NET 5.0 SDK
- Skapa ett Media Services konto. Se till att kopiera API-åtkomstinformationen i JSON-format eller lagra de värden som behövs för att ansluta till Media Services-kontot i filformatet .env som används i det här exemplet.
- Följ stegen i Access the Azure Media Services API with the Azure CLI (Få åtkomst till API Azure Media Services med Azure CLI och spara autentiseringsuppgifterna. Du måste använda dem för att få åtkomst till API:et i det här exemplet eller ange dem i filformatet .env.
Ladda ned och konfigurera exemplet
Klona en GitHub-lagringsplats som innehåller .NET-exemplet till din dator med följande kommando:
git clone https://github.com/Azure-Samples/media-services-v3-dotnet-tutorials.git
Du hittar exemplet i mappen AnalyzeVideos.
Ö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 analyserar den angivna videon
Det här avsnittet går igenom funktionerna som definierades i filen Program.cs för projektet AnalyzeVideos.
Exemplet slutför följande åtgärder:
- Skapa en transformering och ett jobb som analyserar dina videor.
- Skapar en inkommande tillgång och överför videon till den. TIllgången används som jobbets indata.
- Skapar en utgående tillgång som lagrar utdata för jobbet.
- Skickar jobbet.
- Kontrollerar jobbets status.
- Laddar ned filer som härrör från körningen av jobbet.
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. Om du vill 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 anslutningsparametrarna 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. Tillgången används som indata för kodningsjobbet. I Media Services v3 kan indata till ett jobb antingen vara en tillgång eller innehåll som du gör tillgängligt för Media Services-kontot via HTTPS-webbadresser. 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.
Följande funktion slutför dessa å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 Storage 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 ditt jobb. 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 analyserar videor
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 analyserar den angivna videon.
Transformering
När du skapar en ny instans för en Transformering, måste du ange vilken utdata du vill att den ska skapa. TransformOutput är en obligatorisk parameter. 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. I det här exemplet används förinställningen VideoAnalyzerPreset och språket ("en-US") skickas till konstruktorn ( new VideoAnalyzerPreset("en-US") ). Med denna förinställning kan du extrahera flera ljud- och videoinsikter från en video. Du kan använda förinställningen AudioAnalyzerPreset om du vill extrahera flera ljudinsikter från en video.
När du skapar en transformering kontrollerar du först om det redan finns en med hjälp av metoden Hämta, som du ser 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,
Preset preset)
{
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)
{
// Start by defining the desired outputs.
TransformOutput[] outputs = new TransformOutput[]
{
new TransformOutput(preset),
};
// Create the Transform with the output defined above
transform = await client.Transforms.CreateOrUpdateAsync(resourceGroupName, accountName, transformName, outputs);
}
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. Jobbet anger information som platsen för indatavideon och platsen för utdata. Du kan ange platsen för din video med: HTTPS-webbadresser, SAS-URL:er eller tillgångar som finns på ditt Media Services-konto.
I det här exemplet är jobbets indata en lokal video.
private static async Task<Job> SubmitJobAsync(IAzureMediaServicesClient client,
string resourceGroupName,
string accountName,
string transformName,
string jobName,
JobInput jobInput,
string outputAssetName)
{
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, Get methods 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 lite tid att slutföra. När det gör det vill du bli meddelad. Det finns olika alternativ för att få meddelanden om när jobben är klara. Det enklaste alternativet (som visas här) är att använda avsökning.
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. Mer information finns i 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 sedan Avbryts 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.
Ladda ned jobbets resultat
Följande funktion laddar ned resultaten från utdatatillgången till mappen "utdata" så att du kan granska jobbets resultat.
private static async Task DownloadOutputAssetAsync(
IAzureMediaServicesClient client,
string resourceGroup,
string accountName,
string assetName,
string outputFolderName)
{
if (!Directory.Exists(outputFolderName))
{
Directory.CreateDirectory(outputFolderName);
}
AssetContainerSas assetContainerSas = await client.Assets.ListContainerSasAsync(
resourceGroup,
accountName,
assetName,
permissions: AssetContainerPermission.Read,
expiryTime: DateTime.UtcNow.AddHours(1).ToUniversalTime());
Uri containerSasUrl = new Uri(assetContainerSas.AssetContainerSasUrls.FirstOrDefault());
BlobContainerClient container = new BlobContainerClient(containerSasUrl);
string directory = Path.Combine(outputFolderName, assetName);
Directory.CreateDirectory(directory);
Console.WriteLine($"Downloading output results to '{directory}'...");
string continuationToken = null;
IList<Task> downloadTasks = new List<Task>();
do
{
var resultSegment = container.GetBlobs().AsPages(continuationToken);
foreach (Azure.Page<BlobItem> blobPage in resultSegment)
{
foreach (BlobItem blobItem in blobPage.Values)
{
var blobClient = container.GetBlobClient(blobItem.Name);
string filename = Path.Combine(directory, blobItem.Name);
downloadTasks.Add(blobClient.DownloadToAsync(filename));
}
// Get the continuation token and loop until it is empty.
continuationToken = blobPage.ContinuationToken;
}
} while (continuationToken != "");
await Task.WhenAll(downloadTasks);
Console.WriteLine("Download complete.");
}
Rensa resurser på ditt Media Services-konto
Varning
Det är viktigt att du tar bort resurser om du inte längre behöver dem när du debiteras för dem.
I allmänhet bör du rensa bort allt utom objekt som du planerar att återanvända (vanligtvis återanvänder du transformeringar och bevarar StreamingLocators). 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 och utdatatillgången:
Ta bort resurser med kod
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);
}
}
Du kan också använda CLI.
Ta bort en resursgrupp med CLI
az group delete --name <your-resource-group-name>
Kör exempelappen
Tryck på Ctrl+F5 för att köra appen AnalyzeVideos.
När vi kör programmet skapar jobbet miniatyrer för varje ansikte som hittas i videon. Det skapar också filen insights.json.
Granska utdatan
Utdatafilen för videoanalysen kallas insights.json. Den här filen innehåller insikter om videon. Beskrivning av elementen i json-filen finns i artikeln Medieintelligens.
Flertrådsteknik
Varning
De Azure Media Services v3-SDK:erna är inte trådsäkra. När du arbetar med en flertrådig app bör du generera ett nytt AzureMediaServicesClient-objekt per tråd.