/// <summary>
        /// Submits a request to Media Services to apply the specified Transform to a given input video.
        /// </summary>
        /// <param name="client">The Media Services client.</param>
        /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
        /// <param name="accountName"> The Media Services account name.</param>
        /// <param name="transformName">The name of the transform.</param>
        /// <param name="jobName">The (unique) name of the job.</param>
        /// <param name="inputAssetName"></param>
        /// <param name="outputAssetName">The (unique) name of the  output asset that will store the result of the encoding job. </param>
        // <SubmitJob>
        private static async Task <Job> SubmitJobAsync(IAzureMediaServicesClient client,
                                                       string resourceGroupName,
                                                       string accountName,
                                                       string transformName,
                                                       string jobName,
                                                       string inputAssetName,
                                                       JobOutput jobOutput)
        {
            JobInput jobInput = new JobInputAsset(assetName: inputAssetName);

            JobOutput[] jobOutputs =
            {
                jobOutput
            };

            // In this example, we are assuming that the job name is unique.
            //
            // If you already have a job with the desired name, use the Jobs.Get method
            // to get the existing job. In Media Services v3, Get methods on entities returns ErrorResponseException
            // if the entity doesn't exist (a case-insensitive check on the name).
            Job job;

            try
            {
                job = await client.Jobs.CreateAsync(
                    resourceGroupName,
                    accountName,
                    transformName,
                    jobName,
                    new Job
                {
                    Input   = jobInput,
                    Outputs = jobOutputs,
                });
            }
            catch (Exception exception)
            {
                if (exception.GetBaseException() is ErrorResponseException apiException)
                {
                    Console.Error.WriteLine(
                        $"ERROR: API call failed with error code '{apiException.Body.Error.Code}' and message '{apiException.Body.Error.Message}'.");
                }
                throw;
            }

            return(job);
        }
Beispiel #2
0
        static void Main(string[] args)
        {
            ConfigWrapper config = new ConfigWrapper();

            try{
                IAzureMediaServicesClient client = CreateMediaServicesClient(config);

                Transform videoAnalyzerTransform = EnsureTransformExists(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, new VideoAnalyzerPreset("en-US"));

                // 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().Substring(0, 13);

                string jobName         = "job-" + uniqueness;
                string outputAssetName = "output-" + uniqueness;
                string inputAssetName  = "input-" + uniqueness;


                CreateInputAsset(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName);
                JobInput jobInput = new JobInputAsset(assetName: inputAssetName);

                Asset outputAsset = client.Assets.CreateOrUpdate(config.ResourceGroup, config.AccountName, outputAssetName, new Asset());

                Job job = SubmitJob(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName, jobInput, outputAssetName);

                job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName);

                if (job.State == JobState.Finished)
                {
                    Console.WriteLine("Job finished.");
                    if (!Directory.Exists(OutputFolder))
                    {
                        Directory.CreateDirectory(OutputFolder);
                    }

                    DownloadResults(client, config.ResourceGroup, config.AccountName, outputAssetName, OutputFolder);
                }
            }
            catch (ApiErrorException ex)
            {
                Console.WriteLine("{0}", ex.Message);

                Console.WriteLine("Code: {0}", ex.Body.Error.Code);
                Console.WriteLine("Message: {0}", ex.Body.Error.Message);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Indexer のタスクを非同期で実行する。
        /// </summary>
        /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        // <RunAsync>
        private static async Task RunAsync(ConfigWrapper config, Stream myBlob)
        {
            IAzureMediaServicesClient client = await CreateMediaServicesClientAsync(config);

            // AMS の Task の完了をポーリングする間隔を設定
            // デフォルト値は 30 秒
            client.LongRunningOperationRetryTimeout = 2;

            // 複数回実行してもエラーにならないようにユニークな suffix を生成
            // ここは実際にはユーザーの入力など、コントローラブルな変数にしても良い
            string uniqueness      = Guid.NewGuid().ToString("N");
            string jobName         = $"job-{uniqueness}";
            string outputAssetName = $"output-{uniqueness}";
            string inputAssetName  = $"input-{uniqueness}";

            // Ensure that you have the desired Transform. This is really a one time setup operation.
            //
            // In this Transform, we specify to use the VideoAnalyzerPreset preset.
            // This preset enables you to extract multiple audio and video insights from a video.
            // In the example, the language ("en-US") is passed to its constructor.
            // You can also specify what insights you want to extract by passing InsightsToExtract to the constructor.
            Transform videoAnalyzerTransform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, new VideoAnalyzerPreset("ja-JP"));

            // Create a new input Asset and upload the specified local video file into it.
            await CreateInputAssetAsync(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName, myBlob);

            // Use the name of the created input asset to create the job input.
            JobInput jobInput = new JobInputAsset(assetName: inputAssetName);

            // 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, jobInput, outputAsset.Name);

            // In this demo code, we will poll for Job status
            // 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.
            job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName);

            if (job.State == JobState.Finished)
            {
                Console.WriteLine("Job finished.");
            }

            Console.WriteLine("Indexing Done.");
        }
Beispiel #4
0
        private static async Task <Job> SubmitJobAsync(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string transformName, string jobName, string inputAssetName, string outputAssetName)
        {
            JobInput jobInput = new JobInputAsset(assetName: inputAssetName);

            JobOutput[] jobOutputs =
            {
                new JobOutputAsset(outputAssetName),
            };

            Job job = await client.Jobs.CreateAsync(resourceGroupName, accountName, transformName, jobName,
                                                    new Job
            {
                Input   = jobInput,
                Outputs = jobOutputs,
            });

            return(job);
        }
Beispiel #5
0
        /// <inheritdoc/>
        /// <param name="endTime">Mark Out of the encode.  If null or empty, will end at, well the end.</param>
        public async Task CreateJobAsync(string transformName, string inputAssetName, string ouputAssetName, string jobName, TimeBasedEncodeDTO timeBasedEncodeInfo, IDictionary <string, string> correlationData, JObject operationContext)
        {
            await ConnectAsync().ConfigureAwait(false);

            CheckArgumentNotNullOrEmpty(transformName, nameof(transformName));
            CheckArgumentNotNullOrEmpty(inputAssetName, nameof(inputAssetName));
            CheckArgumentNotNullOrEmpty(ouputAssetName, nameof(ouputAssetName));
            CheckArgumentNotNullOrEmpty(jobName, nameof(jobName));

            // let's build the input and output objects
            var jobInput   = new JobInputAsset(inputAssetName);
            var jobOutputs = new[] { new JobOutputAsset(ouputAssetName) };

            // process mark in and mark out if provided, null otherwise.
            if (!(timeBasedEncodeInfo is null))
            {
                if (timeBasedEncodeInfo.StartSeconds < 0)
                {
                    throw new GridwichTimeParameterException(nameof(timeBasedEncodeInfo.StartSeconds), timeBasedEncodeInfo.StartSeconds, "Must be above zero.");
                }

                jobInput.Start = new AbsoluteClipTime(TimeSpan.FromSeconds(timeBasedEncodeInfo.StartSeconds));

                if (timeBasedEncodeInfo.EndSeconds < 0)
                {
                    throw new GridwichTimeParameterException(nameof(timeBasedEncodeInfo.EndSeconds), timeBasedEncodeInfo.EndSeconds, "Must be above zero.");
                }

                jobInput.End = new AbsoluteClipTime(TimeSpan.FromSeconds(timeBasedEncodeInfo.EndSeconds));
            }

            // Submit the job:
            _ = await this.MediaServicesV3SdkWrapper.JobCreateAsync(
                transformName : transformName,
                jobName : jobName,
                parameters : new Job
            {
                Input           = jobInput,
                Outputs         = jobOutputs,
                CorrelationData = correlationData,
            }).ConfigureAwait(false);
        }
