public static void Run([BlobTrigger("audio-in/{name}", Connection = "AudioInConnectionString")] CloudBlockBlob inputBlob, string name, TraceWriter log)
        {
            log.Info($"Azure Media Services Audio Indexer for '{name}' started");

            try
            {
                AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(_azureTenantId,
                                                                                       new AzureAdClientSymmetricKey(_azureClientId, _azureClientSecret),
                                                                                       AzureEnvironments.AzureCloudEnvironment);

                AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials);
                _context = new CloudMediaContext(new Uri(_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/

                StorageCredentials mediaServicesStorageCredentials = new StorageCredentials(_AMSstorageAccountName, _AMSstorageAccountKey);

                CopyBlobHelpers cbh = new CopyBlobHelpers(_context, _AMSstorageAccountName, _AMSstorageAccountKey, null);

                IAsset newAsset = cbh.CreateAssetFromBlob(inputBlob, name, log).GetAwaiter().GetResult();
                log.Info("Deleting the source asset from the input container");
                inputBlob.DeleteIfExists();

                byte[] keyBytes = Convert.FromBase64String(_AMSNotificationWebHookKey);

                var endpoint = _context.NotificationEndPoints.Create("FunctionWebHook", NotificationEndPointType.WebHook, _AMSNotificationWebHookUri, keyBytes);

                IJob job = _context.Jobs.Create("Indexing: " + name);

                string          MediaProcessorName = "Azure Media Indexer"; // Get a reference to the Azure Media Indexer.
                IMediaProcessor processor          = GetLatestMediaProcessorByName(MediaProcessorName);

                string configuration = LoadConfiguration(log);

                ITask task = job.Tasks.AddNew("Audio Indexing Task",
                                              processor,
                                              configuration,
                                              TaskOptions.None);

                task.InputAssets.Add(newAsset);
                task.OutputAssets.AddNew("Output Asset", AssetCreationOptions.None);
                task.TaskNotificationSubscriptions.AddNew(NotificationJobState.All, endpoint, true);

                job.Submit();
                log.Info($"Indexer Job Submitted for '{name}'.");
            }
            catch (Exception ex)
            {
                log.Info("Exception: " + ex.Message);
            }
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            dynamic data;

            try
            {
                data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd());
            }
            catch (Exception ex)
            {
                return(IrdetoHelpers.ReturnErrorException(log, ex));
            }

            var assetName = (string)data.assetName;

            if (assetName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON"));
            }

            if (data.fileNames == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass fileNames in the input object"));
            }

            var sourceStorageAccountName = (string)data.sourceStorageAccountName;

            if (sourceStorageAccountName == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceStorageAccountName in the input object"));
            }

            var sourceStorageAccountKey = (string)data.sourceStorageAccountKey;

            if (sourceStorageAccountKey == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceStorageAccountKey in the input object"));
            }

            var sourceContainer = (string)data.sourceContainer;

            if (sourceContainer == null)
            {
                return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceContainer in the input object"));
            }

            bool missingBlob = false;

            List <string> containers     = new List <string>();
            List <string> containerPaths = new List <string>();

            // Azure region management
            var azureRegions = new List <string>();

            if ((string)data.azureRegion != null)
            {
                azureRegions = ((string)data.azureRegion).Split(',').ToList();
            }
            else
            {
                azureRegions.Add((string)null);
            }

            // Setup blob container
            CloudBlobContainer sourceBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(sourceStorageAccountName, sourceStorageAccountKey, (string)data.sourceContainer);

            foreach (var region in azureRegions)
            {
                ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder()
                                                         .SetBasePath(Directory.GetCurrentDirectory())
                                                         .AddEnvironmentVariables()
                                                         .Build(),
                                                         region
                                                         );

                MediaServicesHelpers.LogInformation(log, "config loaded.", region);
                MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, region);

                var client = await MediaServicesHelpers.CreateMediaServicesClientAsync(config);

                // Set the polling interval for long running operations to 2 seconds.
                // The default value is 30 seconds for the .NET client SDK
                client.LongRunningOperationRetryTimeout = 2;

                MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region);

                try
                {
                    var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName);

                    // Access to container
                    ListContainerSasInput input = new ListContainerSasInput()
                    {
                        Permissions = AssetContainerPermission.ReadWrite,
                        ExpiryTime  = DateTime.Now.AddHours(6).ToUniversalTime()
                    };

                    var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime);

                    string uploadSasUrl             = responseListSas.AssetContainerSasUrls.First();
                    var    sasUri                   = new Uri(uploadSasUrl);
                    var    destinationBlobContainer = new CloudBlobContainer(sasUri);
                    containers.Add(asset.Container);


                    if (data.fileNames != null)
                    {
                        int indexFile = 1;
                        foreach (var file in data.fileNames)
                        {
                            string fileName = (string)file;

                            CloudBlob sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName);

                            if (data.wait != null && (bool)data.wait && (indexFile == 1))
                            {
                                for (int i = 1; i <= 3; i++) // let's wait 3 times 5 seconds (15 seconds)
                                {
                                    if (await sourceBlob.ExistsAsync())
                                    {
                                        break;
                                    }

                                    log.LogInformation("Waiting 5 s...");
                                    System.Threading.Thread.Sleep(5 * 1000);
                                    sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName);
                                }
                            }

                            if (await sourceBlob.ExistsAsync() && sourceBlob.Properties.Length > 0)
                            {
                                if (data.flattenPath != null && (bool)data.flattenPath)
                                {
                                    fileName = Path.GetFileName(fileName);
                                }

                                CloudBlob destinationBlob = destinationBlobContainer.GetBlockBlobReference(fileName);

                                CopyBlobHelpers.CopyBlobAsync(sourceBlob, destinationBlob);
                            }
                            else
                            {
                                missingBlob = true;
                                log.LogWarning("Missing blob :" + fileName);
                            }
                            indexFile++;
                        }
                    }
                    containers.Add(asset.Container);
                }
                catch (Exception ex)
                {
                    return(IrdetoHelpers.ReturnErrorException(log, ex));
                }
            }

            var response = new JObject
            {
                { "success", true },
                { "assetName", assetName },
                { "container", new JArray(containers) },
                { "missingBlob", missingBlob },
                {
                    "operationsVersion",
                    AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString()
                }
            };

            return(new OkObjectResult(
                       response
                       ));
        }