public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"Webhook was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); log.Info("Request : " + jsonContent); var attachedstoragecred = KeyHelper.ReturnStorageCredentials(); // Validate input objects if (data.assetId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } if (data.targetStorageAccountName == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass targetStorageAccountName in the input object" })); } if (data.targetStorageAccountKey == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass targetStorageAccountKey in the input object" })); } if (data.targetContainer == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass targetContainer in the input object" })); } string targetStorageAccountName = data.targetStorageAccountName; string targetStorageAccountKey = data.targetStorageAccountKey; string targetContainer = data.targetContainer; string startsWith = data.startsWith; string endsWith = data.endsWith; log.Info("Input - targetStorageAccountName : " + targetStorageAccountName); log.Info("Input - targetStorageAccountKey : " + targetStorageAccountKey); log.Info("Input - targetContainer : " + targetContainer); string assetId = data.assetId; IAsset asset = null; IIngestManifest manifest = null; MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}"); try { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Find the Asset asset = _context.Assets.Where(a => a.Id == assetId).FirstOrDefault(); if (asset == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } string storname = amsCredentials.StorageAccountName; string storkey = amsCredentials.StorageAccountKey; if (asset.StorageAccountName != amsCredentials.StorageAccountName) { if (attachedstoragecred.ContainsKey(asset.StorageAccountName)) // asset is using another storage than default but we have the key { storname = asset.StorageAccountName; storkey = attachedstoragecred[storname]; } else // we don't have the key for that storage { log.Info($"Face redaction Asset is in {asset.StorageAccountName} and key is not provided in MediaServicesAttachedStorageCredentials application settings"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Storage key is missing" })); } } // Setup blob container CloudBlobContainer sourceBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, asset.Uri.Segments[1]); CloudBlobContainer destinationBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(targetStorageAccountName, targetStorageAccountKey, targetContainer); destinationBlobContainer.CreateIfNotExists(); var files = asset.AssetFiles.ToList().Where(f => ((string.IsNullOrEmpty(endsWith) || f.Name.EndsWith(endsWith)) && (string.IsNullOrEmpty(startsWith) || f.Name.StartsWith(startsWith)))); string path = data.targetPath != null ? data.targetPath : string.Empty; // if user wants to use folder(s) for the output blob(s) foreach (var file in files) { CloudBlob sourceBlob = sourceBlobContainer.GetBlockBlobReference(file.Name); CloudBlob destinationBlob = destinationBlobContainer.GetBlockBlobReference(path + file.Name); CopyBlobHelpers.CopyBlobAsync(sourceBlob, destinationBlob); log.Info($"Start copy of file : {file.Name}"); } } catch (Exception ex) { string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : ""); log.Info($"ERROR: Exception {message}"); return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message })); } return(req.CreateResponse(HttpStatusCode.OK)); }
public static async Task<object> Run([HttpTrigger(WebHookType = "genericJson")]HttpRequestMessage req, TraceWriter log) { log.Info($"Webhook was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); log.Info("Request : " + jsonContent); MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); var attachedstoragecred = KeyHelper.ReturnStorageCredentials(); // Validate input objects int delay = 5000; if (data.destinationContainer == null) return req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass DestinationContainer in the input object" }); if (data.delay != null) delay = data.delay; log.Info("Input - DestinationContainer : " + data.destinationContainer); //log.Info("delay : " + delay); log.Info($"Wait " + delay + "(ms)"); System.Threading.Thread.Sleep(delay); string storname = amsCredentials.StorageAccountName; string storkey = amsCredentials.StorageAccountKey; if (data.assetStorage != null) { string assetstor = (string)data.assetStorage; if (assetstor != amsCredentials.StorageAccountName) { if (attachedstoragecred.ContainsKey(assetstor)) // asset is using another storage than default but we have the key { storname = assetstor; storkey = attachedstoragecred[storname]; } else // we don't have the key for that storage { log.Info($"Face redaction Asset is in {assetstor} and key is not provided in MediaServicesAttachedStorageCredentials application settings"); return req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Storage key is missing" }); } } } string destinationContainerName = data.destinationContainer; CloudBlobContainer destinationBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, destinationContainerName); CopyStatus copyStatus = CopyStatus.Success; try { string blobPrefix = null; bool useFlatBlobListing = true; var destBlobList = destinationBlobContainer.ListBlobs(blobPrefix, useFlatBlobListing, BlobListingDetails.Copy); foreach (var dest in destBlobList) { var destBlob = dest as CloudBlob; if (destBlob.CopyState.Status == CopyStatus.Aborted || destBlob.CopyState.Status == CopyStatus.Failed) { // Log the copy status description for diagnostics and restart copy destBlob.StartCopyAsync(destBlob.CopyState.Source); copyStatus = CopyStatus.Pending; } else if (destBlob.CopyState.Status == CopyStatus.Pending) { // We need to continue waiting for this pending copy // However, let us log copy state for diagnostics copyStatus = CopyStatus.Pending; } // else we completed this pending copy } } catch (Exception ex) { string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : ""); log.Info($"ERROR: Exception {message}"); return req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message }); } return req.CreateResponse(HttpStatusCode.OK, new { copyStatus = copyStatus, isRunning = (copyStatus == CopyStatus.Pending).ToString(), isSuccessful = (copyStatus == CopyStatus.Success).ToString() }); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"Webhook was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); log.Info("Request : " + jsonContent); MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}"); // Validate input objects if (data.assetId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } string assetId = data.assetId; var attachedstoragecred = KeyHelper.ReturnStorageCredentials(); string mp4FileName = ""; IAsset asset = null; try { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Find the Asset asset = _context.Assets.Where(a => a.Id == assetId).FirstOrDefault(); if (asset == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } var files = asset.AssetFiles.ToList().Where(f => !f.Name.EndsWith(".mp4")); string storname = amsCredentials.StorageAccountName; string storkey = amsCredentials.StorageAccountKey; if (asset.StorageAccountName != amsCredentials.StorageAccountName) { if (attachedstoragecred.ContainsKey(asset.StorageAccountName)) // asset is using another storage than default but we have the key { storname = asset.StorageAccountName; storkey = attachedstoragecred[storname]; } else // we don't have the key for that storage { log.Info($"Face redaction Asset is in {asset.StorageAccountName} and key is not provided in MediaServicesAttachedStorageCredentials application settings"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Storage key is missing" })); } } // Setup blob container CloudBlobContainer sourceBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, asset.Uri.Segments[1]); foreach (var file in asset.AssetFiles.ToList()) { if (file.Name.EndsWith(".mp4")) { file.IsPrimary = true; file.Update(); mp4FileName = file.Name; } else { file.Delete(); CloudBlob sourceBlob = sourceBlobContainer.GetBlockBlobReference(file.Name); sourceBlob.DeleteIfExists(); log.Info($"Start copy of file : {file.Name}"); } } asset.Update(); MediaServicesHelper.SetAFileAsPrimary(asset); } catch (Exception ex) { string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : ""); log.Info($"ERROR: Exception {message}"); return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message })); } return(req.CreateResponse(HttpStatusCode.OK, new { mp4FileName })); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"Webhook was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); log.Info(jsonContent); var attachedstoragecred = KeyHelper.ReturnStorageCredentials(); if (data.assetId == null) { // for test // data.Path = "/input/WP_20121015_081924Z.mp4"; return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}"); try { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Step 1: Copy the Blob into a new Input Asset for the Job // ***NOTE: Ideally we would have a method to ingest a Blob directly here somehow. // using code from this sample - https://azure.microsoft.com/en-us/documentation/articles/media-services-copying-existing-blob/ // Get the asset string assetid = data.assetId; var asset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault(); if (asset == null) { log.Info($"Asset not found {assetid}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } log.Info("Asset found, ID: " + asset.Id); string storname = amsCredentials.StorageAccountName; string storkey = amsCredentials.StorageAccountKey; if (asset.StorageAccountName != amsCredentials.StorageAccountName) { if (attachedstoragecred.ContainsKey(asset.StorageAccountName)) // asset is using another storage than default but we have the key { storname = asset.StorageAccountName; storkey = attachedstoragecred[storname]; } else // we don't have the key for that storage { log.Info($"Face redaction Asset is in {asset.StorageAccountName} and key is not provided in MediaServicesAttachedStorageCredentials application settings"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Storage key is missing" })); } } CloudBlobContainer assetContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, asset.Uri.Segments[1]); foreach (String seg in asset.Uri.Segments) { log.Info($"> asset.Uri.Segments :" + seg); } /*IEnumerable<CloudBlobContainer> containers = blobClient.ListContainers(); * foreach (CloudBlobContainer item in containers) * { * foreach (IListBlobItem blob in item.ListBlobs()) * { * blobs.Add(string.Format("{0}", blob.Uri.Segments[2])); * } * } */ /* * //Get a reference to the storage account that is associated with the Media Services account. * StorageCredentials mediaServicesStorageCredentials = * new StorageCredentials(_storageAccountName, _storageAccountKey); * var _destinationStorageAccount = new CloudStorageAccount(mediaServicesStorageCredentials, false); * * CloudBlobClient destBlobStorage = _destinationStorageAccount.CreateCloudBlobClient(); * * // Get the destination asset container reference * string destinationContainerName = asset.Uri.Segments[1]; * log.Info($"destinationContainerName : {destinationContainerName}"); * * CloudBlobContainer assetContainer = destBlobStorage.GetContainerReference(destinationContainerName); */ log.Info($"assetContainer retrieved"); // Get hold of the destination blobs var blobsPseudo = assetContainer.ListBlobs(); log.Info($"blobsPseudo retrieved"); log.Info($"blobsPseudo count : {blobsPseudo.Count()}"); var aflist = asset.AssetFiles.ToList().Select(af => af.Name); /* OLD WAY * foreach (CloudBlockBlob blob in blobs) * { * if (aflist.Contains(blob.Name)) * { * var assetFile = asset.AssetFiles.Where(af => af.Name == blob.Name).FirstOrDefault(); * assetFile.ContentFileSize = blob.Properties.Length; * assetFile.Update(); * log.Info($"Asset file updated : {assetFile.Name}"); * } * else * { * var assetFile = asset.AssetFiles.Create(blob.Name); * assetFile.ContentFileSize = blob.Properties.Length; * assetFile.Update(); * log.Info($"Asset file created : {assetFile.Name}"); * } * } */ log.Info($"Witness 3 "); //Adding mecanic to list all sub dir (original just lists elements in given folder and consider them as blob even if they are subdirs) //var folders = blobs.Where(b => b as CloudBlobDirectory != null).ToList(); //this is supposedly a 2 levels scenario... might not suits our case yet (one more level?) foreach (IListBlobItem blobItem in blobsPseudo) { log.Info($"blobItem found : "); if (blobItem is CloudBlobDirectory) { CloudBlobDirectory directory = (CloudBlobDirectory)blobItem; IEnumerable <IListBlobItem> blobs = directory.ListBlobs(); //ICloudBlob bi; foreach (var item in blobs) { log.Info($"item StorageUri : " + item.StorageUri); CloudBlockBlob blob = (CloudBlockBlob)item; blob.FetchAttributes(); log.Info($"Blob found uri : " + blob.Uri); log.Info($"Blob found Name : " + blob.Name); String potentialName = Path.GetFileName(blob.Name); log.Info($"Blob potentialName : " + potentialName); String normalizedName = potentialName; if (aflist.Contains(normalizedName)) { log.Info($" aflist.Contains Blob found Name : " + normalizedName); var assetFile = asset.AssetFiles.Where(af => af.Name == normalizedName).FirstOrDefault(); assetFile.ContentFileSize = blob.Properties.Length; assetFile.Update(); log.Info($"Asset file updated : {normalizedName}"); } else { log.Info($"Create Blob found Name : " + normalizedName); var assetFile = asset.AssetFiles.Create(normalizedName); assetFile.ContentFileSize = blob.Properties.Length; assetFile.Update(); log.Info($"Asset file created : {normalizedName}"); } } } else { //TODO redefine ! CloudBlockBlob blob = (CloudBlockBlob)blobItem; blob.FetchAttributes(); log.Info($"Blob2 found uri : " + blob.Uri); log.Info($"Blob2 found Name : " + blob.Name); if (aflist.Contains(blob.Name)) { var assetFile = asset.AssetFiles.Where(af => af.Name == blob.Name).FirstOrDefault(); assetFile.ContentFileSize = blob.Properties.Length; assetFile.Update(); log.Info($"Asset2 file updated : {assetFile.Name}"); } else { var assetFile = asset.AssetFiles.Create(blob.Name); assetFile.ContentFileSize = blob.Properties.Length; assetFile.Update(); log.Info($"Asset2 file created : {assetFile.Name}"); } } } asset.Update(); MediaServicesHelper.SetAFileAsPrimary(asset); log.Info("Asset updated"); } catch (Exception ex) { string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : ""); log.Info($"ERROR: Exception {message}"); return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message })); } return(req.CreateResponse(HttpStatusCode.OK)); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"Webhook was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); log.Info(jsonContent); var attachedstoragecred = KeyHelper.ReturnStorageCredentials(); if (data.assetId == null) { // for test // data.Path = "/input/WP_20121015_081924Z.mp4"; return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}"); try { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Step 1: Copy the Blob into a new Input Asset for the Job // ***NOTE: Ideally we would have a method to ingest a Blob directly here somehow. // using code from this sample - https://azure.microsoft.com/en-us/documentation/articles/media-services-copying-existing-blob/ // Get the asset string assetid = data.assetId; var asset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault(); if (asset == null) { log.Info($"Asset not found {assetid}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } log.Info("Asset found, ID: " + asset.Id); string storname = amsCredentials.StorageAccountName; string storkey = amsCredentials.StorageAccountKey; if (asset.StorageAccountName != amsCredentials.StorageAccountName) { if (attachedstoragecred.ContainsKey(asset.StorageAccountName)) // asset is using another storage than default but we have the key { storname = asset.StorageAccountName; storkey = attachedstoragecred[storname]; } else // we don't have the key for that storage { log.Info($"Face redaction Asset is in {asset.StorageAccountName} and key is not provided in MediaServicesAttachedStorageCredentials application settings"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Storage key is missing" })); } } CloudBlobContainer assetContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, asset.Uri.Segments[1]); /* * //Get a reference to the storage account that is associated with the Media Services account. * StorageCredentials mediaServicesStorageCredentials = * new StorageCredentials(_storageAccountName, _storageAccountKey); * var _destinationStorageAccount = new CloudStorageAccount(mediaServicesStorageCredentials, false); * * CloudBlobClient destBlobStorage = _destinationStorageAccount.CreateCloudBlobClient(); * * // Get the destination asset container reference * string destinationContainerName = asset.Uri.Segments[1]; * log.Info($"destinationContainerName : {destinationContainerName}"); * * CloudBlobContainer assetContainer = destBlobStorage.GetContainerReference(destinationContainerName); */ log.Info($"assetContainer retrieved"); // Get hold of the destination blobs var blobs = assetContainer.ListBlobs(); log.Info($"blobs retrieved"); log.Info($"blobs count : {blobs.Count()}"); var aflist = asset.AssetFiles.ToList().Select(af => af.Name); foreach (CloudBlockBlob blob in blobs) { if (aflist.Contains(blob.Name)) { var assetFile = asset.AssetFiles.Where(af => af.Name == blob.Name).FirstOrDefault(); assetFile.ContentFileSize = blob.Properties.Length; assetFile.Update(); log.Info($"Asset file updated : {assetFile.Name}"); } else { var assetFile = asset.AssetFiles.Create(blob.Name); assetFile.ContentFileSize = blob.Properties.Length; assetFile.Update(); log.Info($"Asset file created : {assetFile.Name}"); } } asset.Update(); MediaServicesHelper.SetAFileAsPrimary(asset); log.Info("Asset updated"); } catch (Exception ex) { string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : ""); log.Info($"ERROR: Exception {message}"); return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message })); } return(req.CreateResponse(HttpStatusCode.OK)); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"Webhook was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); log.Info("Request : " + jsonContent); var attachedstoragecred = KeyHelper.ReturnStorageCredentials(); // Validate input objects if (data.assetId == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass assetId in the input object" })); } if (data.fileName == null && data.fileNames == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass fileName or fileNames in the input object" })); } if (data.sourceStorageAccountName == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass sourceStorageAccountName in the input object" })); } if (data.sourceStorageAccountKey == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass sourceStorageAccountKey in the input object" })); } if (data.sourceContainer == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass sourceContainer in the input object" })); } log.Info("Input - sourceStorageAccountName : " + data.sourceStorageAccountName); log.Info("Input - sourceStorageAccountKey : " + data.sourceStorageAccountKey); log.Info("Input - sourceContainer : " + data.sourceContainer); string _sourceStorageAccountName = data.sourceStorageAccountName; string _sourceStorageAccountKey = data.sourceStorageAccountKey; string assetId = data.assetId; bool missingBlob = false; IAsset newAsset = null; IIngestManifest manifest = null; MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}"); try { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Find the Asset newAsset = _context.Assets.Where(a => a.Id == assetId).FirstOrDefault(); if (newAsset == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } // Setup blob container CloudBlobContainer sourceBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(_sourceStorageAccountName, _sourceStorageAccountKey, (string)data.sourceContainer); string storname = amsCredentials.StorageAccountName; string storkey = amsCredentials.StorageAccountKey; if (newAsset.StorageAccountName != amsCredentials.StorageAccountName) { if (attachedstoragecred.ContainsKey(newAsset.StorageAccountName)) // asset is using another storage than default but we have the key { storname = newAsset.StorageAccountName; storkey = attachedstoragecred[storname]; } else // we don't have the key for that storage { log.Info($"Face redaction Asset is in {newAsset.StorageAccountName} and key is not provided in MediaServicesAttachedStorageCredentials application settings"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Storage key is missing" })); } } CloudBlobContainer destinationBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, newAsset.Uri.Segments[1]); sourceBlobContainer.CreateIfNotExists(); if (data.fileName != null) { string fileName = (string)data.fileName; CloudBlob sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName); if (data.wait != null && (bool)data.wait) { for (int i = 1; i <= 3; i++) // let's wait 3 times 5 seconds (15 seconds) { if (sourceBlob.Exists()) { break; } log.Info("Waiting 5 s..."); System.Threading.Thread.Sleep(5 * 1000); sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName); } } if (sourceBlob.Exists()) { CloudBlob destinationBlob = destinationBlobContainer.GetBlockBlobReference(fileName); if (destinationBlobContainer.CreateIfNotExists()) { log.Info("container created"); destinationBlobContainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob }); } CopyBlobHelpers.CopyBlobAsync(sourceBlob, destinationBlob); } else { missingBlob = true; } } if (data.fileNames != null) { foreach (var file in data.fileNames) { string fileName = (string)file; CloudBlob sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName); if (sourceBlob.Exists()) { CloudBlob destinationBlob = destinationBlobContainer.GetBlockBlobReference(fileName); if (destinationBlobContainer.CreateIfNotExists()) { log.Info("container created"); destinationBlobContainer.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob }); } CopyBlobHelpers.CopyBlobAsync(sourceBlob, destinationBlob); } else { missingBlob = true; } } } } catch (Exception ex) { string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : ""); log.Info($"ERROR: Exception {message}"); return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message })); } return(req.CreateResponse(HttpStatusCode.OK, new { destinationContainer = newAsset.Uri.Segments[1], missingBlob = missingBlob.ToString() })); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { { log.Info($"Webhook was triggered!"); // Init variables string pathUrl = ""; string jsonFaceRedaction = ""; dynamic jpgFaces = new JArray() as dynamic; dynamic objFaceDetection = new JObject(); dynamic objFaceDetectionOffset = new JObject(); dynamic pngThumbnails = new JArray() as dynamic; string prefixpng = ""; string jsonMotionDetection = ""; dynamic objMotionDetection = new JObject(); dynamic objMotionDetectionOffset = new JObject(); string jsonOcr = ""; dynamic objOcr = new JObject(); dynamic objOcrOffset = new JObject(); string jsonAnnotation = ""; dynamic objAnnotation = new JObject(); dynamic objAnnotationOffset = new JObject(); string jsonModeration = ""; dynamic objModeration = new JObject(); dynamic objModerationOffset = new JObject(); string copyToContainer = ""; string prefixjpg = ""; string targetContainerUri = ""; TimeSpan timeOffset = new TimeSpan(0); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); var attachedstoragecred = KeyHelper.ReturnStorageCredentials(); log.Info(jsonContent); MediaServicesCredentials amsCredentials = new MediaServicesCredentials(); log.Info($"Using Azure Media Service Rest API Endpoint : {amsCredentials.AmsRestApiEndpoint}"); try { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(amsCredentials.AmsAadTenantDomain, new AzureAdClientSymmetricKey(amsCredentials.AmsClientId, amsCredentials.AmsClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(amsCredentials.AmsRestApiEndpoint, tokenProvider); // Offset value ? if (data.timeOffset != null) // let's store the offset { timeOffset = TimeSpan.Parse((string)data.timeOffset); } // // FACE REDACTION // if (data.faceRedaction != null && data.faceRedaction.assetId != null) { List <CloudBlob> listJPGCopies = new List <CloudBlob>(); // Get the asset string assetid = data.faceRedaction.assetId; var outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault(); if (outputAsset == null) { log.Info($"Asset not found {assetid}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } var jsonFile = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".JSON")).FirstOrDefault(); var jpgFiles = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".JPG")); Uri publishurl = MediaServicesHelper.GetValidOnDemandPath(_context, outputAsset); if (publishurl != null) { pathUrl = publishurl.ToString(); } else { log.Info($"Asset not published"); } // Let's copy the JPG faces if (data.faceRedaction.copyToContainer != null) { copyToContainer = data.faceRedaction.copyToContainer + DateTime.UtcNow.ToString("yyyyMMdd"); // let's copy JPG to a container prefixjpg = outputAsset.Uri.Segments[1] + "-"; log.Info($"prefixjpg {prefixjpg}"); string storname = amsCredentials.StorageAccountName; string storkey = amsCredentials.StorageAccountKey; if (outputAsset.StorageAccountName != amsCredentials.StorageAccountName) { if (attachedstoragecred.ContainsKey(outputAsset.StorageAccountName)) // asset is using another storage than default but we have the key { storname = outputAsset.StorageAccountName; storkey = attachedstoragecred[storname]; } else // we don't have the key for that storage { log.Info($"Face redaction Asset is in {outputAsset.StorageAccountName} and key is not provided in MediaServicesAttachedStorageCredentials application settings"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Storage key is missing" })); } } var sourceContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, outputAsset.Uri.Segments[1]); CloudBlobContainer targetContainer; if (data.faceRedaction.copyToContainerAccountName != null) { // copy to a specific storage account targetContainer = CopyBlobHelpers.GetCloudBlobContainer((string)data.faceRedaction.copyToContainerAccountName, (string)data.faceRedaction.copyToContainerAccountKey, copyToContainer); } else { // copy to ams storage account targetContainer = CopyBlobHelpers.GetCloudBlobContainer(amsCredentials.StorageAccountName, amsCredentials.StorageAccountKey, copyToContainer); } listJPGCopies = await CopyBlobHelpers.CopyFilesAsync(sourceContainer, targetContainer, prefixjpg, "jpg", log); targetContainerUri = targetContainer.Uri.ToString(); } foreach (IAssetFile file in jpgFiles) { string index = file.Name.Substring(file.Name.Length - 10, 6); int index_i = 0; if (int.TryParse(index, out index_i)) { dynamic entry = new JObject(); entry.id = index_i; entry.fileId = file.Id; entry.fileName = file.Name; if (copyToContainer != "") { entry.url = targetContainerUri + "/" + prefixjpg + file.Name; } else if (!string.IsNullOrEmpty(pathUrl)) { entry.url = pathUrl + file.Name; } jpgFaces.Add(entry); } } if (jsonFile != null) { jsonFaceRedaction = MediaServicesHelper.ReturnContent(jsonFile); objFaceDetection = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonFaceRedaction); objFaceDetectionOffset = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonFaceRedaction); if (timeOffset.Ticks != 0) // Let's add the offset { foreach (var frag in objFaceDetectionOffset.fragments) { frag.start = ((long)(frag.start)) + (long)((((double)timeOffset.Ticks / (double)TimeSpan.TicksPerSecond) * (double)objFaceDetectionOffset.timescale)); } } } if (jsonFaceRedaction != "" && data.faceRedaction.deleteAsset != null && ((bool)data.faceRedaction.deleteAsset)) // If asset deletion was asked { // let's wait for the copy to finish before deleting the asset.. if (listJPGCopies.Count > 0) { log.Info("JPG Copy with asset deletion was asked. Checking copy status..."); bool continueLoop = true; while (continueLoop) { listJPGCopies = listJPGCopies.Where(r => r.CopyState.Status == CopyStatus.Pending).ToList(); if (listJPGCopies.Count == 0) { continueLoop = false; } else { log.Info("JPG Copy not finished. Waiting 3s..."); Task.Delay(TimeSpan.FromSeconds(3d)).Wait(); listJPGCopies.ForEach(r => r.FetchAttributes()); } } } outputAsset.Delete(); } } // // MES Thumbnails // if (data.mesThumbnails != null && data.mesThumbnails.assetId != null) { List <CloudBlob> listPNGCopies = new List <CloudBlob>(); // Get the asset string assetid = data.mesThumbnails.assetId; var outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault(); if (outputAsset == null) { log.Info($"Asset not found {assetid}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } var pngFiles = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".PNG")); Uri publishurl = MediaServicesHelper.GetValidOnDemandPath(_context, outputAsset); if (publishurl != null) { pathUrl = publishurl.ToString(); } else { log.Info($"Asset not published"); } // Let's copy the PNG Thumbnails if (data.mesThumbnails.copyToContainer != null) { copyToContainer = data.mesThumbnails.copyToContainer + DateTime.UtcNow.ToString("yyyyMMdd"); // let's copy PNG to a container prefixpng = outputAsset.Uri.Segments[1] + "-"; log.Info($"prefixpng {prefixpng}"); string storname = amsCredentials.StorageAccountName; string storkey = amsCredentials.StorageAccountKey; if (outputAsset.StorageAccountName != amsCredentials.StorageAccountName) { if (attachedstoragecred.ContainsKey(outputAsset.StorageAccountName)) // asset is using another storage than default but we have the key { storname = outputAsset.StorageAccountName; storkey = attachedstoragecred[storname]; } else // we don't have the key for that storage { log.Info($"MES Thumbnails Asset is in {outputAsset.StorageAccountName} and key is not provided in MediaServicesAttachedStorageCredentials application settings"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Storage key is missing" })); } } var sourceContainer = CopyBlobHelpers.GetCloudBlobContainer(storname, storkey, outputAsset.Uri.Segments[1]); CloudBlobContainer targetContainer; if (data.mesThumbnails.copyToContainerAccountName != null) { // copy to a specific storage account targetContainer = CopyBlobHelpers.GetCloudBlobContainer((string)data.mesThumbnails.copyToContainerAccountName, (string)data.mesThumbnails.copyToContainerAccountKey, copyToContainer); } else { // copy to ams storage account targetContainer = CopyBlobHelpers.GetCloudBlobContainer(amsCredentials.StorageAccountName, amsCredentials.StorageAccountKey, copyToContainer); } listPNGCopies = await CopyBlobHelpers.CopyFilesAsync(sourceContainer, targetContainer, prefixpng, "png", log); targetContainerUri = targetContainer.Uri.ToString(); } foreach (IAssetFile file in pngFiles) { string index = file.Name.Substring(file.Name.Length - 10, 6); int index_i = 0; if (int.TryParse(index, out index_i)) { dynamic entry = new JObject(); entry.id = index_i; entry.fileId = file.Id; entry.fileName = file.Name; if (copyToContainer != "") { entry.url = targetContainerUri + "/" + prefixpng + file.Name; } else if (!string.IsNullOrEmpty(pathUrl)) { entry.url = pathUrl + file.Name; } pngThumbnails.Add(entry); } } if (data.mesThumbnails.deleteAsset != null && ((bool)data.mesThumbnails.deleteAsset)) { // If asset deletion was asked // let's wait for the copy to finish before deleting the asset.. if (listPNGCopies.Count > 0) { log.Info("PNG Copy with asset deletion was asked. Checking copy status..."); bool continueLoop = true; while (continueLoop) { listPNGCopies = listPNGCopies.Where(r => r.CopyState.Status == CopyStatus.Pending).ToList(); if (listPNGCopies.Count == 0) { continueLoop = false; } else { log.Info("PNG Copy not finished. Waiting 3s..."); Task.Delay(TimeSpan.FromSeconds(3d)).Wait(); listPNGCopies.ForEach(r => r.FetchAttributes()); } } } outputAsset.Delete(); } } // // MOTION DETECTION // if (data.motionDetection != null && data.motionDetection.assetId != null) { // Get the asset string assetid = data.motionDetection.assetId; var outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault(); if (outputAsset == null) { log.Info($"Asset not found {assetid}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } var jsonFile = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".JSON")).FirstOrDefault(); if (jsonFile != null) { jsonMotionDetection = MediaServicesHelper.ReturnContent(jsonFile); objMotionDetection = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonMotionDetection); objMotionDetectionOffset = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonMotionDetection); if (timeOffset.Ticks != 0) // Let's add the offset { foreach (var frag in objMotionDetectionOffset.fragments) { frag.start = ((long)(frag.start)) + (long)((((double)timeOffset.Ticks / (double)TimeSpan.TicksPerSecond) * (double)objMotionDetectionOffset.timescale)); } } } if (jsonMotionDetection != "" && data.motionDetection.deleteAsset != null && ((bool)data.motionDetection.deleteAsset)) // If asset deletion was asked { outputAsset.Delete(); } } // // OCR // if (data.ocr != null && data.ocr.assetId != null) { // Get the asset string assetid = data.ocr.assetId; var outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault(); if (outputAsset == null) { log.Info($"Asset not found {assetid}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } var jsonFile = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".JSON")).FirstOrDefault(); if (jsonFile != null) { jsonOcr = MediaServicesHelper.ReturnContent(jsonFile); objOcr = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonOcr); objOcrOffset = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonOcr); if (timeOffset.Ticks != 0) // Let's add the offset { foreach (var frag in objOcrOffset.fragments) { frag.start = ((long)(frag.start)) + (long)((((double)timeOffset.Ticks / (double)TimeSpan.TicksPerSecond) * (double)objOcrOffset.timescale)); } } } if (jsonOcr != "" && data.ocr.deleteAsset != null && ((bool)data.ocr.deleteAsset)) // If asset deletion was asked { outputAsset.Delete(); } } // // Video Annotator // if (data.videoAnnotation != null && data.videoAnnotation.assetId != null) { // Get the asset string assetid = data.videoAnnotation.assetId; var outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault(); if (outputAsset == null) { log.Info($"Asset not found {assetid}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } var jsonFile = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".JSON")).FirstOrDefault(); log.Info($"JSON file = {jsonFile}"); if (jsonFile != null) { jsonAnnotation = MediaServicesHelper.ReturnContent(jsonFile); objAnnotation = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonAnnotation); objAnnotationOffset = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonAnnotation); if (timeOffset.Ticks != 0) // Let's add the offset { foreach (var frag in objAnnotationOffset.fragments) { frag.start = ((long)(frag.start)) + (long)((((double)timeOffset.Ticks / (double)TimeSpan.TicksPerSecond) * (double)objAnnotationOffset.timescale)); } } } if (jsonAnnotation != "" && data.videoAnnotation.deleteAsset != null && ((bool)data.videoAnnotation.deleteAsset)) // If asset deletion was asked { outputAsset.Delete(); } } // // Content Moderation // if (data.contentModeration != null && data.contentModeration.assetId != null) { // Get the asset string assetid = data.contentModeration.assetId; var outputAsset = _context.Assets.Where(a => a.Id == assetid).FirstOrDefault(); if (outputAsset == null) { log.Info($"Asset not found {assetid}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset not found" })); } var jsonFile = outputAsset.AssetFiles.Where(a => a.Name.ToUpper().EndsWith(".JSON")).FirstOrDefault(); log.Info($"JSON file = {jsonFile}"); if (jsonFile != null) { jsonModeration = MediaServicesHelper.ReturnContent(jsonFile); objModeration = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonModeration); objModerationOffset = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonModeration); if (timeOffset.Ticks != 0) // Let's add the offset { foreach (var frag in objModerationOffset.fragments) { frag.start = ((long)(frag.start)) + (long)((((double)timeOffset.Ticks / (double)TimeSpan.TicksPerSecond) * (double)objModerationOffset.timescale)); if (frag.events != null) { for (int i = 0; i < frag.events.Count; i++) { frag.events[i][0].timestamp = ((long)(frag.events[i][0].timestamp)) + (long)((((double)timeOffset.Ticks / (double)TimeSpan.TicksPerSecond) * (double)objModerationOffset.timescale)); } } } } } if (jsonModeration != "" && data.contentModeration.deleteAsset != null && ((bool)data.contentModeration.deleteAsset)) // If asset deletion was asked { outputAsset.Delete(); } } } catch (Exception ex) { string message = ex.Message + ((ex.InnerException != null) ? Environment.NewLine + MediaServicesHelper.GetErrorMessage(ex) : ""); log.Info($"ERROR: Exception {message}"); return(req.CreateResponse(HttpStatusCode.InternalServerError, new { error = message })); } log.Info($""); return(req.CreateResponse(HttpStatusCode.OK, new { faceRedaction = new { json = Newtonsoft.Json.JsonConvert.SerializeObject(objFaceDetection), jsonOffset = Newtonsoft.Json.JsonConvert.SerializeObject(objFaceDetectionOffset), jpgFaces = Newtonsoft.Json.JsonConvert.SerializeObject(jpgFaces) }, mesThumbnail = new { pngThumbnails = Newtonsoft.Json.JsonConvert.SerializeObject(pngThumbnails) }, motionDetection = new { json = Newtonsoft.Json.JsonConvert.SerializeObject(objMotionDetection), jsonOffset = Newtonsoft.Json.JsonConvert.SerializeObject(objMotionDetectionOffset) }, ocr = new { json = Newtonsoft.Json.JsonConvert.SerializeObject(objOcr), jsonOffset = Newtonsoft.Json.JsonConvert.SerializeObject(objOcrOffset) }, videoAnnotation = new { json = Newtonsoft.Json.JsonConvert.SerializeObject(objAnnotation), jsonOffset = Newtonsoft.Json.JsonConvert.SerializeObject(objAnnotationOffset) }, contentModeration = new { json = Newtonsoft.Json.JsonConvert.SerializeObject(objModeration), jsonOffset = Newtonsoft.Json.JsonConvert.SerializeObject(objModerationOffset) } })); } }