Beispiel #6
0
        private async void listBoxInput_SelectedIndexChanged(object sender, EventArgs e)
        {
            dataGridInput.Rows.Clear();

            if (MyJob.Input.GetType() == typeof(JobInputAsset))
            {
                JobInputAsset inputA = MyJob.Input as JobInputAsset;
                dataGridInput.Rows.Add("Input type", "asset");
                dataGridInput.Rows.Add("Asset name", inputA.AssetName);
                dataGridInput.Rows.Add("Asset type", (await AssetInfo.GetAssetTypeAsync(inputA.AssetName, _amsClient))?.Type);
                if (inputA.Start != null && inputA.Start.GetType() == typeof(AbsoluteClipTime))
                {
                    AbsoluteClipTime startA = inputA.Start as AbsoluteClipTime;
                    dataGridInput.Rows.Add("Absolute Clip Time Start", startA.Time.ToString());
                }
                if (inputA.End != null && inputA.End.GetType() == typeof(AbsoluteClipTime))
                {
                    AbsoluteClipTime endA = inputA.End as AbsoluteClipTime;
                    dataGridInput.Rows.Add("Absolute Clip Time End", endA.Time.ToString());
                }
                dataGridInput.Rows.Add("Label", inputA.Label);
                dataGridInput.Rows.Add("Files", string.Join(Constants.endline, inputA.Files));
            }
            else if (MyJob.Input.GetType() == typeof(JobInputHttp))
            {
                JobInputHttp inputH = MyJob.Input as JobInputHttp;
                dataGridInput.Rows.Add("Input type", "http");
                dataGridInput.Rows.Add("Base Url", inputH.BaseUri);
                if (inputH.Start != null && inputH.Start.GetType() == typeof(AbsoluteClipTime))
                {
                    AbsoluteClipTime startA = inputH.Start as AbsoluteClipTime;
                    dataGridInput.Rows.Add("Absolute Clip Time Start", startA.Time.ToString());
                }
                if (inputH.End != null && inputH.End.GetType() == typeof(AbsoluteClipTime))
                {
                    AbsoluteClipTime endA = inputH.End as AbsoluteClipTime;
                    dataGridInput.Rows.Add("Absolute Clip Time End", endA.Time.ToString());
                }
                dataGridInput.Rows.Add("Label", inputH.Label);
                dataGridInput.Rows.Add("Files", string.Join(Constants.endline, inputH.Files));
            }
        }
Beispiel #7
0
        private JobInput GetJobInput(MediaJob mediaJob)
        {
            JobInput jobInput;

            if (!string.IsNullOrEmpty(mediaJob.InputFileUrl))
            {
                jobInput = new JobInputHttp()
                {
                    Files = new string[] { mediaJob.InputFileUrl }
                };
            }
            else
            {
                jobInput = new JobInputAsset()
                {
                    AssetName = mediaJob.InputAssetName
                };
            }
            return(jobInput);
        }
Beispiel #8
0
        // </CreateMediaServicesClient>

        private static void Cleanup(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string transformName, string jobName, string outputAssetName, JobInput input, string streamingLocatorName, string contentKeyPolicyName)
        {
            client.Jobs.Delete(resourceGroupName, accountName, transformName, jobName);
            client.Assets.Delete(resourceGroupName, accountName, outputAssetName);

            JobInputAsset jobInputAsset = input as JobInputAsset;

            if (jobInputAsset != null)
            {
                client.Assets.Delete(resourceGroupName, accountName, jobInputAsset.AssetName);
            }

            // Delete the Streaming Locator
            client.StreamingLocators.Delete(resourceGroupName, accountName, streamingLocatorName);

            // Stop and delete the StreamingEndpoint - use this if you are creating a custom (non default) endpoint
            //client.StreamingEndpoints.Stop(resourceGroupName, accountName, endpointName);
            //client.StreamingEndpoints.Delete(resourceGroupName, accountName, endpointName);

            client.ContentKeyPolicies.Delete(resourceGroupName, accountName, contentKeyPolicyName);
        }
Beispiel #9
0
        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)
                {
                    myAssetV3 = asset,
                    myStreamingEndpoints = MyStreamingEndpoints // we want to keep the same sorting
                })
                {
                    DialogResult dialogResult = form.ShowDialog(this);
                }
            }
        }
Beispiel #10
0
        public async Task <Job> SubmitJobAsync(IAzureMediaServicesClient client,
                                               string resourceGroupName,
                                               string accountName,
                                               string transformName,
                                               string jobName,
                                               string inputAssetName,
                                               string resultName)
        {
            // Use the name of the created input asset to create the job input.
            JobInput jobInput = new JobInputAsset(assetName: inputAssetName);

            JobOutput[] jobOutputs =
            {
                new JobOutputAsset(resultName),
            };

            Job job = await client.Jobs.GetAsync(resourceGroupName, accountName,
                                                 transformName, jobName);

            if (job != null)
            {
                await client.Jobs.DeleteAsync(resourceGroupName, accountName,
                                              transformName, jobName);

                // buat sinkronisasi
                await Task.Delay(3000);
            }
            job = await client.Jobs.CreateAsync(
                resourceGroupName,
                accountName,
                transformName,
                jobName,
                new Job
            {
                Input   = jobInput,
                Outputs = jobOutputs,
            });

            return(job);
        }
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        // <RunAsync>
        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 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}";

            // Ensure that you have the desired Transform. This is really a one time setup operation.
            //
            // In this Transform, we specify to use the VideoAnalyzerPreset preset.
            // This preset enables you to extract multiple audio and video insights from a video.
            // In the example, the language ("en-US") is passed to its constructor.
            // You can also specify what insights you want to extract by passing InsightsToExtract to the constructor, and which audio mode (standard or basic).
            _ = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, new VideoAnalyzerPreset("en-US"));

            // Create a new input Asset and upload the specified local video file into it.
            await CreateInputAssetAsync(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName);

            // Use the name of the created input asset to create the job input.
            JobInput jobInput = new JobInputAsset(assetName: inputAssetName);

            // 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);

            _ = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName, jobInput, outputAsset.Name);

            // In this demo code, we will poll for Job status
            // 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.
            Job job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName);

            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);
            }

            Console.WriteLine("Done.");
            Console.WriteLine("When finished press enter to cleanup.");
            Console.Out.Flush();
            Console.ReadLine();
            Console.WriteLine("Cleaning up...");
            await CleanUpAsync(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, job.Name, new List <string> {
                outputAsset.Name
            }, null);
        }
