private static INotificationEndPoint CreateNotificationEndPoint(IKernel kernel) { var cloudMediaContext = kernel.Resolve <CloudMediaContext>(); var cloudQueueClient = kernel.Resolve <CloudQueueClient>(); try { // ReSharper disable once ReplaceWithSingleCallToFirstOrDefault INotificationEndPoint endpoint = cloudMediaContext.NotificationEndPoints .Where(ep => ep.Name == UploadConfig.NotificationQueueName) .FirstOrDefault(); if (endpoint != null) { return(endpoint); } // Make sure the queue exists in Azure Storage var notificationQueue = cloudQueueClient.GetQueueReference(UploadConfig.NotificationQueueName); notificationQueue.CreateIfNotExists(); // Create the endpoint return(cloudMediaContext.NotificationEndPoints.Create(UploadConfig.NotificationQueueName, NotificationEndPointType.AzureQueue, UploadConfig.NotificationQueueName)); } finally { kernel.ReleaseComponent(cloudMediaContext); kernel.ReleaseComponent(cloudQueueClient); } }
internal IJob CreateJob(MediaJob mediaJob) { IJob job = _media.Jobs.Create(mediaJob.Name, mediaJob.Priority); foreach (MediaJobTask jobTask in mediaJob.Tasks) { string processorId = Processors.GetMediaProcessorId(jobTask.MediaProcessor); IMediaProcessor processor = GetEntityById(MediaEntity.Processor, processorId) as IMediaProcessor; ITask currentTask = job.Tasks.AddNew(jobTask.Name, processor, jobTask.ProcessorConfig, jobTask.Options); if (jobTask.ParentIndex.HasValue) { ITask parentTask = job.Tasks[jobTask.ParentIndex.Value]; currentTask.InputAssets.AddRange(parentTask.OutputAssets); } else { IAsset[] assets = GetAssets(jobTask.InputAssetIds); currentTask.InputAssets.AddRange(assets); } currentTask.OutputAssets.AddNew(jobTask.OutputAssetName, jobTask.OutputAssetEncryption, jobTask.OutputAssetFormat); } INotificationEndPoint notificationEndpoint = GetNotificationEndpoint(mediaJob.Notification); if (notificationEndpoint != null) { job.JobNotificationSubscriptions.AddNew(NotificationJobState.FinalStatesOnly, notificationEndpoint); } SetProcessorUnits(job, mediaJob.Scale); job.Submit(); return(job); }
public EncodeVideoWhenAcceptedHandler(ISession session, TaskCache <string, PreparedStatement> statementCache, IBus bus, CloudMediaContext cloudMediaContext, INotificationEndPoint notificationEndPoint) { if (session == null) { throw new ArgumentNullException("session"); } if (statementCache == null) { throw new ArgumentNullException("statementCache"); } if (bus == null) { throw new ArgumentNullException("bus"); } if (cloudMediaContext == null) { throw new ArgumentNullException("cloudMediaContext"); } if (notificationEndPoint == null) { throw new ArgumentNullException("notificationEndPoint"); } _session = session; _statementCache = statementCache; _bus = bus; _cloudMediaContext = cloudMediaContext; _notificationEndPoint = notificationEndPoint; }
public IJob CreateJob(MediaJob mediaJob, MediaJobInput[] jobInputs, out IJobTemplate jobTemplate) { IJob job = null; jobTemplate = null; if (!string.IsNullOrEmpty(mediaJob.TemplateId)) { List <IAsset> inputAssets = new List <IAsset>(); foreach (MediaJobInput jobInput in jobInputs) { IAsset asset = GetEntityById(MediaEntity.Asset, jobInput.AssetId) as IAsset; if (asset != null) { inputAssets.Add(asset); } } jobTemplate = GetEntityById(MediaEntity.JobTemplate, mediaJob.TemplateId) as IJobTemplate; job = _media.Jobs.Create(mediaJob.Name, jobTemplate, inputAssets, mediaJob.Priority); } else if (mediaJob.Tasks.Length > 0) { job = _media.Jobs.Create(mediaJob.Name, mediaJob.Priority); foreach (MediaJobTask jobTask in mediaJob.Tasks) { string processorId = Processor.GetProcessorId(jobTask.MediaProcessor, jobTask.ProcessorConfig); IMediaProcessor processor = GetEntityById(MediaEntity.Processor, processorId) as IMediaProcessor; ITask currentTask = job.Tasks.AddNew(jobTask.Name, processor, jobTask.ProcessorConfig, jobTask.Options); if (jobTask.ParentIndex.HasValue) { ITask parentTask = job.Tasks[jobTask.ParentIndex.Value]; currentTask.InputAssets.AddRange(parentTask.OutputAssets); } else { IAsset[] assets = GetAssets(jobTask.InputAssetIds); currentTask.InputAssets.AddRange(assets); } currentTask.OutputAssets.AddNew(jobTask.OutputAssetName, jobTask.OutputAssetEncryption, jobTask.OutputAssetFormat); } INotificationEndPoint notificationEndpoint = GetNotificationEndpoint(); job.JobNotificationSubscriptions.AddNew(NotificationJobState.FinalStatesOnly, notificationEndpoint); } if (job != null) { if (mediaJob.SaveWorkflow) { string templateName = mediaJob.Name; jobTemplate = job.SaveAsTemplate(templateName); } else { SetProcessorUnits(job, jobTemplate, mediaJob.NodeType, true); job.Submit(); } } return(job); }
public ConfigureWebhook(CloudMediaContext myContext, INotificationEndPoint webhookConfig) { InitializeComponent(); this.Icon = Bitmaps.Azure_Explorer_ico; _context = myContext; _webhookEndpoint = webhookConfig; PrepareControls(); }
public void AddNew(NotificationJobState targetJobState, INotificationEndPoint notificationEndPoint) { JobNotificationSubscription subscription = new JobNotificationSubscription(targetJobState, notificationEndPoint); if (_cloudMediaContext != null) { subscription.InitCloudMediaContext(_cloudMediaContext); } _jobNotificationSubscriptionList.Add(subscription); }
public void AddNew(NotificationJobState targetJobState, INotificationEndPoint notificationEndPoint, bool includeTaskProgress) { TaskNotificationSubscription subscription = new TaskNotificationSubscription(targetJobState, notificationEndPoint, includeTaskProgress); if (MediaContext != null) { subscription.SetMediaContext(MediaContext); } _taskNotificationSubscriptionList.Add(subscription); }
public JobNotificationSubscription(NotificationJobState targetJobState, INotificationEndPoint notificationEndPoint) { TargetJobState = (int)targetJobState; if (notificationEndPoint == null) { throw new ArgumentNullException("notificationEndPoint"); } _notificationEndPoint = notificationEndPoint; NotificationEndPointId = _notificationEndPoint.Id; }
public JobNotificationSubscription(NotificationJobState targetJobState, INotificationEndPoint notificationEndPoint) { TargetJobState = (int)targetJobState; if (notificationEndPoint == null) { throw new ArgumentNullException("notificationEndPoint"); } _notificationEndPoint = notificationEndPoint; NotificationEndPointId = _notificationEndPoint.Id; }
public TaskNotificationSubscription(NotificationJobState targetTaskState, INotificationEndPoint notificationEndPoint, bool includeTaskProgress) { TargetTaskState = (int)targetTaskState; if (notificationEndPoint == null) { throw new ArgumentNullException("notificationEndPoint"); } _notificationEndPoint = notificationEndPoint; NotificationEndPointId = _notificationEndPoint.Id; IncludeTaskProgress = includeTaskProgress; }
public void ShouldReceiveNotificationsForCompeletedJob() { string endPointAddress = Guid.NewGuid().ToString(); CloudQueueClient client = CloudStorageAccount.Parse(WindowsAzureMediaServicesTestConfiguration.ClientStorageConnectionString).CreateCloudQueueClient(); CloudQueue queue = client.GetQueueReference(endPointAddress); queue.CreateIfNotExists(); string endPointName = Guid.NewGuid().ToString(); INotificationEndPoint notificationEndPoint = _mediaContext.NotificationEndPoints.Create(endPointName, NotificationEndPointType.AzureQueue, endPointAddress); Assert.IsNotNull(notificationEndPoint); string configuration = File.ReadAllText(WindowsAzureMediaServicesTestConfiguration.DefaultMp4ToSmoothConfig); IAsset asset = AssetTests.CreateAsset(_mediaContext, WindowsAzureMediaServicesTestConfiguration.SmallMp41, AssetCreationOptions.StorageEncrypted); IMediaProcessor mediaProcessor = GetMediaProcessor(_mediaContext, WindowsAzureMediaServicesTestConfiguration.MpPackagerName); IJob job = _mediaContext.Jobs.Create("CreateJobWithNotificationSubscription"); ITask task = job.Tasks.AddNew("Task1", mediaProcessor, configuration, TaskOptions.None); task.InputAssets.Add(asset); task.OutputAssets.AddNew("Output", AssetCreationOptions.None); job.JobNotificationSubscriptions.AddNew(NotificationJobState.All, notificationEndPoint); job.Submit(); Assert.IsTrue(job.JobNotificationSubscriptions.Count > 0); WaitForJob(job.Id, JobState.Finished, VerifyAllTasksFinished); Thread.Sleep((int)TimeSpan.FromMinutes(5).TotalMilliseconds); Assert.IsNotNull(queue); Assert.IsTrue(queue.Exists()); IEnumerable <CloudQueueMessage> messages = queue.GetMessages(10); Assert.IsTrue(messages.Any()); Assert.AreEqual(4, messages.Count(), "Expecting to have 4 notifications messages"); IJob lastJob = _mediaContext.Jobs.Where(j => j.Id == job.Id).FirstOrDefault(); Assert.IsNotNull(lastJob); Assert.IsTrue(lastJob.JobNotificationSubscriptions.Count > 0); IJobNotificationSubscription lastJobNotificationSubscription = lastJob.JobNotificationSubscriptions.Where(n => n.NotificationEndPoint.Id == notificationEndPoint.Id).FirstOrDefault(); Assert.IsNotNull(lastJobNotificationSubscription); INotificationEndPoint lastNotificationEndPoint = lastJobNotificationSubscription.NotificationEndPoint; Assert.IsNotNull(lastNotificationEndPoint); Assert.AreEqual(endPointName, lastNotificationEndPoint.Name); Assert.AreEqual(endPointAddress, lastNotificationEndPoint.EndPointAddress); }
public static async Task <IJob> CreateJob(string name, IAsset asset, INotificationEndPoint endpoint, TraceWriter log, string mediaProcessorName = "Media Encoder Standard", bool deletePreviousJobs = true) { if (string.IsNullOrEmpty(mediaProcessorName)) { return(null); } if (asset == null) { log.Info("Invalid input asset for job."); return(null); } if (deletePreviousJobs) { //Clean previous finished jobs, no need to keep them :) var finishedJobs = _mediaServiceContext.Jobs.Where(j => j.State == JobState.Finished).ToList(); foreach (var item in finishedJobs) { await item.DeleteAsync(); } } IJob job = _mediaServiceContext.Jobs.Create($"Encoding Job for - {name}"); //A standart streaming processor var processor = _mediaServiceContext.MediaProcessors.Where(p => p.Name == mediaProcessorName).ToList().OrderBy(p => new Version(p.Version)).LastOrDefault(); if (processor != null) { //Create job ITask task = job.Tasks.AddNew("Encode with Adaptive Streaming", processor, "Adaptive Streaming", TaskOptions.None); task.InputAssets.Add(asset); var outputAsset = task.OutputAssets.AddNew(name, AssetCreationOptions.None); if (endpoint != null) { task.TaskNotificationSubscriptions.AddNew(NotificationJobState.All, endpoint, true); log.Info("Notification endpoint is added."); } job.Submit(); log.Info($"Encoding job is submitted. Job Id:{job.Id}"); return(job); } return(null); }
public void TestNotificationEndPointCreateRetry() { var expected = new NotificationEndPoint { Name = "testData" }; var fakeException = new WebException("test", WebExceptionStatus.ConnectionClosed); var dataContextMock = TestMediaServicesClassFactory.CreateSaveChangesMock(fakeException, 2, expected); dataContextMock.Setup((ctxt) => ctxt.AddObject("NotificationEndPoints", It.IsAny<object>())); _mediaContext.MediaServicesClassFactory = new TestMediaServicesClassFactory(dataContextMock.Object); INotificationEndPoint actual = _mediaContext.NotificationEndPoints.Create("Empty", NotificationEndPointType.AzureQueue, "127.0.0.1"); Assert.AreEqual(expected.Name, actual.Name); dataContextMock.Verify((ctxt) => ctxt.SaveChangesAsync(It.IsAny<object>()), Times.Exactly(2)); }
private INotificationEndPoint GetNotificationEndpoint() { string endpointName = Constant.Media.JobNotification.EndpointName; INotificationEndPoint notificationEndpoint = GetEntityByName(MediaEntity.NotificationEndpoint, endpointName) as INotificationEndPoint; if (notificationEndpoint == null) { NotificationEndPointType endpointType = NotificationEndPointType.WebHook; string settingKey = Constant.AppSettingKey.MediaPublishContentUrl; string endpointAddress = AppSetting.GetValue(settingKey); notificationEndpoint = _media.NotificationEndPoints.Create(endpointName, endpointType, endpointAddress); } return(notificationEndpoint); }
static void Main(string[] args) { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(_AADTenantDomain, new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret), AzureEnvironments.AzureCloudEnvironment); var tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider); Console.WriteLine("Please choose your Azure Media Services telemety sources"); _streamingEndpoint = ChooseStreamingEndpointForTelemetry(); _channel = ChooseLiveChannelForTelemetry(); var monitoringConfigurations = _context.MonitoringConfigurations; IMonitoringConfiguration monitoringConfiguration = null; // No more than one monitoring configuration settings is allowed. // Once we have created it, it is the one that we shall use in future iterations... // you can use monitoringConfiguration.Delete(); to delete the monitoring configuration. if (monitoringConfigurations.ToArray().Length != 0) { monitoringConfiguration = _context.MonitoringConfigurations.FirstOrDefault(); } else { INotificationEndPoint notificationEndPoint = _context.NotificationEndPoints.Create("monitoring", NotificationEndPointType.AzureTable, GetTableEndPoint()); monitoringConfiguration = _context.MonitoringConfigurations.Create(notificationEndPoint.Id, new List <ComponentMonitoringSetting>() { new ComponentMonitoringSetting(MonitoringComponent.Channel, MonitoringLevel.Verbose), new ComponentMonitoringSetting(MonitoringComponent.StreamingEndpoint, MonitoringLevel.Verbose) }); } //Print metrics for a Streaming Endpoint. PrintMetrics(); Console.WriteLine("\npress any key to exit..."); Console.ReadKey(); }
public static string GeneratesEncoder([ActivityTrigger] InitialSetupResult initialSetupResult, TraceWriter log) { IJob job; // Step 1: Setting up queue, context and endpoint string endPointAddress = Guid.NewGuid().ToString(); AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(_tenantDomain, new AzureAdClientSymmetricKey(_clientId, _clientSecret), AzureEnvironments.AzureCloudEnvironment); var tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(new Uri(_restApiUrl), tokenProvider); // Create the queue that will be receiving the notification messages. _queue = MediaServices.CreateQueue(_storageConnection, endPointAddress); // Create the notification point that is mapped to the queue. _notificationEndPoint = _context.NotificationEndPoints.Create(Guid.NewGuid().ToString(), NotificationEndPointType.AzureQueue, endPointAddress); // Step 2: Creating the encoding job try { log.Info("Starting encoding job..."); IMediaProcessor mediaProcessor = MediaServices.GetLatestMediaProcessorByName("Media Encoder Standard", _context); job = MediaServices.SubmitEncodingJobWithNotificationEndPoint(_context, mediaProcessor.Name, initialSetupResult, _notificationEndPoint); log.Info("Done. Encoding job successfuly scheduled."); log.Info("Waiting the encoding process get completed..."); MediaServices.WaitForJobToReachedFinishedState(job.Id, _queue, log); } catch (Exception ex) { return(string.Empty); } log.Info("Done. Encoding completed."); // Step 3: Cleaning up temporary resources _queue.Delete(); _notificationEndPoint.Delete(); // Step 4: Returns the final result return(job.Id); }
private INotificationEndPoint GetNotificationEndpoint(NotificationEndPointType endpointType) { string endpointName = Constants.Media.JobNotification.EndpointNameStorageQueue; string settingKey = Constants.AppSettingKey.MediaJobNotificationStorageQueueName; string endpointAddress = AppSetting.GetValue(settingKey); if (endpointType == NotificationEndPointType.WebHook) { endpointName = Constants.Media.JobNotification.EndpointNameWebHook; settingKey = Constants.AppSettingKey.MediaJobNotificationWebHookUrl; endpointAddress = AppSetting.GetValue(settingKey); } INotificationEndPoint notificationEndpoint = null; if (!string.IsNullOrEmpty(endpointAddress)) { notificationEndpoint = GetEntityByName(MediaEntity.NotificationEndpoint, endpointName, true) as INotificationEndPoint; if (notificationEndpoint == null) { notificationEndpoint = _media.NotificationEndPoints.Create(endpointName, endpointType, endpointAddress); } } return(notificationEndpoint); }
public JobNotificationSubscription() { _targetJobState = 0; _notificationEndPoint = null; }
public static async Task RunAsync([BlobTrigger("assets/video/chapters/original/{name}", Connection = "")] CloudBlockBlob blob, string name, TraceWriter log) { try { var contentType = blob.Properties.ContentType; log.Info($"Content Type: {blob.Properties.ContentType}"); //Just checking content type if (contentType.Equals("video/mp4")) { log.Info($"Valid content type. Starting to encode..."); _mediaServiceContext = Helper.GenerateMediaContext(_tenant, _clientId, _clientSecret, _mediaServiceAPI); INotificationEndPoint endpoint = _mediaServiceContext.NotificationEndPoints.Where(e => e.Name == _webHookEndpointName).FirstOrDefault(); if (endpoint == null) { byte[] keyBytes = Convert.FromBase64String(_accessKey); endpoint = _mediaServiceContext.NotificationEndPoints.Create(_webHookEndpointName, NotificationEndPointType.WebHook, _webHookEndpoint, keyBytes); log.Info("Notification endpoint is created."); } else { log.Info("Already have a notification endpoint."); } var asset = await CreateAsset(blob, name, log); var job = await CreateJob(name, asset, endpoint, log); if (job != null) { //Fire a custom event TopicCredentials topicCredentials = new TopicCredentials(_eventTopicKey); EventGridClient client = new EventGridClient(topicCredentials); List <EventGridEvent> eventsList = new List <EventGridEvent>(); eventsList.Add(new EventGridEvent() { Id = Guid.NewGuid().ToString(), EventType = "MediaService.Assets.JobStartedEvent", Data = new JobEvent() { JobId = job.Id, EventType = "MediaService.Assets.JobStartedEvent" }, EventTime = DateTime.Now, Subject = "Encoding", DataVersion = "2.0" }); await client.PublishEventsAsync(new Uri(_eventTopicHost).Host, eventsList); } } } catch (Exception ex) { log.Error($"!!!ERROR!!!: {ex.Message}"); throw ex; } }
public static async Task Run([QueueTrigger("ams-input", Connection = "AzureWebJobsStorage")] VippyProcessingState manifest, [Blob("%amsBlobInputContainer%/{BlobName}", FileAccess.ReadWrite)] CloudBlockBlob videoBlob, TraceWriter log) { //================================================================================ // Function AMSInputQueueHandler // Purpose: // This is where the start of the pipeline work begins. It will submit an encoding // job to Azure Media Services. When that job completes asyncronously, a notification // webhook will be called by AMS which causes the next stage of the pipeline to // continue. //================================================================================ var context = MediaServicesHelper.Context; // only set the starttime if it wasn't already set in blob watcher function (that way // it works if the job is iniaited by using this queue directly if (manifest.StartTime == null) { manifest.StartTime = DateTime.Now; } var videofileName = videoBlob.Name; var videoTitle = manifest.videoTitle ?? videofileName; // get a new asset from the blob, and use the file name if video title attribute wasn't passed. IAsset newAsset; try { newAsset = CopyBlobHelper.CreateAssetFromBlob(videoBlob, videoTitle, log).GetAwaiter().GetResult(); } catch (Exception e) { throw new ApplicationException($"Error occured creating asset from Blob;/r/n{e.Message}"); } // If an internal_id was passed in the metadata, use it within AMS (AlternateId) and Cosmos(Id - main document id) for correlation. // if not, generate a unique id. If the same id is ever reprocessed, all stored metadata // will be overwritten. newAsset.AlternateId = manifest.AlternateId; newAsset.Update(); manifest.AmsAssetId = newAsset.Id; // delete the source input from the watch folder videoBlob.DeleteIfExists(); // copy blob into new asset // create the encoding job var job = context.Jobs.Create("MES encode from input container - ABR streaming"); // Get a media processor reference, and pass to it the name of the // processor to use for the specific task. var processor = MediaServicesHelper.GetLatestMediaProcessorByName("Media Encoder Standard"); var task = job.Tasks.AddNew("encoding task", processor, "Content Adaptive Multiple Bitrate MP4", TaskOptions.None ); task.Priority = 100; task.InputAssets.Add(newAsset); // setup webhook notification //byte[] keyBytes = Convert.FromBase64String(_signingKey); var keyBytes = new byte[32]; // Check for existing Notification Endpoint with the name "FunctionWebHook" var existingEndpoint = context.NotificationEndPoints.Where(e => e.Name == "FunctionWebHook").FirstOrDefault(); INotificationEndPoint endpoint = null; if (existingEndpoint != null) { endpoint = existingEndpoint; } else { try { //byte[] credential = new byte[64]; endpoint = context.NotificationEndPoints.Create("FunctionWebHook", NotificationEndPointType.WebHook, WebHookEndpoint, keyBytes); } catch (Exception) { throw new ApplicationException( $"The endpoing address specified - '{WebHookEndpoint}' is not valid."); } } task.TaskNotificationSubscriptions.AddNew(NotificationJobState.FinalStatesOnly, endpoint, false); // Add an output asset to contain the results of the job. // This output is specified as AssetCreationOptions.None, which // means the output asset is not encrypted. task.OutputAssets.AddNew(videofileName, AssetCreationOptions.None); // Starts the job in AMS. AMS will notify the webhook when it completes job.Submit(); // update processing progress with id and metadata payload await Globals.StoreProcessingStateRecordInCosmosAsync(manifest); Globals.LogMessage(log, $"AMS encoding job submitted for {videofileName}"); }
public TaskNotificationSubscription() { _targetTaskState = 0; _notificationEndPoint = null; IncludeTaskProgress = false; }
////////////////////////////////////////////////////////////// NEW VERSION //////////////////////////////////////////////////////////////////////////////////// public static IJob SubmitEncodingJobWithNotificationEndPoint(CloudMediaContext _context, string mediaProcessorName, InitialSetupResult initialSetup, INotificationEndPoint _notificationEndPoint) { // Declare a new job. IJob job = _context.Jobs.Create($"Job_Encoding_{initialSetup.Video.VideoFileName}"); //Create an encrypted asset and upload the mp4 IAsset asset = LoadExistingAsset(initialSetup.Asset.Id, _context); // Get a media processor reference, and pass to it the name of the // processor to use for the specific task. IMediaProcessor processor = GetLatestMediaProcessorByName(mediaProcessorName, _context); // Create a task with the conversion details, using a configuration file. ITask task = job.Tasks.AddNew($"Job_Encoding_Task_{initialSetup.Video.VideoFileName}", processor, "Adaptive Streaming", Microsoft.WindowsAzure.MediaServices.Client.TaskOptions.None); // Specify the input asset to be encoded. task.InputAssets.Add(asset); // Add an output asset to contain the results of the job. task.OutputAssets.AddNew($"Output_Encoding_{initialSetup.Video.VideoFileName}", AssetCreationOptions.None); // Add a notification point to the job. You can add multiple notification points. job.JobNotificationSubscriptions.AddNew(NotificationJobState.FinalStatesOnly, _notificationEndPoint); job.Submit(); return(job); }
public JobNotificationSubscription() { _targetJobState = 0; _notificationEndPoint = null; }
public async static void RunBlobTrigger([BlobTrigger("mediaassetblobcontainer20170928/{name}", Connection = "AzureWebJobsStorage")] Stream myBlob, string name, TraceWriter log) { //#error //uncomment error tag to ensure that developer adds appropriate strings in Azure Function or local.settings.json //SETUP NOTE //When running locally add full blob storage connection string to local.settings.json with key "AzureWebJobsStorage" //When running on cloud - make sure that in the Azure Portal - under your Function > Application Settings to add an environmental variable with key "AzureWebJobsStorage" with the full blob storage connection string // NOTE that the variables {fileName} here come from the path setting in function.json // and are passed into the Run method signature above. We can use this to make decisions on what type of file // was dropped into the input container for the function. // No need to do any Retry strategy in this function, By default, the SDK calls a function up to 5 times for a // given blob. If the fifth try fails, the SDK adds a message to a queue named webjobs-blobtrigger-poison. log.Info($"C# Blob trigger function processed: {name}.mp4"); log.Info($"Media Services REST endpoint : {_RESTAPIEndpoint}"); try { AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(_AADTenantDomain, new AzureAdClientSymmetricKey(_mediaservicesClientId, _mediaservicesClientSecret), AzureEnvironments.AzureCloudEnvironment); AzureAdTokenProvider tokenProvider = new AzureAdTokenProvider(tokenCredentials); _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider); string createdURI = $"https://xamcamstorage.blob.core.windows.net/mediaassetblobcontainer20170928/{name}"; CloudBlockBlob uploadedBlob = new CloudBlockBlob(new Uri(createdURI)); IAsset newAsset = CreateAssetFromBlob(uploadedBlob, name, log).GetAwaiter().GetResult(); // Step 2: Create an Encoding Job //PART II byte[] keyBytes = Convert.FromBase64String(Constants.WebHookSigningKey); var existingEndpoint = _context.NotificationEndPoints.Where(e => e.Name == "FunctionWebHook3").FirstOrDefault(); INotificationEndPoint endpoint = null; if (existingEndpoint != null) { Console.WriteLine("webhook endpoint already exists"); endpoint = (INotificationEndPoint)existingEndpoint; } else { endpoint = _context.NotificationEndPoints.Create("FunctionWebHook3", NotificationEndPointType.WebHook, Constants.WebHookEndpoint, keyBytes); Console.WriteLine("Notification Endpoint Created with Key : {0}", keyBytes.ToString()); } // Declare a new encoding job with the Standard encoder IJob job = _context.Jobs.Create("Azure Function - MES Job"); // Get a media processor reference, and pass to it the name of the // processor to use for the specific task. IMediaProcessor processor = GetLatestMediaProcessorByName("Media Encoder Standard"); // Create a task with the encoding details, using a custom preset ITask task = job.Tasks.AddNew("Encode with Adaptive Streaming", processor, "Adaptive Streaming", TaskOptions.None); // Specify the input asset to be encoded. task.InputAssets.Add(newAsset); // Add an output asset to contain the results of the job. // This output is specified as AssetCreationOptions.None, which // means the output asset is not encrypted. task.OutputAssets.AddNew(name, AssetCreationOptions.None); // Add the WebHook notification to this Task and request all notification state changes. // Note that you can also add a job level notification // which would be more useful for a job with chained tasks. if (endpoint != null) { task.TaskNotificationSubscriptions.AddNew(NotificationJobState.All, endpoint, true); Console.WriteLine("Created Notification Subscription for endpoint: {0}", _webHookEndpoint); } else { Console.WriteLine("No Notification Endpoint is being used"); } job.Submit(); log.Info("Job Submitted"); Console.WriteLine("Expect WebHook to be triggered for the Job ID: {0}", job.Id); Console.WriteLine("Expect WebHook to be triggered for the Task ID: {0}", task.Id); } catch (Exception ex) { log.Error("ERROR: failed."); log.Info($"StackTrace : {ex.StackTrace}"); throw ex; } }