public async Task ExecuteAsync(WorkerJobHelper <AIJob> jobHelper) { S3Locator inputFile; if (!jobHelper.JobInput.TryGet <S3Locator>(nameof(inputFile), out inputFile)) { throw new Exception($"Invalid or missing input file"); } string mediaFileUrl; if (!string.IsNullOrWhiteSpace(inputFile.HttpEndpoint)) { mediaFileUrl = inputFile.HttpEndpoint; } else { var bucketLocation = await inputFile.GetBucketLocationAsync(); var s3SubDomain = !string.IsNullOrWhiteSpace(bucketLocation) ? $"s3-{bucketLocation}" : "s3"; mediaFileUrl = $"https://{s3SubDomain}.amazonaws.com/{inputFile.AwsS3Bucket}/{inputFile.AwsS3Key}"; } var authTokenUrl = jobHelper.Request.ApiUrl() + "/auth/" + jobHelper.Request.Location() + "/Accounts/" + jobHelper.Request.AccountID() + "/AccessToken?allowEdit=true"; var customHeaders = new Dictionary <string, string> { ["Ocp-Apim-Subscription-Key"] = jobHelper.Request.SubscriptionKey() }; Logger.Debug($"Generate Azure Video Indexer Token: Doing a GET on {authTokenUrl}"); var mcmaHttp = new McmaHttpClient(); var response = await mcmaHttp.GetAsync(authTokenUrl, headers : customHeaders).WithErrorHandling(); var apiToken = await response.Content.ReadAsJsonAsync(); Logger.Debug($"Azure API Token: {apiToken}"); // call the Azure API to process the video // in this scenario the video is located in a public link // so no need to upload the file to Azure /* Sample URL Structure * https://api.videoindexer.ai/{location}/Accounts/{accountId}/Videos? * accessToken={accessToken}& * name={name}?description={string}& * partition={string}& * externalId={string}& * callbackUrl={string}& * metadata={string}& * language={string}& * videoUrl={string}& * fileName={string}& * indexingPreset={string}& * streamingPreset=Default& * linguisticModelId={string}& * privacy={string}& * externalUrl={string}" */ var secureHost = new Uri(jobHelper.JobAssignmentId, UriKind.Absolute).Host; var nonSecureHost = new Uri(jobHelper.Request.GetRequiredContextVariable("PublicUrlNonSecure"), UriKind.Absolute).Host; var callbackUrl = Uri.EscapeDataString(jobHelper.JobAssignmentId.Replace(secureHost, nonSecureHost) + "/notifications"); var postVideoUrl = jobHelper.Request.ApiUrl() + "/" + jobHelper.Request.Location() + "/Accounts/" + jobHelper.Request.AccountID() + "/Videos?accessToken=" + apiToken + "&name=" + inputFile.AwsS3Key + "&callbackUrl=" + callbackUrl + "&videoUrl=" + mediaFileUrl + "&fileName=" + inputFile.AwsS3Key; Logger.Debug($"Call Azure Video Indexer API: Doing a POST on {postVideoUrl}"); var postVideoResponse = await mcmaHttp.PostAsync(postVideoUrl, null, customHeaders).WithErrorHandling(); var azureAssetInfo = await postVideoResponse.Content.ReadAsJsonAsync(); Logger.Debug("azureAssetInfo: ", azureAssetInfo); try { jobHelper.JobOutput["jobInfo"] = azureAssetInfo; await jobHelper.UpdateJobAssignmentOutputAsync(); } catch (Exception error) { Logger.Error("Error updating the job", error); } }
internal static async Task ProcessJobAssignmentAsync(AzureAiServiceWorkerRequest @event) { var resourceManager = @event.GetAwsV4ResourceManager(); var table = new DynamoDbTable(@event.StageVariables["TableName"]); var jobAssignmentId = @event.JobAssignmentId; var azure = new AzureConfig(@event); try { // 1. Setting job assignment status to RUNNING await UpdateJobAssignmentStatusAsync(resourceManager, table, jobAssignmentId, "RUNNING", null); // 2. Retrieving WorkflowJob var job = await RetrieveJobAsync(resourceManager, table, jobAssignmentId); // 3. Retrieve JobProfile var jobProfile = await RetrieveJobProfileAsync(resourceManager, job); // 4. Retrieve job inputParameters var jobInput = job.JobInput; // 5. Check if we support jobProfile and if we have required parameters in jobInput ValidateJobProfile(jobProfile, jobInput); S3Locator inputFile; if (!jobInput.TryGet <S3Locator>(nameof(inputFile), out inputFile)) { throw new Exception("Invalid or missing input file."); } string mediaFileUrl; if (!string.IsNullOrWhiteSpace(inputFile.HttpEndpoint)) { mediaFileUrl = inputFile.HttpEndpoint; } else { var bucketLocation = await inputFile.GetBucketLocationAsync(); var s3SubDomain = !string.IsNullOrWhiteSpace(bucketLocation) ? $"s3-{bucketLocation}" : "s3"; mediaFileUrl = $"https://{s3SubDomain}.amazonaws.com/{inputFile.AwsS3Bucket}/{inputFile.AwsS3Key}"; } switch (jobProfile.Name) { case JOB_PROFILE_TRANSCRIBE_AUDIO: case JOB_PROFILE_TRANSLATE_TEXT: throw new NotImplementedException($"{jobProfile.Name} profile has not yet been implemented for Azure."); case JOB_PROFILE_EXTRACT_ALL_AI_METADATA: var authTokenUrl = azure.ApiUrl + "/auth/" + azure.Location + "/Accounts/" + azure.AccountID + "/AccessToken?allowEdit=true"; var customHeaders = new Dictionary <string, string> { ["Ocp-Apim-Subscription-Key"] = azure.SubscriptionKey }; Logger.Debug($"Generate Azure Video Indexer Token: Doing a GET on {authTokenUrl}"); var mcmaHttp = new McmaHttpClient(); var response = await mcmaHttp.GetAsync(authTokenUrl, headers : customHeaders).WithErrorHandling(); var apiToken = await response.Content.ReadAsJsonAsync(); Logger.Debug($"Azure API Token: {apiToken}"); // call the Azure API to process the video // in this scenario the video is located in a public link // so no need to upload the file to Azure /* Sample URL Structure * https://api.videoindexer.ai/{location}/Accounts/{accountId}/Videos? * accessToken={accessToken}& * name={name}?description={string}& * partition={string}& * externalId={string}& * callbackUrl={string}& * metadata={string}& * language={string}& * videoUrl={string}& * fileName={string}& * indexingPreset={string}& * streamingPreset=Default& * linguisticModelId={string}& * privacy={string}& * externalUrl={string}" */ var secureHost = new Uri(jobAssignmentId, UriKind.Absolute).Host; var nonSecureHost = new Uri(@event.StageVariables["PublicUrlNonSecure"], UriKind.Absolute).Host; var callbackUrl = Uri.EscapeDataString(jobAssignmentId.Replace(secureHost, nonSecureHost) + "/notifications"); var postVideoUrl = azure.ApiUrl + "/" + azure.Location + "/Accounts/" + azure.AccountID + "/Videos?accessToken=" + apiToken + "&name=" + inputFile.AwsS3Key + "&callbackUrl=" + callbackUrl + "&videoUrl=" + mediaFileUrl + "&fileName=" + inputFile.AwsS3Key; Logger.Debug($"Call Azure Video Indexer API: Doing a POST on {postVideoUrl}"); var postVideoResponse = await mcmaHttp.PostAsync(postVideoUrl, null, customHeaders).WithErrorHandling(); var azureAssetInfo = await postVideoResponse.Content.ReadAsJsonAsync(); Logger.Debug("azureAssetInfo: ", azureAssetInfo); try { var jobOutput = new JobParameterBag(); jobOutput["jobInfo"] = azureAssetInfo; await UpdateJobAssignmentWithOutputAsync(table, jobAssignmentId, jobOutput); } catch (Exception error) { Logger.Error("Error updating the job", error); } break; } } catch (Exception ex) { Logger.Exception(ex); try { await UpdateJobAssignmentStatusAsync(resourceManager, table, jobAssignmentId, "FAILED", ex.ToString()); } catch (Exception innerEx) { Logger.Exception(innerEx); } } }