Beispiel #12
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request.");

            string  requestBody = new StreamReader(req.Body).ReadToEnd();
            dynamic data        = JsonConvert.DeserializeObject(requestBody);

            // Validate input objects
            if (data.inputAssetName == null)
            {
                return(new BadRequestObjectResult("Please pass inputAssetName in the input object"));
            }
            if (data.transformName == null)
            {
                return(new BadRequestObjectResult("Please pass transformName in the input object"));
            }
            if (data.outputAssetNamePrefix == null)
            {
                return(new BadRequestObjectResult("Please pass outputAssetNamePrefix in the input object"));
            }
            string inputAssetName        = data.inputAssetName;
            string transformName         = data.transformName;
            string outputAssetNamePrefix = data.outputAssetNamePrefix;
            string assetStorageAccount   = null;

            if (data.assetStorageAccount != null)
            {
                assetStorageAccount = data.assetStorageAccount;
            }

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

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

            Asset inputAsset = null;

            string guid    = Guid.NewGuid().ToString();
            string jobName = "amsv3function-job-" + guid;
            string encoderOutputAssetName       = null;
            string audioAnalyzerOutputAssetName = null;
            string videoAnalyzerOutputAssetName = null;
            JArray outputs = new JArray();

            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;

                try
                {
                    inputAsset = client.Assets.Get(config.ResourceGroup, config.AccountName, inputAssetName);
                    if (inputAsset == null)
                    {
                        return(new BadRequestObjectResult("Asset for input not found"));
                    }
                    Transform transform = client.Transforms.Get(config.ResourceGroup, config.AccountName, transformName);
                    if (transform == null)
                    {
                        return(new BadRequestObjectResult("Transform not found"));
                    }

                    var jobOutputList = new List <JobOutput>();
                    for (int i = 0; i < transform.Outputs.Count; i++)
                    {
                        Guid   assetGuid       = Guid.NewGuid();
                        string outputAssetName = outputAssetNamePrefix + "-" + assetGuid.ToString();
                        Asset  assetParams     = new Asset(null, outputAssetName, null, assetGuid, DateTime.Now, DateTime.Now, null, outputAssetName, null, assetStorageAccount, AssetStorageEncryptionFormat.None);
                        Asset  outputAsset     = client.Assets.CreateOrUpdate(config.ResourceGroup, config.AccountName, outputAssetName, assetParams);
                        jobOutputList.Add(new JobOutputAsset(outputAssetName));

                        Preset preset = transform.Outputs[i].Preset;
                        if (encoderOutputAssetName == null && (preset is BuiltInStandardEncoderPreset || preset is StandardEncoderPreset))
                        {
                            encoderOutputAssetName = outputAssetName;
                        }
                        if (audioAnalyzerOutputAssetName == null && preset is AudioAnalyzerPreset)
                        {
                            audioAnalyzerOutputAssetName = outputAssetName;
                        }
                        if (videoAnalyzerOutputAssetName == null && preset is VideoAnalyzerPreset)
                        {
                            videoAnalyzerOutputAssetName = outputAssetName;
                        }

                        // set up jobOutputs
                        JObject outObject = new JObject();
                        outObject["Preset"]          = preset.ToString().Split('.').Last <string>();
                        outObject["OutputAssetName"] = outputAssetName;
                        if (preset is BuiltInStandardEncoderPreset || preset is StandardEncoderPreset)
                        {
                            outObject["Category"] = "Encoder";
                        }
                        else if (preset is AudioAnalyzerPreset || preset is VideoAnalyzerPreset)
                        {
                            outObject["Category"] = "Analyzer";
                        }
                        else
                        {
                            outObject["Category"] = "Unknown";
                        }
                        outputs.Add(outObject);
                    }

                    // Use the name of the created input asset to create the job input.
                    JobInput    jobInput   = new JobInputAsset(assetName: inputAssetName);
                    JobOutput[] jobOutputs = jobOutputList.ToArray();
                    Job         job        = client.Jobs.Create(
                        config.ResourceGroup,
                        config.AccountName,
                        transformName,
                        jobName,
                        new Job
                    {
                        Input   = jobInput,
                        Outputs = jobOutputs,
                    }
                        );
                }
                catch (ApiErrorException e)
                {
                    log.LogError($"ERROR: AMS API call failed with error code: {e.Body.Error.Code} and message: {e.Body.Error.Message}");
                    return(new BadRequestObjectResult("AMS API call error: " + e.Message + "\nError Code: " + e.Body.Error.Code + "\nMessage: " + e.Body.Error.Message));
                }
                catch (Exception e)
                {
                    log.LogError($"ERROR: Exception with message: {e.Message}");
                    return(new BadRequestObjectResult("Error: " + e.Message));
                }
            }


            JObject result = new JObject();

            result["jobName"]                      = jobName;
            result["jobOutputs"]                   = outputs;
            result["encoderOutputAssetName"]       = encoderOutputAssetName;
            result["videoAnalyzerOutputAssetName"] = videoAnalyzerOutputAssetName;
            result["audioAnalyzerOutputAssetName"] = audioAnalyzerOutputAssetName;
            return((ActionResult) new OkObjectResult(result));
        }
Beispiel #13
0
        public async Task <TextModerationResult> ModerateVideo(string videoPath)
        {
            string resourceGroup = this.textModeratorConfig.ResourceGroup;
            string accountName   = this.textModeratorConfig.AccountName;

            IAzureMediaServicesClient client = await CreateMediaServicesClientAsync();

            // 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;
            TextModerationResult result = null;

            try
            {
                string uniqueness = Guid.NewGuid().ToString();
                string jobName    = JobNamePrefix + uniqueness;
                string streamingOutputAssetName = textModeratorConfig + uniqueness;
                string analyticsOutputAssetName = textModeratorConfig + uniqueness;

                JobInput     jobInput               = null;
                List <Asset> outputAssetList        = new List <Asset>();
                Transform    videoAnalyzerTransform = EnsureTransformExists(client, resourceGroup, accountName, VisualModerationTransformName);

                if (videoPath.StartsWith("http://") || videoPath.StartsWith("https://"))
                {
                    Uri    inputVideoUri = new Uri(videoPath);
                    string baseUri       = inputVideoUri.Scheme + "://" + inputVideoUri.Host;
                    for (int i = 0; i < inputVideoUri.Segments.Length - 1; i++)
                    {
                        baseUri = baseUri + inputVideoUri.Segments[i];
                    }
                    jobInput = new JobInputHttp(
                        baseUri: baseUri,
                        files: new List <String> {
                        inputVideoUri.Segments[inputVideoUri.Segments.Length - 1]
                    },
                        label: JobInputLabel
                        );
                }
                else
                {
                    string inputAssetName = InputAssetNamePrefix + uniqueness;
                    CreateInputAssetWithUploading(client, resourceGroup, accountName, inputAssetName, videoPath).Wait();
                    jobInput = new JobInputAsset(assetName: inputAssetName, label: JobInputLabel);
                }

                List <JobOutput> jobOutputList        = new List <JobOutput>();
                Asset            analyticsOutputAsset = CreateOutputAsset(client, resourceGroup, accountName, analyticsOutputAssetName);
                outputAssetList.Add(analyticsOutputAsset);
                jobOutputList.Add(new JobOutputAsset(assetName: analyticsOutputAsset.Name, label: JobAnalyticsOutputLabel));
                if (this.textModeratorConfig.EnableStreamingVideo)
                {
                    Asset streamingOutputAsset = CreateOutputAsset(client, resourceGroup, accountName, streamingOutputAssetName);
                    outputAssetList.Add(streamingOutputAsset);
                    jobOutputList.Add(new JobOutputAsset(assetName: streamingOutputAsset.Name, label: JobVideoOutputLabel));
                }

                JobOutput[] jobOutputs = jobOutputList.ToArray();
                Job         job        = SubmitJob(client, resourceGroup, accountName, videoAnalyzerTransform.Name, jobName, jobInput, jobOutputs);
                job = WaitForJobToFinish(client, resourceGroup, accountName, videoAnalyzerTransform.Name, jobName);

                if (job.State == JobState.Finished)
                {
                    Console.WriteLine("\nAMSv3 Job finished.");
                    List <StreamingLocator> locators = PublishAssets(client, resourceGroup, accountName, jobOutputList);
                    result = CreateVisualModeratorResult(client, resourceGroup, accountName, videoPath, locators);

                    using (var webClient = new WebClient())
                    {
                        webClient.Encoding          = Encoding.UTF8;
                        result.VisualModerationJson = webClient.DownloadString(result.StreamingUrlDetails.ContentModerationJsonUrl);
                        result.OcrJson = webClient.DownloadString(result.StreamingUrlDetails.OcrJsonUrl);
                    }
                }
                else if (job.State == JobState.Error)
                {
                    Console.WriteLine($"ERROR: Job finished with error message: {job.Outputs[0].Error.Message}");
                    Console.WriteLine($"ERROR:                   error details: {job.Outputs[0].Error.Details[0].Message}");
                }
            }
            catch (ApiErrorException ex)
            {
                string code    = ex.Body.Error.Code;
                string message = ex.Body.Error.Message;

                Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}", code, message);
            }

            return(result);
        }
