/// <summary> /// Run the sample async. /// </summary> /// <param name="config">The param is of type ConfigWrapper. This class reads values from local configuration file.</param> /// <returns></returns> private static async Task RunAsync(ConfigWrapper config) { IAzureMediaServicesClient client; try { client = await CreateMediaServicesClientAsync(config); } catch (Exception e) { Console.Error.WriteLine("TIP: Make sure that you have filled out the appsettings.json file before running this sample."); Console.Error.WriteLine($"{e.Message}"); return; } // 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; // Creating a unique suffix so that we don't have name collisions if you run the sample // multiple times without cleaning up. string uniqueness = Guid.NewGuid().ToString("N"); string jobName = $"job-{uniqueness}"; string outputAssetName = $"output-{uniqueness}"; string inputAssetName = $"input-{uniqueness}"; // Create a video analyzer preset with video insights. Preset preset = new VideoAnalyzerPreset(null, InsightsType.VideoInsightsOnly); // Ensure that you have the desired encoding Transform. This is really a one time setup operation. // Once it is created, we won't delete it. Transform videoAnalyzerTransform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, preset); // Create a new input Asset and upload the specified local video file into it. await CreateInputAssetAsync(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName); // Output from the encoding Job must be written to an Asset, so let's create one Asset outputAsset = await CreateOutputAssetAsync(client, config.ResourceGroup, config.AccountName, outputAssetName); Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName, inputAssetName, outputAsset.Name); EventProcessorHost eventProcessorHost = null; try { // First we will try to process Job events through Event Hub in real-time. If this fails for any reason, // we will fall-back on polling Job status instead. // Please refer README for Event Hub and storage settings. string storageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", config.StorageAccountName, config.StorageAccountKey); // Create a new host to process events from an Event Hub. Console.WriteLine("Creating a new host to process events from an Event Hub..."); eventProcessorHost = new EventProcessorHost(config.EventHubName, PartitionReceiver.DefaultConsumerGroupName, config.EventHubConnectionString, storageConnectionString, config.StorageContainerName); // Create an AutoResetEvent to wait for the job to finish and pass it to EventProcessor so that it can be set when a final state event is received. AutoResetEvent jobWaitingEvent = new AutoResetEvent(false); // Registers the Event Processor Host and starts receiving messages. Pass in jobWaitingEvent so it can be called back. await eventProcessorHost.RegisterEventProcessorFactoryAsync(new MediaServicesEventProcessorFactory(jobName, jobWaitingEvent), EventProcessorOptions.DefaultOptions); // Create a Task list, adding a job waiting task and a timer task. Other tasks can be added too. IList <Task> tasks = new List <Task>(); // Add a task to wait for the job to finish. The AutoResetEvent will be set when a final state is received by EventProcessor. Task jobTask = Task.Run(() => jobWaitingEvent.WaitOne()); tasks.Add(jobTask); // 30 minutes timeout. var tokenSource = new CancellationTokenSource(); var timeout = Task.Delay(30 * 60 * 1000, tokenSource.Token); tasks.Add(timeout); // Wait for tasks. if (await Task.WhenAny(tasks) == jobTask) { // Job finished. Cancel the timer. tokenSource.Cancel(); // Get the latest status of the job. job = await client.Jobs.GetAsync(config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName); } else { // Timeout happened, Something might be wrong with job events. Fall-back on polling instead. jobWaitingEvent.Set(); throw new Exception("Timeout happened."); } } catch (Exception) { Console.WriteLine("Warning: Failed to connect to Event Hub, please refer README for Event Hub and storage settings."); // Polling is not a recommended best practice for production applications because of the latency it introduces. // Overuse of this API may trigger throttling. Developers should instead use Event Grid. Console.WriteLine("Polling job status..."); job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName); } finally { if (eventProcessorHost != null) { Console.WriteLine("Job final state received, unregistering event processor..."); // Disposes of the Event Processor Host. await eventProcessorHost.UnregisterEventProcessorAsync(); Console.WriteLine(); } } if (job.State == JobState.Finished) { Console.WriteLine("Job finished."); if (!Directory.Exists(OutputFolderName)) { Directory.CreateDirectory(OutputFolderName); } await DownloadOutputAssetAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, OutputFolderName); } await CleanUpAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, inputAssetName, outputAssetName, jobName); }
/// <summary> /// Creates the AzureMediaServicesClient object based on the credentials /// supplied in local configuration file. /// </summary> /// <param name="config">The param is of type ConfigWrapper. This class reads values from local configuration file.</param> /// <returns></returns> private static async Task <IAzureMediaServicesClient> CreateMediaServicesClientAsync(ConfigWrapper config) { var credentials = await GetCredentialsAsync(config); return(new AzureMediaServicesClient(config.ArmEndpoint, credentials) { SubscriptionId = config.SubscriptionId, }); }