Example #1
0
        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()
            });
        }
Example #3
0
        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
            }));
        }
Example #4
0
        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));
        }
Example #5
0
        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));
        }
Example #6
0
        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)
                    }
                }));
            }
        }