Beispiel #14
0
        public async Task <IEnumerable <string> > EncodeVideoForStreaming(string inputMp4FileName, string uniqueMediaName, string downloadResultAssetsOutputPath = null)
        {
            var client = await CreateMediaServicesClientAsync(_configuration);

            // 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.
            var jobName         = $"job-{uniqueMediaName}";
            var locatorName     = $"locator-{uniqueMediaName}";
            var outputAssetName = $"{uniqueMediaName}";
            var inputAssetName  = $"input-{uniqueMediaName}";

            var existingStreamingUrls = await GetExistingStreamingUrls(locatorName,
                                                                       _configuration.ResourceGroup,
                                                                       _configuration.AccountName,
                                                                       client);

            if (existingStreamingUrls?.Any() == true)
            {
                return(existingStreamingUrls);
            }

            // Ensure that you have the desired encoding Transform. This is really a one time setup operation.
            _ = await GetOrCreateTransformAsync(client, _configuration.ResourceGroup, _configuration.AccountName,
                                                AdaptiveStreamingTransformName);

            // Create a new input Asset and upload the specified local video file into it.
            _ = await CreateInputAssetAsync(client, _configuration.ResourceGroup, _configuration.AccountName, inputAssetName,
                                            inputMp4FileName);

            // Use the name of the created input asset to create the job input.
            _ = new JobInputAsset(inputAssetName);

            // Output from the encoding Job must be written to an Asset, so let's create one
            var outputAsset =
                await CreateOutputAssetAsync(client, _configuration.ResourceGroup, _configuration.AccountName, outputAssetName);

            _ = await SubmitJobAsync(client, _configuration.ResourceGroup, _configuration.AccountName, AdaptiveStreamingTransformName,
                                     jobName, inputAssetName, outputAsset.Name);

            // In this demo code, we will poll for Job status
            // 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.
            var job = await WaitForJobToFinishAsync(client, _configuration.ResourceGroup, _configuration.AccountName,
                                                    AdaptiveStreamingTransformName, jobName);

            if (job.State == JobState.Finished)
            {
                Console.WriteLine("Job finished. Cleaning up resources.");

                await CleanUpAsync(client,
                                   _configuration.ResourceGroup,
                                   _configuration.AccountName,
                                   AdaptiveStreamingTransformName,
                                   jobName,
                                   new List <string> {
                    inputAssetName
                });

                if (!string.IsNullOrWhiteSpace(downloadResultAssetsOutputPath))
                {
                    if (!Directory.Exists(downloadResultAssetsOutputPath))
                    {
                        Directory.CreateDirectory(downloadResultAssetsOutputPath);
                    }

                    await DownloadOutputAssetAsync(client,
                                                   _configuration.ResourceGroup,
                                                   _configuration.AccountName,
                                                   outputAsset.Name,
                                                   downloadResultAssetsOutputPath);
                }

                var locator = await CreateStreamingLocatorAsync(client,
                                                                _configuration.ResourceGroup,
                                                                _configuration.AccountName,
                                                                outputAsset.Name,
                                                                locatorName);

                // Note that the URLs returned by this method include a /manifest path followed by a (format=)
                // parameter that controls the type of manifest that is returned.
                // The /manifest(format=m3u8-aapl) will provide Apple HLS v4 manifest using MPEG TS segments.
                // The /manifest(format=mpd-time-csf) will provide MPEG DASH manifest.
                // And using just /manifest alone will return Microsoft Smooth Streaming format.
                // There are additional formats available that are not returned in this call, please check the documentation
                // on the dynamic packager for additional formats - see https://docs.microsoft.com/azure/media-services/latest/dynamic-packaging-overview
                var urls = await GetStreamingUrlsAsync(client, _configuration.ResourceGroup, _configuration.AccountName, locator.Name);

                return(urls);
            }

            throw new Exception($"Failed to upload video {inputAssetName}");
        }
Beispiel #15
0
        public async Task <VisualModerationResult> ModerateVideo(string videoPath)
        {
            string resourceGroup = this.visualModeratorConfig.ResourceGroup;
            string accountName   = this.visualModeratorConfig.AccountName;

            IAzureMediaServicesClient client = await CreateMediaServicesClientAsync();

            VisualModerationResult result = null;

            try
            {
                string uniqueness            = Guid.NewGuid().ToString();
                string jobName               = "job-" + uniqueness;
                string inputAssetName        = "asset-input-" + uniqueness;
                string outputAssetName1      = "asset-output-video-" + uniqueness;
                string outputAssetName2      = "asset-output-analysis-" + uniqueness;
                string streamingLocatorName1 = "streaminglocator-video-" + uniqueness;
                string streamingLocatorName2 = "streaminglocator-analysis-" + uniqueness;

                Transform videoAnalyzerTransform = EnsureTransformExists(client, resourceGroup, accountName, VisualModerationTransformName);

                CreateInputAsset(client, resourceGroup, accountName, inputAssetName, videoPath).Wait();
                Asset       outputAsset1 = CreateOutputAsset(client, resourceGroup, accountName, outputAssetName1);
                Asset       outputAsset2 = CreateOutputAsset(client, resourceGroup, accountName, outputAssetName2);
                JobInput    jobInput     = new JobInputAsset(assetName: inputAssetName);
                JobOutput[] jobOutputs   =
                {
                    new JobOutputAsset(outputAsset1.Name),
                    new JobOutputAsset(outputAsset2.Name),
                };

                Job job = SubmitJob(client, resourceGroup, accountName, VisualModerationTransformName, jobName, jobInput, jobOutputs);
                job = WaitForJobToFinish(client, resourceGroup, accountName, VisualModerationTransformName, jobName);

                if (job.State == JobState.Finished)
                {
                    Console.WriteLine("\nAMSv3 Job finished.");
                    PublishStreamingAsset(client, resourceGroup, accountName, outputAsset1.Name, streamingLocatorName1);
                    PublishDownloadAsset(client, resourceGroup, accountName, outputAsset2.Name, streamingLocatorName2);
                    result                     = CreateVisualModeratorResult(client, resourceGroup, accountName, streamingLocatorName1, streamingLocatorName2);
                    result.VideoName           = outputAssetName1;
                    result.VideoFilePath       = videoPath;
                    result.AccessToken         = null;
                    result.VisualModeratedJson = await GetVisualModerationJsonFile(client, resourceGroup, accountName, outputAsset2.Name);
                }
                else if (job.State == JobState.Error)
                {
                    Console.WriteLine($"ERROR: Job finished with error message: {job.Outputs[0].Error.Message}");
                    Console.WriteLine($"ERROR:                   error details: {job.Outputs[0].Error.Details[0].Message}");
                }
            }
            catch (ApiErrorException ex)
            {
                string code    = ex.Body.Error.Code;
                string message = ex.Body.Error.Message;

                Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}", code, message);
            }

            return(result);
        }
