private void DisplayAssetInfo(bool input) { string assetName = null; if (input) { if (MyJob.Input.GetType() == typeof(JobInputAsset)) { JobInputAsset inputAsset = MyJob.Input as JobInputAsset; assetName = inputAsset.AssetName; } } else // output { int index = listBoxOutputs.SelectedIndices[0]; if (MyJob.Outputs[index].GetType() == typeof(JobOutputAsset)) { JobOutputAsset outputAsset = MyJob.Outputs[index] as JobOutputAsset; assetName = outputAsset.AssetName; } } if (assetName != null) { _amsClient.RefreshTokenIfNeeded(); Asset asset = Task.Run(() => _amsClient.AMSclient.Assets.GetAsync(_amsClient.credentialsEntry.ResourceGroup, _amsClient.credentialsEntry.AccountName, assetName)) .GetAwaiter().GetResult(); using (AssetInformation form = new AssetInformation(_mainform, _amsClient) { myAsset = asset, myStreamingEndpoints = MyStreamingEndpoints // we want to keep the same sorting }) { DialogResult dialogResult = form.ShowDialog(this); } } }
public void JobComboTest() { using (MockContext context = this.StartMockContextAndInitializeClients(this.GetType())) { try { string transformName = TestUtilities.GenerateName("transform"); string transformDescription = "A test transform"; string jobName = TestUtilities.GenerateName("job"); string outputAssetName = TestUtilities.GenerateName("outputAsset"); CreateMediaServicesAccount(); // Create a transform as it is the parent of Jobs TransformOutput[] outputs = new TransformOutput[] { new TransformOutput(new BuiltInStandardEncoderPreset(EncoderNamedPreset.AdaptiveStreaming)) }; Transform transform = MediaClient.Transforms.CreateOrUpdate(ResourceGroup, AccountName, transformName, outputs, transformDescription); // List jobs, which should be empty var jobs = MediaClient.Jobs.List(ResourceGroup, AccountName, transformName); Assert.Empty(jobs); // Try to get the job, which should not exist Job job = MediaClient.Jobs.Get(ResourceGroup, AccountName, transformName, jobName); Assert.Null(job); // Create a job using an input from an HTTP url and an output to an Asset Asset outputAsset = MediaClient.Assets.CreateOrUpdate(ResourceGroup, AccountName, outputAssetName, new Asset()); JobInputHttp jobInputHttp = new JobInputHttp(files: new string[] { "https://amssamples.streaming.mediaservices.windows.net/2e91931e-0d29-482b-a42b-9aadc93eb825/AzurePromo.mp4" }); JobInputs jobInputs = new JobInputs(inputs: new JobInput[] { jobInputHttp }); JobOutputAsset jobOutput = new JobOutputAsset(outputAssetName); JobOutput[] jobOutputs = new JobOutput[] { jobOutput }; Job input = new Job(jobInputs, jobOutputs); Job createdJob = MediaClient.Jobs.Create(ResourceGroup, AccountName, transformName, jobName, input); ValidateJob(createdJob, jobName, null, jobInputs, jobOutputs); // List jobs and validate the created job shows up jobs = MediaClient.Jobs.List(ResourceGroup, AccountName, transformName); Assert.Single(jobs); ValidateJob(jobs.First(), jobName, null, jobInputs, jobOutputs); // Get the newly created job job = MediaClient.Jobs.Get(ResourceGroup, AccountName, transformName, jobName); Assert.NotNull(job); ValidateJob(job, jobName, null, jobInputs, jobOutputs); // If the job isn't already finished, cancel it if (job.State != JobState.Finished) { MediaClient.Jobs.CancelJob(ResourceGroup, AccountName, transformName, jobName); do { System.Threading.Thread.Sleep(15 * 1000); job = MediaClient.Jobs.Get(ResourceGroup, AccountName, transformName, jobName); }while (job.State != JobState.Finished && job.State != JobState.Canceled); } // Delete the job MediaClient.Jobs.Delete(ResourceGroup, AccountName, transformName, jobName); // List jobs, which should be empty again jobs = MediaClient.Jobs.List(ResourceGroup, AccountName, transformName); Assert.Empty(jobs); // Try to get the job, which should not exist job = MediaClient.Jobs.Get(ResourceGroup, AccountName, transformName, jobName); Assert.Null(job); // Delete the transform MediaClient.Transforms.Delete(ResourceGroup, AccountName, transformName); } finally { DeleteMediaServicesAccount(); } } }
/// <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 Authentication.CreateMediaServicesClientAsync(config, UseInteractiveAuth); } catch (Exception e) { Console.Error.WriteLine("TIP: Make sure that you have filled out the appsettings.json or .env 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 an AudioAnalyzer preset with audio insights and Basic audio mode. Preset preset = new AudioAnalyzerPreset( audioLanguage: "en-US", // // There are two modes available, Basic and Standard // Basic : This mode performs speech-to-text transcription and generation of a VTT subtitle/caption file. // The output of this mode includes an Insights JSON file including only the keywords, transcription,and timing information. // Automatic language detection and speaker diarization are not included in this mode. // Standard : Performs all operations included in the Basic mode, additionally performing language detection and speaker diarization. // mode: AudioAnalysisMode.Standard ); // 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 audioAnalyzerTransform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, AudioAnalyzerTransformName, preset); // Create a new input Asset and upload the specified local media 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); // Use a preset override to change the language or mode on the Job level. // Above we created a Transform with a preset that was set to a specific audio language and mode. // If we want to change that language or mode before submitting the job, we can modify it using the PresetOverride property // on the JobOutput. #region PresetOverride // First we re-define the preset that we want to use for this specific Job... var presetOverride = new AudioAnalyzerPreset { AudioLanguage = "en-US", Mode = AudioAnalysisMode.Basic /// Switch this job to use Basic mode instead of standard }; // Then we use the PresetOverride property of the JobOutput to pass in the override values to use on this single Job // without the need to create a completely separate and new Transform with another langauge code or Mode setting. // This can save a lot of complexity in your AMS account and reduce the number of Transforms used. JobOutput jobOutput = new JobOutputAsset() { AssetName = outputAsset.Name, PresetOverride = presetOverride }; Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, AudioAnalyzerTransformName, jobName, inputAssetName, jobOutput); #endregion PresetOverride // In this sample, we use Event Grid to listen to the notifications through an Azure Event Hub. // If you do not provide an Event Hub config in the settings, the sample will fall back to polling the job for status. // For production ready code, it is always recommended to use Event Grid instead of polling on the Job status. EventProcessorClient processorClient = null; BlobContainerClient storageClient = null; MediaServicesEventProcessor mediaEventProcessor = 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. // A storage account is required to process the Event Hub events from the Event Grid subscription in this sample. // Create a new host to process events from an Event Hub. Console.WriteLine("Creating a new client to process events from an Event Hub..."); var credential = new DefaultAzureCredential(); var storageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", config.StorageAccountName, config.StorageAccountKey); var blobContainerName = config.StorageContainerName; var eventHubsConnectionString = config.EventHubConnectionString; var eventHubName = config.EventHubName; var consumerGroup = config.EventHubConsumerGroup; storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); processorClient = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName); // 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(false); // 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 cancellationSource = new CancellationTokenSource(); var timeout = Task.Delay(30 * 60 * 1000, cancellationSource.Token); tasks.Add(timeout); mediaEventProcessor = new MediaServicesEventProcessor(jobName, jobWaitingEvent, null); processorClient.ProcessEventAsync += mediaEventProcessor.ProcessEventsAsync; processorClient.ProcessErrorAsync += mediaEventProcessor.ProcessErrorAsync; await processorClient.StartProcessingAsync(cancellationSource.Token); // Wait for tasks. if (await Task.WhenAny(tasks) == jobTask) { // Job finished. Cancel the timer. cancellationSource.Cancel(); // Get the latest status of the job. job = await client.Jobs.GetAsync(config.ResourceGroup, config.AccountName, AudioAnalyzerTransformName, jobName); } else { // Timeout happened, Something might be wrong with job events. Fall-back on polling instead. jobWaitingEvent.Set(); throw new Exception("Timeout occurred."); } } catch (Exception e) { Console.WriteLine("Warning: Failed to connect to Event Hub, please refer README for Event Hub and storage settings."); Console.WriteLine(e.Message); // 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 and listen for the status events on the jobs Console.WriteLine("Polling job status..."); job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AudioAnalyzerTransformName, jobName); } finally { if (processorClient != null) { Console.WriteLine("Job final state received, Stopping the event processor..."); await processorClient.StopProcessingAsync(); Console.WriteLine(); // It is encouraged that you unregister your handlers when you have // finished using the Event Processor to ensure proper cleanup. This // is especially important when using lambda expressions or handlers // in any form that may contain closure scopes or hold other references. processorClient.ProcessEventAsync -= mediaEventProcessor.ProcessEventsAsync; processorClient.ProcessErrorAsync -= mediaEventProcessor.ProcessErrorAsync; } } 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, AudioAnalyzerTransformName, inputAssetName, outputAssetName, jobName); }