This class reads values from local configuration file resources/conf/appsettings.json. Please change the configuration using your account information. For more information, see https://docs.microsoft.com/azure/media-services/latest/access-api-cli-how-to. For security reasons, do not check in the configuration file to source control.
        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, log);
            }
            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;

            // Ensure that you have customized encoding Transform.  This is really a one time setup operation.
            Transform transform = await TransformUtils.CreateSubclipTransform(client, log, config.ResourceGroup, config.AccountName, SubclipTransformName);

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

            // Output from the Job must be written to an Asset, so let's create one
            Asset outputAsset = await AssetUtils.CreateAssetAsync(client, log, config.ResourceGroup, config.AccountName, liveOutput.Name + "-subclip-" + triggerStart, data.OutputAssetStorageAccount);

            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 = await JobUtils.SubmitJobAsync(
                client,
                log,
                config.ResourceGroup,
                config.AccountName,
                SubclipTransformName,
                $"Subclip-{liveOutput.Name}-{triggerStart}",
                jobInput,
                outputAsset.Name
                );

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

            return(HttpRequest.ResponseOk(req, dataOk));
        }
    }
        public static async Task <HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, FunctionContext executionContext)
        {
            var log = executionContext.GetLogger("PublishAsset");

            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.AssetName == null)
            {
                return(HttpRequest.ResponseBadRequest(req, "Please pass assetName in the request body"));
            }
            if (data.StreamingPolicyName == null)
            {
                return(HttpRequest.ResponseBadRequest(req, "Please pass streamingPolicyName in the request body"));
            }

            ConfigWrapper config = ConfigUtils.GetConfig();

            IAzureMediaServicesClient client;

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

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

            List <StreamingLocatorContentKey> contentKeys = new List <StreamingLocatorContentKey>();

            Guid streamingLocatorId = Guid.NewGuid();

            if (data.StreamingLocatorId != null)
            {
                streamingLocatorId = new Guid((string)(data.StreamingLocatorId));
            }
            string streamingLocatorName = "streaminglocator-" + streamingLocatorId.ToString();

            StreamingPolicy streamingPolicy;
            Asset           asset;

            try
            {
                asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, data.AssetName);

                if (asset == null)
                {
                    return(HttpRequest.ResponseBadRequest(req, "Asset not found"));
                }

                streamingPolicy = await client.StreamingPolicies.GetAsync(config.ResourceGroup, config.AccountName, data.StreamingPolicyName);

                if (streamingPolicy == null)
                {
                    return(HttpRequest.ResponseBadRequest(req, "Streaming Policy not found"));
                }

                if (data.ContentKeyPolicyName != null)
                {
                    ContentKeyPolicy contentKeyPolicy = null;
                    contentKeyPolicy = await client.ContentKeyPolicies.GetAsync(config.ResourceGroup, config.AccountName, data.ContentKeyPolicyName);

                    if (contentKeyPolicy == null)
                    {
                        return(HttpRequest.ResponseBadRequest(req, "Content Key Policy not found"));
                    }
                }

                if (data.ContentKeys != null)
                {
                    JsonConverter[] jsonConverters =
                    {
                        new MediaServicesHelperJsonReader()
                    };
                    contentKeys = JsonConvert.DeserializeObject <List <StreamingLocatorContentKey> >(data.ContentKeys.ToString(), jsonConverters);
                }

                var streamingLocator = new StreamingLocator()
                {
                    AssetName                   = data.AssetName,
                    StreamingPolicyName         = data.StreamingPolicyName,
                    DefaultContentKeyPolicyName = data.ContentKeyPolicyName,
                    StreamingLocatorId          = streamingLocatorId,
                    StartTime                   = data.StartDateTime,
                    EndTime = data.EndDateTime
                };

                if (contentKeys.Count != 0)
                {
                    streamingLocator.ContentKeys = contentKeys;
                }
                streamingLocator.Validate();

                await client.StreamingLocators.CreateAsync(config.ResourceGroup, config.AccountName, streamingLocatorName, streamingLocator);
            }
            catch (Exception e)
            {
                log.LogError("Error when publishing the asset.");
                log.LogError($"{e.Message}");
                return(HttpRequest.ResponseBadRequest(req, e.Message));
            }

            AnswerBodyModel dataOk = new()
            {
                StreamingLocatorName = streamingLocatorName,
                StreamingLocatorId   = streamingLocatorId
            };

            return(HttpRequest.ResponseOk(req, dataOk));
        }
    }
Exemplo n.º 3
0
        /// <summary>
        /// Creates the AzureMediaServicesClient object based on the credentials
        /// supplied in local configuration file.
        /// </summary>
        /// <param name="config">The param is of type ConfigWrapper, which reads values from local configuration file.</param>
        /// <returns>A task.</returns>
        private static async Task <IAzureMediaServicesClient> CreateMediaServicesClientAsync(ConfigWrapper config)
        {
            ServiceClientCredentials credentials = await GetCredentialsAsync(config);

            return(new AzureMediaServicesClient(config.ArmEndpoint, credentials)
            {
                SubscriptionId = config.SubscriptionId
            });
        }
        public static async Task <HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, FunctionContext executionContext)
        {
            var log = executionContext.GetLogger("CreateEmptyAsset");

            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.AssetNamePrefix == null)
            {
                return(HttpRequest.ResponseBadRequest(req, "Please pass asset name prefix in the request body"));
            }

            ConfigWrapper config = ConfigUtils.GetConfig();

            IAzureMediaServicesClient client;

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

                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 assetName  = $"{data.AssetNamePrefix}-{uniqueness}";

            Asset asset;

            try
            {
                // let's create the asset
                asset = await AssetUtils.CreateAssetAsync(client, log, config.ResourceGroup, config.AccountName, assetName, data.AssetStorageAccount);

                log.LogInformation($"Asset '{assetName}' created.");

                // let's get the asset to have full metadata like container
                asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName);
            }
            catch (Exception e)
            {
                log.LogError("Error when creating the asset.");
                log.LogError($"{e.Message}");
                return(HttpRequest.ResponseBadRequest(req, e.Message));
            }

            AnswerBodyModel dataOk = new()
            {
                AssetName = asset.Name,
                AssetId   = asset.AssetId,
                Container = asset.Container
            };

            return(HttpRequest.ResponseOk(req, dataOk));
        }
    }