Beispiel #16
0
        static void Main(string[] args)
        {
            ConfigWrapper config = new ConfigWrapper();

            try{
                IAzureMediaServicesClient client = CreateMediaServicesClient(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;

                // 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().Substring(0, 13);

                string jobName         = "job-" + uniqueness;
                string outputAssetName = "output-" + uniqueness;
                string inputAssetName  = "input-" + uniqueness;

                // Ensure that you have the desired encoding Transform. This is really a one time setup operation.
                Transform videoAnalyzerTransform = EnsureTransformExists(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, new VideoAnalyzerPreset("en-US"));

                // Create a new input Asset and upload the specified local video file into it.
                CreateInputAsset(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName);

                // Use the name of the created input asset to create the job input.
                JobInput jobInput = new JobInputAsset(assetName: inputAssetName);

                // Output from the encoding Job must be written to an Asset, so let's create one
                Asset outputAsset = CreateOutputAsset(client, config.ResourceGroup, config.AccountName, outputAssetName);

                Job job = SubmitJob(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName, jobInput, outputAssetName);

                // In this demo code, we will poll for Job status
                // 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.
                job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName);

                if (job.State == JobState.Finished)
                {
                    Console.WriteLine("Job finished.");
                    if (!Directory.Exists(OutputFolder))
                    {
                        Directory.CreateDirectory(OutputFolder);
                    }

                    DownloadResults(client, config.ResourceGroup, config.AccountName, outputAssetName, OutputFolder);
                }

                Console.WriteLine("Done.");
                Console.WriteLine("Press Enter to Continue");
                Console.ReadLine();
            }
            catch (ApiErrorException ex)
            {
                Console.WriteLine("{0}", ex.Message);

                Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}",
                                  ex.Body.Error.Code, ex.Body.Error.Message);
            }
        }
Beispiel #17
0
        public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log)
        {
            log.Info($"AMS v3 Function - submit_job was triggered!");

            string jsonContent = await req.Content.ReadAsStringAsync();

            dynamic data = JsonConvert.DeserializeObject(jsonContent);

            // Validate input objects
            if (data.inputAssetName == null)
            {
                return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass inputAssetName in the input object" }));
            }
            if (data.transformName == null)
            {
                return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass transformName in the input object" }));
            }
            if (data.outputAssetNamePrefix == null)
            {
                return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass outputAssetNamePrefix in the input object" }));
            }
            string inputAssetName        = data.inputAssetName;
            string transformName         = data.transformName;
            string outputAssetNamePrefix = data.outputAssetNamePrefix;
            string assetStorageAccount   = null;

            if (data.assetStorageAccount != null)
            {
                assetStorageAccount = data.assetStorageAccount;
            }

            MediaServicesConfigWrapper amsconfig = new MediaServicesConfigWrapper();
            Asset inputAsset = null;

            string guid    = Guid.NewGuid().ToString();
            string jobName = "amsv3function-job-" + guid;
            string encoderOutputAssetName       = null;
            string videoAnalyzerOutputAssetName = null;
            string outputContainer = null;

            try
            {
                var containerName = inputAssetName;
                containerName = containerName.Replace("asset", "saida");

                IAzureMediaServicesClient client = CreateMediaServicesClient(amsconfig);

                inputAsset = client.Assets.Get(amsconfig.ResourceGroup, amsconfig.AccountName, inputAssetName);
                if (inputAsset == null)
                {
                    return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Asset for input not found" }));
                }
                Transform transform = client.Transforms.Get(amsconfig.ResourceGroup, amsconfig.AccountName, transformName);
                if (transform == null)
                {
                    return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Transform not found" }));
                }

                var jobOutputList = new List <JobOutput>();
                for (int i = 0; i < transform.Outputs.Count; i++)
                {
                    Guid   assetGuid       = Guid.NewGuid();
                    string outputAssetName = outputAssetNamePrefix + "-" + assetGuid.ToString();
                    Preset p = transform.Outputs[i].Preset;
                    if (p is BuiltInStandardEncoderPreset || p is StandardEncoderPreset)
                    {
                        encoderOutputAssetName = outputAssetName;
                    }
                    else if (p is VideoAnalyzerPreset)
                    {
                        videoAnalyzerOutputAssetName = outputAssetName;
                    }

                    Asset assetParams = new Asset(null, outputAssetName, null, assetGuid, DateTime.Now, DateTime.Now, null, outputAssetName, containerName, assetStorageAccount, AssetStorageEncryptionFormat.None);
                    Asset outputAsset = client.Assets.CreateOrUpdate(amsconfig.ResourceGroup, amsconfig.AccountName, outputAssetName, assetParams);
                    jobOutputList.Add(new JobOutputAsset(outputAssetName));

                    if (outputContainer != null)
                    {
                        outputContainer += containerName + ",";
                    }

                    outputContainer += containerName;
                }

                // Use the name of the created input asset to create the job input.
                JobInput    jobInput   = new JobInputAsset(assetName: inputAssetName);
                JobOutput[] jobOutputs = jobOutputList.ToArray();
                Job         job        = client.Jobs.Create(
                    amsconfig.ResourceGroup,
                    amsconfig.AccountName,
                    transformName,
                    jobName,
                    new Job
                {
                    Input   = jobInput,
                    Outputs = jobOutputs,
                }
                    );
            }
            catch (ApiErrorException e)
            {
                log.Error("error", e);
                log.Info($"ERROR: AMS API call failed with error code: {e.Body.Error.Code} and message: {e.Body.Error.Message}");
                return(req.CreateResponse(HttpStatusCode.BadRequest, new
                {
                    error = "AMS API call error: " + e.Message
                }));
            }
            catch (Exception ex)
            {
                log.Error("error", ex);
            }


            return(req.CreateResponse(HttpStatusCode.OK, new
            {
                jobName = jobName,
                encoderOutputAssetName = encoderOutputAssetName,
                videoAnalyzerOutputAssetName = videoAnalyzerOutputAssetName,
                outputGuid = outputContainer
            }));
        }
Beispiel #18
0
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        // <RunAsync>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client = await 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;

            try
            {
                // Ensure that you have customized transforms for the VideoAnalyzer.  This is really a one time setup operation.
                Transform videoAnalyzerTransform = EnsureTransformExists(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, new VideoAnalyzerPreset());

                // 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().Substring(0, 13);
                string jobName         = "job-" + uniqueness;
                string inputAssetName  = "input-" + uniqueness;
                string outputAssetName = "output-" + uniqueness;

                CreateInputAsset(client, config.ResourceGroup, config.AccountName, inputAssetName, inputMP4FileName).Wait();

                JobInput input = new JobInputAsset(assetName: inputAssetName);

                Asset outputAsset = CreateOutputAsset(client, config.ResourceGroup, config.AccountName, outputAssetName);

                // Note that you can now pass custom correlation data Dictionary into the job to use via EventGrid or other Job polling listeners.
                // this is handy for passing tenant ID, or custom workflow data as part of your job.
                var correlationData = new Dictionary <string, string>();
                correlationData.Add("customData1", "some custom data to pass through the job");
                correlationData.Add("custom ID", "some GUID here");

                Job job = SubmitJob(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName, input, outputAsset.Name, correlationData);

                DateTime startedTime = DateTime.Now;

                job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName);

                TimeSpan elapsed = DateTime.Now - startedTime;

                if (job.State == JobState.Finished)
                {
                    Console.WriteLine("Job finished.");
                    if (!Directory.Exists(outputFolder))
                    {
                        Directory.CreateDirectory(outputFolder);
                    }
                    DownloadResults(client, config.ResourceGroup, config.AccountName, outputAsset.Name, outputFolder).Wait();
                }
                else if (job.State == JobState.Error)
                {
                    Console.WriteLine($"ERROR: Job finished with error message: {job.Outputs[0].Error.Message}");
                    Console.WriteLine($"ERROR:                   error details: {job.Outputs[0].Error.Details[0].Message}");
                }
            }
            catch (ApiErrorException ex)
            {
                string code    = ex.Body.Error.Code;
                string message = ex.Body.Error.Message;

                Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}", code, message);
            }
        }
        public static async Task <HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, FunctionContext executionContext)
        {
            var log = executionContext.GetLogger("SubmitSubclipJob");

            log.LogInformation("C# HTTP trigger function processed a request.");

            string triggerStart = DateTime.UtcNow.ToString("yyMMddHHmmss");

            // Get request body data.
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var    data        = (RequestBodyModel)JsonConvert.DeserializeObject(requestBody, typeof(RequestBodyModel));

            // Return bad request if input asset name is not passed in
            if (data.LiveEventName == null || data.LiveOutputName == null)
            {
                return(HttpRequest.ResponseBadRequest(req, "Please pass liveEventName and liveOutputName in the request body"));
            }

            data.IntervalSec ??= 60;

            ConfigWrapper config = ConfigUtils.GetConfig();

            IAzureMediaServicesClient client;

            try
            {
                client = await Authentication.CreateMediaServicesClientAsync(config);
            }
            catch (Exception e)
            {
                if (e.Source.Contains("ActiveDirectory"))
                {
                    log.LogError("TIP: Make sure that you have filled out the appsettings.json file before running this sample.");
                }
                log.LogError($"{e.Message}");

                return(HttpRequest.ResponseBadRequest(req, e.Message));
            }

            // 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;

            try
            {
                // Ensure that you have customized encoding Transform.  This is really a one time setup operation.
                Transform transform = await TransformUtils.GetOrCreateSubclipTransform(client, log, config.ResourceGroup, config.AccountName, SubclipTransformName);
            }
            catch (ErrorResponseException ex)
            {
                return(HttpRequest.ResponseBadRequest(req, LogUtils.LogError(log, ex, "Error when getting or creating the transform.")));
            }

            var liveOutput = await client.LiveOutputs.GetAsync(config.ResourceGroup, config.AccountName, data.LiveEventName, data.LiveOutputName);


            // let's analyze the client manifest and adjust times for the subclip job
            var doc = await LiveManifest.TryToGetClientManifestContentAsABlobAsync(client, config.ResourceGroup, config.AccountName, liveOutput.AssetName);

            var assetmanifestdata = LiveManifest.GetManifestTimingData(doc);

            if (assetmanifestdata.Error)
            {
                return(HttpRequest.ResponseBadRequest(req, "Data cannot be read from live output / asset manifest."));
            }

            log.LogInformation("Timestamps : " + string.Join(",", assetmanifestdata.TimestampList.Select(n => n.ToString()).ToArray()));

            var livetime = TimeSpan.FromSeconds(assetmanifestdata.TimestampEndLastChunk / (double)assetmanifestdata.TimeScale);

            log.LogInformation($"Livetime : {livetime}");

            var starttime = LiveManifest.ReturnTimeSpanOnGOP(assetmanifestdata, livetime.Subtract(TimeSpan.FromSeconds((int)data.IntervalSec)));

            log.LogInformation($"Value starttime : {starttime}");

            if (data.LastSubclipEndTime != null)
            {
                var lastEndTime = (TimeSpan)data.LastSubclipEndTime;
                log.LogInformation($"Value lastEndTime : {lastEndTime}");

                var delta = (livetime - lastEndTime - TimeSpan.FromSeconds((int)data.IntervalSec)).Duration();
                log.LogInformation($"Delta: {delta}");

                if (delta < (TimeSpan.FromSeconds(3 * (int)data.IntervalSec))) // less than 3 times the normal duration (3*60s)
                {
                    starttime = lastEndTime;
                    log.LogInformation($"Value new starttime : {starttime}");
                }
            }

            var duration = livetime - starttime;

            log.LogInformation($"Value duration: {duration}");
            if (duration == new TimeSpan(0)) // Duration is zero, this may happen sometimes !
            {
                return(HttpRequest.ResponseBadRequest(req, "Stopping. Duration of subclip is zero."));
            }

            Asset outputAsset;

            try
            {
                // Output from the Job must be written to an Asset, so let's create one
                outputAsset = await AssetUtils.CreateAssetAsync(client, log, config.ResourceGroup, config.AccountName, liveOutput.Name + "-subclip-" + triggerStart, data.OutputAssetStorageAccount);
            }
            catch (ErrorResponseException ex)
            {
                return(HttpRequest.ResponseBadRequest(req, LogUtils.LogError(log, ex, "Error when creating the output asset.")));
            }

            JobInput jobInput = new JobInputAsset(
                assetName: liveOutput.AssetName,
                start: new AbsoluteClipTime(starttime.Subtract(TimeSpan.FromMilliseconds(100))),
                end: new AbsoluteClipTime(livetime.Add(TimeSpan.FromMilliseconds(100)))
                );

            Job job;

            try
            {
                job = await JobUtils.SubmitJobAsync(
                    client,
                    log,
                    config.ResourceGroup,
                    config.AccountName,
                    SubclipTransformName,
                    $"Subclip-{liveOutput.Name}-{triggerStart}",
                    jobInput,
                    outputAsset.Name
                    );
            }
            catch (ErrorResponseException ex)
            {
                return(HttpRequest.ResponseBadRequest(req, LogUtils.LogError(log, ex, "Error when submitting the job.")));
            }


            AnswerBodyModel dataOk = new()
            {
                SubclipAssetName     = outputAsset.Name,
                SubclipJobName       = job.Name,
                SubclipTransformName = SubclipTransformName,
                SubclipEndTime       = starttime + duration
            };

            return(HttpRequest.ResponseOk(req, dataOk, HttpStatusCode.Accepted));
        }
    }
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        // <RunAsync>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client = await 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;

            // 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 locatorName     = $"locator-{uniqueness}";
            string outputAssetName = $"output-{uniqueness}";
            string inputAssetName  = $"input-{uniqueness}";

            // Ensure that you have the desired encoding Transform. This is really a one time setup operation.
            _ = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName);

            // Create a new input Asset and upload the specified local video file into it.
            _ = await CreateInputAssetAsync(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName);

            // Use the name of the created input asset to create the job input.
            _ = new JobInputAsset(assetName: inputAssetName);

            // 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);

            _ = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName, inputAssetName, outputAsset.Name);

            // In this demo code, we will poll for Job status
            // 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.
            Job job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName);

            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);

                StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName);

                // Note that the URLs returned by this method include a /manifest path followed by a (format=)
                // parameter that controls the type of manifest that is returned.
                // The /manifest(format=m3u8-aapl) will provide Apple HLS v4 manifest using MPEG TS segments.
                // The /manifest(format=mpd-time-csf) will provide MPEG DASH manifest.
                // And using just /manifest alone will return Microsoft Smooth Streaming format.
                // There are additional formats available that are not returned in this call, please check the documentation
                // on the dynamic packager for additional formats - see https://docs.microsoft.com/azure/media-services/latest/dynamic-packaging-overview
                IList <string> urls = await GetStreamingUrlsAsync(client, config.ResourceGroup, config.AccountName, locator.Name);

                foreach (var url in urls)
                {
                    Console.WriteLine(url);
                }
            }

            Console.WriteLine("Done. Copy and paste the Streaming URL ending in '/manifest' into the Azure Media Player at 'http://aka.ms/azuremediaplayer'.");
            Console.WriteLine("See the documentation on Dynamic Packaging for additional format support, including CMAF.");
            Console.WriteLine("https://docs.microsoft.com/azure/media-services/latest/dynamic-packaging-overview");
        }
Beispiel #21
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation($"AMS v3 Function - SubmitMediaJob was triggered!");

            string  requestBody = new StreamReader(req.Body).ReadToEnd();
            dynamic data        = JsonConvert.DeserializeObject(requestBody);

            // Validate input objects
            if (data.inputAssetName == null)
            {
                return(new BadRequestObjectResult("Please pass inputAssetName in the input object"));
            }
            if (data.transformName == null)
            {
                return(new BadRequestObjectResult("Please pass transformName in the input object"));
            }
            if (data.outputAssetNamePrefix == null)
            {
                return(new BadRequestObjectResult("Please pass outputAssetNamePrefix in the input object"));
            }
            string inputAssetName         = data.inputAssetName;
            string transformName          = data.transformName;
            string outputAssetNamePrefix  = data.outputAssetNamePrefix;
            string outputAssetDescription = null;

            if (data.outputAssetDescription != null)
            {
                outputAssetDescription = data.outputAssetDescription;
            }
            string assetStorageAccount = null;

            if (data.assetStorageAccount != null)
            {
                assetStorageAccount = data.assetStorageAccount;
            }

            MediaServicesConfigWrapper amsconfig = new MediaServicesConfigWrapper();
            Asset inputAsset = null;

            string guid    = Guid.NewGuid().ToString();
            string jobName = "amsv3function-job-" + guid;
            string encoderOutputAssetName       = null;
            string audioAnalyzerOutputAssetName = null;
            string videoAnalyzerOutputAssetName = null;
            JArray outputs = new JArray();

            try
            {
                IAzureMediaServicesClient client = MediaServicesHelper.CreateMediaServicesClientAsync(amsconfig);

                inputAsset = client.Assets.Get(amsconfig.ResourceGroup, amsconfig.AccountName, inputAssetName);
                if (inputAsset == null)
                {
                    return(new BadRequestObjectResult("Asset for input not found"));
                }
                Transform transform = client.Transforms.Get(amsconfig.ResourceGroup, amsconfig.AccountName, transformName);
                if (transform == null)
                {
                    return(new BadRequestObjectResult("Transform not found"));
                }

                var jobOutputList = new List <JobOutput>();
                for (int i = 0; i < transform.Outputs.Count; i++)
                {
                    Guid   assetGuid       = Guid.NewGuid();
                    string outputAssetName = outputAssetNamePrefix + "-" + assetGuid.ToString();

                    if (outputAssetDescription == null)
                    {
                        outputAssetDescription = outputAssetName;
                    }

                    Asset assetParams = new Asset(null, outputAssetName, null, assetGuid, DateTime.Now, DateTime.Now, null, outputAssetDescription, null, assetStorageAccount, AssetStorageEncryptionFormat.None);
                    Asset outputAsset = client.Assets.CreateOrUpdate(amsconfig.ResourceGroup, amsconfig.AccountName, outputAssetName, assetParams);
                    jobOutputList.Add(new JobOutputAsset(outputAssetName));

                    Preset preset = transform.Outputs[i].Preset;
                    if (encoderOutputAssetName == null && (preset is BuiltInStandardEncoderPreset || preset is StandardEncoderPreset))
                    {
                        encoderOutputAssetName = outputAssetName;
                    }
                    if (audioAnalyzerOutputAssetName == null && preset is AudioAnalyzerPreset)
                    {
                        audioAnalyzerOutputAssetName = outputAssetName;
                    }
                    if (videoAnalyzerOutputAssetName == null && preset is VideoAnalyzerPreset)
                    {
                        videoAnalyzerOutputAssetName = outputAssetName;
                    }

                    // set up jobOutputs
                    JObject outObject = new JObject();
                    outObject["Preset"]          = preset.ToString().Split('.').Last <string>();
                    outObject["OutputAssetName"] = outputAssetName;
                    if (preset is BuiltInStandardEncoderPreset || preset is StandardEncoderPreset)
                    {
                        outObject["Category"] = "Encoder";
                    }
                    else if (preset is AudioAnalyzerPreset || preset is VideoAnalyzerPreset)
                    {
                        outObject["Category"] = "Analyzer";
                    }
                    else
                    {
                        outObject["Category"] = "Unknown";
                    }
                    outputs.Add(outObject);
                }

                // Use the name of the created input asset to create the job input.
                JobInput    jobInput   = new JobInputAsset(assetName: inputAssetName);
                JobOutput[] jobOutputs = jobOutputList.ToArray();
                Job         job        = client.Jobs.Create(
                    amsconfig.ResourceGroup,
                    amsconfig.AccountName,
                    transformName,
                    jobName,
                    new Job
                {
                    Input   = jobInput,
                    Outputs = jobOutputs,
                }
                    );
            }
            catch (ApiErrorException e)
            {
                log.LogError($"ERROR: AMS API call failed with error code: {e.Body.Error.Code} and message: {e.Body.Error.Message}");
                return(new BadRequestObjectResult("AMS API call error: " + e.Message + "\nError Code: " + e.Body.Error.Code + "\nMessage: " + e.Body.Error.Message));
            }
            catch (Exception e)
            {
                log.LogError($"ERROR: Exception with message: {e.Message}");
                return(new BadRequestObjectResult("Error: " + e.Message));
            }

            JObject result = new JObject();

            result["jobName"]                      = jobName;
            result["jobOutputs"]                   = outputs;
            result["encoderOutputAssetName"]       = encoderOutputAssetName;
            result["videoAnalyzerOutputAssetName"] = videoAnalyzerOutputAssetName;
            result["audioAnalyzerOutputAssetName"] = audioAnalyzerOutputAssetName;
            return((ActionResult) new OkObjectResult(result));
        }
Beispiel #22
0
        public static async Task <HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, FunctionContext executionContext)
        {
            var log = executionContext.GetLogger("SubmitEncodingJob");

            log.LogInformation("C# HTTP trigger function processed a request.");

            // Get request body data.
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var    data        = (RequestBodyModel)JsonConvert.DeserializeObject(requestBody, typeof(RequestBodyModel));

            // Return bad request if input asset name is not passed in
            if (data.InputAssetName == null && data.InputUrl == null)
            {
                return(HttpRequest.ResponseBadRequest(req, "Please pass inputAssetName or inputUrl in the request body"));
            }

            // Return bad request if input asset name is not passed in
            if (data.TransformName == null)
            {
                return(HttpRequest.ResponseBadRequest(req, "Please pass transformName in the request body"));
            }

            ConfigWrapper config = ConfigUtils.GetConfig();

            IAzureMediaServicesClient client;

            try
            {
                client = await Authentication.CreateMediaServicesClientAsync(config);

                log.LogInformation("AMS Client created.");
            }
            catch (Exception e)
            {
                if (e.Source.Contains("ActiveDirectory"))
                {
                    log.LogError("TIP: Make sure that you have filled out the appsettings.json file before running this sample.");
                }
                log.LogError($"{e.Message}");

                return(HttpRequest.ResponseBadRequest(req, e.Message));
            }

            // 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().Substring(0, 13);
            string jobName         = $"job-{uniqueness}";
            string outputAssetName = $"output-{uniqueness}";

            Transform transform;

            try
            {
                // Ensure that you have the encoding Transform.  This is really a one time setup operation.
                transform = await TransformUtils.CreateEncodingTransform(client, log, config.ResourceGroup, config.AccountName, data.TransformName, data.BuiltInPreset);

                log.LogInformation("Transform retrieved.");
            }
            catch (ErrorResponseException ex)
            {
                return(HttpRequest.ResponseBadRequest(req, LogUtils.LogError(log, ex, "Error when creating the transform.")));
            }

            Asset outputAsset;

            try
            {
                // Output from the job must be written to an Asset, so let's create one
                outputAsset = await AssetUtils.CreateAssetAsync(client, log, config.ResourceGroup, config.AccountName, outputAssetName, data.OutputAssetStorageAccount);

                log.LogInformation($"Output asset '{outputAssetName}' created.");
            }
            catch (ErrorResponseException ex)
            {
                return(HttpRequest.ResponseBadRequest(req, LogUtils.LogError(log, ex, "Error when creating the output asset.")));
            }

            // Job input prepration : asset or url
            JobInput jobInput;

            if (data.InputUrl != null)
            {
                jobInput = new JobInputHttp(files: new[] { data.InputUrl });
                log.LogInformation("Input is a Url.");
            }
            else
            {
                jobInput = new JobInputAsset(assetName: data.InputAssetName);
                log.LogInformation($"Input is asset '{data.InputAssetName}'.");
            }

            Job job;

            try
            {
                // Job submission to Azure Media Services
                job = await JobUtils.SubmitJobAsync(
                    client,
                    log,
                    config.ResourceGroup,
                    config.AccountName,
                    data.TransformName,
                    jobName,
                    jobInput,
                    outputAssetName
                    );

                log.LogInformation($"Job '{jobName}' submitted.");
            }
            catch (ErrorResponseException ex)
            {
                return(HttpRequest.ResponseBadRequest(req, LogUtils.LogError(log, ex, "Error when submitting the job.")));
            }


            AnswerBodyModel dataOk = new()
            {
                OutputAssetName = outputAsset.Name,
                JobName         = job.Name
            };

            return(HttpRequest.ResponseOk(req, dataOk, HttpStatusCode.Accepted));
        }
    }
Beispiel #23
0
        public async Task <Job> StartEncode(Models.Resource resource)
        {
            var client = await GetClient();

            var credential = _mediaCredential.Value;

            var contentAddress = new ContentAddress(resource.ContentAddress);
            var sourceName     = $"raw-{contentAddress.ContainerName}";
            var resultName     = $"result-{contentAddress.ContainerName}";
            var jobName        = $"job-{contentAddress.ContainerName}";

            //await client.Assets.DeleteAsync(credential.ResourceGroup, credential.AccountName, resultName);
            Asset resultAsset = await client.Assets.GetAsync(credential.ResourceGroup, credential.AccountName, resultName);

            if (resultAsset != null)
            {
                await client.Assets.DeleteAsync(credential.ResourceGroup, credential.AccountName, resultName);

                await Task.Delay(TimeSpan.FromSeconds(60));
            }
            //do
            //{
            //    await Task.Delay(TimeSpan.FromSeconds(60));
            //    resultAsset = client.Assets.Get(credential.ResourceGroup, credential.AccountName, resultName);
            //}
            //while (resultAsset != null);

            resultAsset = await client.Assets.CreateOrUpdateAsync(credential.ResourceGroup, credential.AccountName,
                                                                  resultName, new Asset(name : resultName, container : resultName));

            await client.Transforms.CreateOrUpdateAsync(
                credential.ResourceGroup,
                credential.AccountName,
                TRANSFORM_NAME,
                new List <TransformOutput> {
                new TransformOutput(MediaTransform.Preset)
            });

            JobInput jobInput = new JobInputAsset(sourceName);

            JobOutput[] jobOutputs =
            {
                new JobOutputAsset(resultName),
            };

            Job job = await client.Jobs.GetAsync(credential.ResourceGroup, credential.AccountName,
                                                 TRANSFORM_NAME, jobName);

            if (job != null)
            {
                await client.Jobs.DeleteAsync(credential.ResourceGroup, credential.AccountName,
                                              TRANSFORM_NAME, jobName);
            }

            do // poll job status
            {
                await Task.Delay(TimeSpan.FromSeconds(3));

                job = await client.Jobs.GetAsync(credential.ResourceGroup, credential.AccountName,
                                                 TRANSFORM_NAME, jobName);
            }while (job != null);

            try
            {
                var tt = await client.Jobs.CreateWithHttpMessagesAsync(credential.ResourceGroup, credential.AccountName,
                                                                       TRANSFORM_NAME, jobName,
                                                                       parameters : new Job(input: jobInput, outputs: jobOutputs));
            }
            catch (ApiErrorException aee)
            {
                throw new Exception(aee.Message);
            }
            catch (Exception e)
            {
                throw e;
            }

            return(job);
        }