public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var prefixAssetName = (string)data.prefixAssetName ?? "asset-"; var assetName = (string)data.assetName ?? prefixAssetName + Guid.NewGuid().ToString().Substring(0, 13); List <string> containers = new List <string>(); List <string> containerPaths = new List <string>(); // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } 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; MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region); string storageName = (data.baseStorageName != null) ? (string)data.baseStorageName + config.AzureRegionCode : null; Asset asset = new Asset() { StorageAccountName = storageName, AlternateId = data.alternateId, Description = data.description }; try { asset = client.Assets.CreateOrUpdate(config.ResourceGroup, config.AccountName, assetName, asset); asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName); // Access to container ListContainerSasInput input = new ListContainerSasInput() { Permissions = AssetContainerPermission.Read, ExpiryTime = DateTime.Now.AddMinutes(5).ToUniversalTime() }; var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime); string uploadSasUrl = responseListSas.AssetContainerSasUrls.First(); var sasUri = new Uri(uploadSasUrl); var container = new CloudBlobContainer(sasUri); containerPaths.Add(container.Uri.ToString()); containers.Add(asset.Container); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } } var response = new JObject { { "success", true }, { "assetName", assetName }, { "containerPath", new JArray(containerPaths) }, { "container", new JArray(containers) }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var assetName = (string)data.assetName; if (assetName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON")); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } CopyStatus copyStatus = CopyStatus.Success; 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; MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region); try { var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName); // Access to container ListContainerSasInput input = new ListContainerSasInput() { Permissions = AssetContainerPermission.ReadWrite, ExpiryTime = DateTime.Now.AddHours(6).ToUniversalTime() }; var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime); string uploadSasUrl = responseListSas.AssetContainerSasUrls.First(); var sasUri = new Uri(uploadSasUrl); var destinationBlobContainer = new CloudBlobContainer(sasUri); List <IListBlobItem> blobsresult = new List <IListBlobItem>(); BlobContinuationToken continuationToken = null; do { var responseList = await destinationBlobContainer.ListBlobsSegmentedAsync(null, true, BlobListingDetails.Metadata, null, continuationToken, null, null); continuationToken = responseList.ContinuationToken; blobsresult.AddRange(responseList.Results); }while (continuationToken != null); foreach (var dest in blobsresult) { var destBlob = dest as CloudBlob; await destBlob.FetchAttributesAsync(); if (destBlob.CopyState.Status == CopyStatus.Aborted || destBlob.CopyState.Status == CopyStatus.Failed) { // Log the copy status description for diagnostics and restart copy await destBlob.StartCopyAsync(destBlob.CopyState.Source); copyStatus = CopyStatus.Pending; } else if (destBlob.CopyState.Status == CopyStatus.Pending) { // We need to continue waiting for this pending copy // However, let us log copy state for diagnostics copyStatus = CopyStatus.Pending; } // else we completed this pending copy } } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } } var response = new JObject { { "success", true }, { "copyStatus", copyStatus.ToString() }, { "isRunning", (copyStatus == CopyStatus.Pending) }, { "isSuccessful", (copyStatus == CopyStatus.Success) }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var assetName = (string)data.assetName; if (assetName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON")); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } // semaphore file (json structure) VodSemaphore semaphore = null; if (data.semaphore != null) { semaphore = VodSemaphore.FromJson((string)data.semaphore); } // init default var streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created var uniquenessLocator = streamingLocatorGuid.ToString().Substring(0, 13); var streamingLocatorName = "locator-" + uniquenessLocator; string locatorPath = string.Empty; string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13); // Default content id and semaphare value string irdetoContentId = null; if (semaphore != null && semaphore.DrmContentId != null) // semaphore data has higher priority { irdetoContentId = semaphore.DrmContentId; } else if (data.defaultIrdetoContentId != null) { irdetoContentId = (string)data.defaultIrdetoContentId; } var clientTasks = new List <Task <AssetEntry> >(); foreach (var region in azureRegions) { var task = Task <AssetEntry> .Run(async() => { Asset asset = null; 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; // let's get the asset try { MediaServicesHelpers.LogInformation(log, "Getting asset.", region); asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName); } catch (Exception ex) { throw new Exception("Error when retreving asset by name", ex); } // Locator creation try { StreamingLocator locator = null; locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid); MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region); } catch (Exception ex) { throw new Exception("Error when creating the locator", ex); } // let's build info for the live event and output AssetEntry assetEntry = await GenerateInfoHelpers.GenerateAssetInformation(config, client, asset, semaphore, irdetoContentId, region); var locatorPath2 = assetEntry.StreamingLocators.Where(l => l.StreamingLocatorName == streamingLocatorName).First().Urls.Where(u => u.Protocol == OutputProtocol.SmoothStreaming.ToString()).First().Url; var uriloc = new Uri(locatorPath2); locatorPath = uriloc.Scheme + "://" + uriloc.Host + "/" + uriloc.Segments[1]; if (!await CosmosHelpers.CreateOrUpdateAssetDocument(assetEntry)) { log.LogWarning("Cosmos access not configured."); } return(assetEntry); }); clientTasks.Add(task); } try { Task.WaitAll(clientTasks.ToArray()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } return(new OkObjectResult( JsonConvert.SerializeObject(new VodAssetInfoSimple { CreatedLocatorName = streamingLocatorName, CreatedLocatorPath = locatorPath, Success = true, Asset = clientTasks.Select(i => i.Result).First() }, Formatting.Indented) )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var generalOutputInfos = new List <GeneralOutputInfo>(); var liveEventName = (string)data.liveEventName; if (liveEventName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON")); } // default settings var eventInfoFromCosmos = new LiveEventSettingsInfo { LiveEventName = liveEventName }; // Load config from Cosmos try { var setting = await CosmosHelpers.ReadSettingsDocument(liveEventName); eventInfoFromCosmos = setting ?? eventInfoFromCosmos; if (setting == null) { log.LogWarning("Settings not read from Cosmos."); } } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } // init default var deleteAsset = (data.deleteAsset != null) ? (bool)data.deleteAsset : true; var uniquenessAssets = Guid.NewGuid().ToString().Substring(0, 13); string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13); var manifestName = liveEventName.ToLower(); if (data.archiveWindowLength != null) { eventInfoFromCosmos.ArchiveWindowLength = (int)data.archiveWindowLength; } var cencKey = new StreamingLocatorContentKey(); var cbcsKey = new StreamingLocatorContentKey(); if (!deleteAsset) // we need to regenerate the keys if the user wants to keep the asset as keys cannot be reused for more than one asset { try { ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddEnvironmentVariables() .Build(), null); MediaServicesHelpers.LogInformation(log, "Irdeto call..."); cencKey = await IrdetoHelpers.GenerateAndRegisterCENCKeyToIrdeto(liveEventName, config); cbcsKey = await IrdetoHelpers.GenerateAndRegisterCBCSKeyToIrdeto(liveEventName, config); MediaServicesHelpers.LogInformation(log, "Irdeto call done."); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex, "Irdeto response error")); } } var clientTasks = new List <Task <LiveEventEntry> >(); // list of locators guid for the new locators var locatorGuids = new List <Guid>(); for (int i = 0; i < 10; i++) { locatorGuids.Add(Guid.NewGuid()); } foreach (var region in azureRegions) { var task = Task <LiveEventEntry> .Run(async() => { Asset asset = null; LiveEvent liveEvent = null; LiveOutput liveOutput = null; bool reuseKeys = false; string storageAccountName = null; var streamingLocatorsPolicies = new Dictionary <string, string>(); // locator name, policy name 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; // let's check that the channel exists liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName); if (liveEvent == null) { throw new Exception("Error : live event does not exist !"); } if (liveEvent.ResourceState != LiveEventResourceState.Running && liveEvent.ResourceState != LiveEventResourceState.Stopped) { throw new Exception("Error : live event should be in Running or Stopped state !"); } // get live output(s) - it should be one var myLiveOutputs = client.LiveOutputs.List(config.ResourceGroup, config.AccountName, liveEventName); // get the names of the streaming policies. If not possible, recreate it if (myLiveOutputs.FirstOrDefault() != null) { asset = client.Assets.Get(config.ResourceGroup, config.AccountName, myLiveOutputs.First().AssetName); var streamingLocatorsNames = client.Assets.ListStreamingLocators(config.ResourceGroup, config.AccountName, asset.Name).StreamingLocators.Select(l => l.Name); foreach (var locatorName in streamingLocatorsNames) { var locator = client.StreamingLocators.Get(config.ResourceGroup, config.AccountName, locatorName); if (locator != null) { streamingLocatorsPolicies.Add(locatorName, locator.StreamingPolicyName); if (locator.StreamingPolicyName != PredefinedStreamingPolicy.ClearStreamingOnly) // let's backup the keys to reuse them { if (deleteAsset) // we reuse the keys. Only possible if the previous asset is deleted { reuseKeys = true; var keys = client.StreamingLocators.ListContentKeys(config.ResourceGroup, config.AccountName, locatorName).ContentKeys; cencKey = keys.Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCenc).FirstOrDefault(); cbcsKey = keys.Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCbcs).FirstOrDefault(); } } } } if (streamingLocatorsPolicies.Count == 0) // no way to get the streaming policy, let's read Cosmos or create a new one { MediaServicesHelpers.LogInformation(log, "Trying to read streaming policy from Cosmos.", region); string streamingPolicyName = null; // Load streaming policy info from Cosmos try { var info = await CosmosHelpers.ReadStreamingPolicyDocument(new StreamingPolicyInfo(false) { AMSAccountName = config.AccountName }); if (info == null) { log.LogWarning("Streaming policy not read from Cosmos."); } else { streamingPolicyName = info.StreamingPolicyName; } } catch (Exception ex) { throw new Exception("Error reading Cosmos DB", ex); } // STREAMING POLICY CREATION if (streamingPolicyName == null) // not found in Cosmos let's create a new one { StreamingPolicy streamingPolicy; MediaServicesHelpers.LogInformation(log, "Creating streaming policy.", region); try { streamingPolicy = await IrdetoHelpers.CreateStreamingPolicyIrdeto(config, client, uniquenessPolicyName); streamingLocatorsPolicies.Add("", streamingPolicy.Name); } catch (Exception ex) { throw new Exception("Streaming policy creation error", ex); } try { if (!await CosmosHelpers.CreateOrUpdatePolicyDocument(new StreamingPolicyInfo(false) { AMSAccountName = config.AccountName, StreamingPolicyName = streamingPolicy.Name })) { log.LogWarning("Cosmos access not configured or error."); } } catch (Exception ex) { throw new Exception("Streaming policy write error to Cosmos", ex); } } else { streamingLocatorsPolicies.Add("", streamingPolicyName); } } } // let's purge all live output for now foreach (var p in myLiveOutputs) { var assetName = p.AssetName; var thisAsset = client.Assets.Get(config.ResourceGroup, config.AccountName, p.AssetName); if (thisAsset != null) { storageAccountName = thisAsset.StorageAccountName; // let's backup storage account name to create the new asset here } MediaServicesHelpers.LogInformation(log, "deleting live output : " + p.Name, region); await client.LiveOutputs.DeleteAsync(config.ResourceGroup, config.AccountName, liveEvent.Name, p.Name); if (deleteAsset) { MediaServicesHelpers.LogInformation(log, "deleting asset : " + assetName, region); await client.Assets.DeleteAsync(config.ResourceGroup, config.AccountName, assetName); } } if (liveEvent.ResourceState == LiveEventResourceState.Running) { MediaServicesHelpers.LogInformation(log, "reseting live event : " + liveEvent.Name, region); await client.LiveEvents.ResetAsync(config.ResourceGroup, config.AccountName, liveEvent.Name); } else { MediaServicesHelpers.LogInformation(log, "Skipping the reset of live event " + liveEvent.Name + " as it is stopped.", region); } // LIVE OUTPUT CREATION MediaServicesHelpers.LogInformation(log, "Live output creation...", region); try { MediaServicesHelpers.LogInformation(log, "Asset creation...", region); asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName, "asset-" + uniquenessAssets, new Asset(storageAccountName: storageAccountName)); Hls hlsParam = null; liveOutput = new LiveOutput(asset.Name, TimeSpan.FromMinutes(eventInfoFromCosmos.ArchiveWindowLength), null, "output-" + uniquenessAssets, null, null, manifestName, hlsParam); MediaServicesHelpers.LogInformation(log, "create live output...", region); await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveOutput.Name, liveOutput); } catch (Exception ex) { throw new Exception("live output creation error", ex); } try { // streaming locator(s) creation MediaServicesHelpers.LogInformation(log, "Locator creation...", region); int i = 0; foreach (var entryLocPol in streamingLocatorsPolicies) { StreamingLocator locator = null; var streamingLocatorGuid = locatorGuids[i]; // same locator for the two ouputs if 2 live event namle created var uniquenessLocator = streamingLocatorGuid.ToString().Substring(0, 13); var streamingLocatorName = "locator-" + uniquenessLocator; if (entryLocPol.Value == PredefinedStreamingPolicy.ClearStreamingOnly) { locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid); } else // DRM content { MediaServicesHelpers.LogInformation(log, "creating DRM locator : " + streamingLocatorName, region); if (!reuseKeys) { MediaServicesHelpers.LogInformation(log, "using new keys.", region); locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithNewKeys( config, entryLocPol.Value, streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid); } else // no need to create new keys, let's use the exiting one { MediaServicesHelpers.LogInformation(log, "using existing keys.", region); locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithExistingKeys( config, entryLocPol.Value, streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid); } } MediaServicesHelpers.LogInformation(log, "locator : " + streamingLocatorName, region); i++; } await client.Assets.UpdateAsync(config.ResourceGroup, config.AccountName, asset.Name, asset); } catch (Exception ex) { throw new Exception("locator creation error", ex); } var generalOutputInfo = GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> { liveEvent }); if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0])) { MediaServicesHelpers.LogWarning(log, "Cosmos access not configured.", region); } return(generalOutputInfo.LiveEvents[0]); }); clientTasks.Add(task); } try { Task.WaitAll(clientTasks.ToArray()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } return(new OkObjectResult( JsonConvert.SerializeObject(new GeneralOutputInfo { Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList() }, Formatting.Indented) )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var liveEventName = (string)data.liveEventName; if (liveEventName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON")); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } // init default var uniquenessAssets = Guid.NewGuid().ToString().Substring(0, 13); var streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created var uniquenessLocator = streamingLocatorGuid.ToString().Substring(0, 13); var streamingLocatorName = "locator-" + uniquenessLocator; var manifestName = liveEventName.ToLower(); var clientTasks = new List <Task <LiveEventEntry> >(); foreach (var region in azureRegions) { var task = Task <LiveEventEntry> .Run(async() => { Asset asset = null; LiveOutput liveOutput = null; 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; // let's check that the channel exists var liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName); if (liveEvent == null) { throw new Exception($"Live event {liveEventName} does not exist."); } var outputs = await client.LiveOutputs.ListAsync(config.ResourceGroup, config.AccountName, liveEventName); if (outputs.FirstOrDefault() != null) { liveOutput = outputs.FirstOrDefault(); asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, liveOutput.AssetName); } if (asset == null) { throw new Exception("Error - asset not found"); } try { // streaming locator creation MediaServicesHelpers.LogInformation(log, "Locator creation...", region); var locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid); MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region); if (liveOutput != null) { await client.Assets.UpdateAsync(config.ResourceGroup, config.AccountName, asset.Name, asset); } } catch (Exception ex) { throw new Exception("locator creation error", ex); } // object to store the output of the function var generalOutputInfo = new GeneralOutputInfo(); // let's build info for the live event and output generalOutputInfo = GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> { liveEvent }); if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0])) { MediaServicesHelpers.LogWarning(log, "Cosmos access not configured.", region); } return(generalOutputInfo.LiveEvents[0]); }); clientTasks.Add(task); } try { Task.WaitAll(clientTasks.ToArray()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } return(new OkObjectResult( JsonConvert.SerializeObject(new GeneralOutputInfo { Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList() }, Formatting.Indented) )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var generalOutputInfos = new List <GeneralOutputInfo>(); var assetName = (string)data.assetName; if (assetName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON")); } var fileName = (string)data.fileName; ManifestGenerated smildata = null; VodSemaphore semaphore = null; if (data.semaphore != null) { semaphore = VodSemaphore.FromJson((string)data.semaphore); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } 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; MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region); var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName); if (asset == null) { throw new Exception($"Asset {asset} does not exist."); } // Access to container ListContainerSasInput input = new ListContainerSasInput() { Permissions = AssetContainerPermission.ReadWriteDelete, ExpiryTime = DateTime.Now.AddHours(2).ToUniversalTime() }; var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime); string uploadSasUrl = responseListSas.AssetContainerSasUrls.First(); var sasUri = new Uri(uploadSasUrl); var container = new CloudBlobContainer(sasUri); // Manifest generate smildata = (semaphore == null) ? await ManifestHelpers.LoadAndUpdateManifestTemplate(asset, container, execContext, fileName) : await ManifestHelpers.LoadAndUpdateManifestTemplateUsingSemaphore(semaphore, execContext, fileName); // if not file name passed, then we use the one generated based on mp4 files names if (fileName == null) { fileName = smildata.FileName; } var blob = container.GetBlockBlobReference(fileName); using (Stream s = ManifestHelpers.GenerateStreamFromString(smildata.Content)) { await blob.UploadFromStreamAsync(s); } } var response = new JObject { { "success", true }, { "fileName", fileName }, { "manifestContent", smildata.Content }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var assetNameStartsWith = (string)data.assetNameStartsWith; if (assetNameStartsWith == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetNameStartsWith in the JSON")); } List <string> assets = new List <string>(); // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } 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; MediaServicesHelpers.LogInformation(log, "asset name starts : " + assetNameStartsWith, region); try { ODataQuery <Asset> query = new ODataQuery <Asset>(); string search = "'" + assetNameStartsWith + "'"; query.Filter = "name gt " + search.Substring(0, search.Length - 2) + char.ConvertFromUtf32(char.ConvertToUtf32(search, search.Length - 2) - 1) + new string('z', 262 - search.Length) + "'" + " and name lt " + search.Substring(0, search.Length - 1) + new string('z', 262 - search.Length) + "'"; query.OrderBy = "Properties/Created"; var assetsResult = client.Assets.List(config.ResourceGroup, config.AccountName, query); assets = assetsResult.Select(a => a.Name).ToList(); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } } var response = new JObject { { "success", true }, { "assetNames", new JArray(assets) }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var assetName = (string)data.assetName; if (assetName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON")); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } // semaphore file (json structure) VodSemaphore semaphore = null; if (data.semaphore != null) { semaphore = VodSemaphore.FromJson((string)data.semaphore); } // init default var streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created var uniquenessLocator = streamingLocatorGuid.ToString().Substring(0, 13); var streamingLocatorName = "locator-" + uniquenessLocator; string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13); // useDRM init var useDRM = true; if (data.useDRM != null) { useDRM = (bool)data.useDRM; } else if (semaphore != null & semaphore.ClearStream != null) { useDRM = !(bool)semaphore.ClearStream; } // Default content id and semaphare value string irdetoContentId = null; if (semaphore != null && semaphore.DrmContentId != null) // semaphore data has higher priority { irdetoContentId = semaphore.DrmContentId; } else if (data.defaultIrdetoContentId != null) { irdetoContentId = (string)data.defaultIrdetoContentId; } DateTime?startTime = null; DateTime?endTime = null; try { if (semaphore != null && semaphore.StartTime != null) { startTime = DateTime.ParseExact(semaphore.StartTime, AssetEntry.DateFormat, System.Globalization.CultureInfo.InvariantCulture); } if (semaphore != null && semaphore.EndTime != null) { endTime = DateTime.ParseExact(semaphore.EndTime, AssetEntry.DateFormat, System.Globalization.CultureInfo.InvariantCulture); } } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var cencKey = new StreamingLocatorContentKey(); var cbcsKey = new StreamingLocatorContentKey(); if (useDRM) { try { ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddEnvironmentVariables() .Build(), null); MediaServicesHelpers.LogInformation(log, "Irdeto call..."); cencKey = await IrdetoHelpers.GenerateAndRegisterCENCKeyToIrdeto(irdetoContentId, config); cbcsKey = await IrdetoHelpers.GenerateAndRegisterCBCSKeyToIrdeto(irdetoContentId, config); MediaServicesHelpers.LogInformation(log, "Irdeto call done."); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex, "Irdeto response error")); } } var clientTasks = new List <Task <AssetEntry> >(); foreach (var region in azureRegions) { var task = Task <AssetEntry> .Run(async() => { Asset asset = null; StreamingPolicy streamingPolicy = null; 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; if (useDRM) { MediaServicesHelpers.LogInformation(log, "Trying to read streaming policy from Cosmos.", region); string streamingPolicyName = null; // Load streaming policy info from Cosmos try { var info = await CosmosHelpers.ReadStreamingPolicyDocument(new StreamingPolicyInfo(true) { AMSAccountName = config.AccountName }); if (info == null) { log.LogWarning("Streaming policy not read from Cosmos."); } else { streamingPolicyName = info.StreamingPolicyName; } } catch (Exception ex) { throw new Exception("Error reading Cosmos DB", ex); } // STREAMING POLICY CREATION if (streamingPolicyName == null) // not found in Cosmos let's create a new one { MediaServicesHelpers.LogInformation(log, "Creating streaming policy.", region); try { streamingPolicy = await IrdetoHelpers.CreateStreamingPolicyIrdeto(config, client, uniquenessPolicyName); } catch (Exception ex) { throw new Exception("Streaming policy creation error", ex); } try { if (!await CosmosHelpers.CreateOrUpdatePolicyDocument(new StreamingPolicyInfo(true) { AMSAccountName = config.AccountName, StreamingPolicyName = streamingPolicy.Name })) { log.LogWarning("Cosmos access not configured or error."); } } catch (Exception ex) { throw new Exception("Streaming policy write error to Cosmos", ex); } } else { MediaServicesHelpers.LogInformation(log, "Getting streaming policy in AMS.", region); try { streamingPolicy = await client.StreamingPolicies.GetAsync(config.ResourceGroup, config.AccountName, streamingPolicyName); } catch (Exception ex) { throw new Exception("Error when getting streaming policy " + streamingPolicy, ex); } } } // let's get the asset try { MediaServicesHelpers.LogInformation(log, "Getting asset.", region); asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName); } catch (Exception ex) { throw new Exception("Error when retreving asset by name", ex); } // Locator creation try { StreamingLocator locator = null; if (useDRM) { locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithNewKeys(config, streamingPolicy.Name, streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid, irdetoContentId, startTime, endTime); } else // no DRM { locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid, startTime, endTime); } MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region); } catch (Exception ex) { throw new Exception("Error when creating the locator", ex); } // let's build info for the live event and output AssetEntry assetEntry = await GenerateInfoHelpers.GenerateAssetInformation(config, client, asset, semaphore, irdetoContentId, region); if (!await CosmosHelpers.CreateOrUpdateAssetDocument(assetEntry)) { log.LogWarning("Cosmos access not configured."); } return(assetEntry); }); clientTasks.Add(task); } try { Task.WaitAll(clientTasks.ToArray()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } return(new OkObjectResult( JsonConvert.SerializeObject(new VodAssetInfo { Success = true, Assets = clientTasks.Select(i => i.Result).ToList() }, Formatting.Indented) )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var assetName = (string)data.assetName; if (assetName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON")); } if (data.fileNames == null) { return(IrdetoHelpers.ReturnErrorException(log, "Please pass fileNames in the input object")); } var sourceStorageAccountName = (string)data.sourceStorageAccountName; if (sourceStorageAccountName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceStorageAccountName in the input object")); } var sourceStorageAccountKey = (string)data.sourceStorageAccountKey; if (sourceStorageAccountKey == null) { return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceStorageAccountKey in the input object")); } var sourceContainer = (string)data.sourceContainer; if (sourceContainer == null) { return(IrdetoHelpers.ReturnErrorException(log, "Please pass sourceContainer in the input object")); } bool missingBlob = false; List <string> containers = new List <string>(); List <string> containerPaths = new List <string>(); // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } // Setup blob container CloudBlobContainer sourceBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(sourceStorageAccountName, sourceStorageAccountKey, (string)data.sourceContainer); 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; MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region); try { var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName); // Access to container ListContainerSasInput input = new ListContainerSasInput() { Permissions = AssetContainerPermission.ReadWrite, ExpiryTime = DateTime.Now.AddHours(6).ToUniversalTime() }; var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime); string uploadSasUrl = responseListSas.AssetContainerSasUrls.First(); var sasUri = new Uri(uploadSasUrl); var destinationBlobContainer = new CloudBlobContainer(sasUri); containers.Add(asset.Container); if (data.fileNames != null) { int indexFile = 1; foreach (var file in data.fileNames) { string fileName = (string)file; CloudBlob sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName); if (data.wait != null && (bool)data.wait && (indexFile == 1)) { for (int i = 1; i <= 3; i++) // let's wait 3 times 5 seconds (15 seconds) { if (await sourceBlob.ExistsAsync()) { break; } log.LogInformation("Waiting 5 s..."); System.Threading.Thread.Sleep(5 * 1000); sourceBlob = sourceBlobContainer.GetBlockBlobReference(fileName); } } if (await sourceBlob.ExistsAsync() && sourceBlob.Properties.Length > 0) { if (data.flattenPath != null && (bool)data.flattenPath) { fileName = Path.GetFileName(fileName); } CloudBlob destinationBlob = destinationBlobContainer.GetBlockBlobReference(fileName); CopyBlobHelpers.CopyBlobAsync(sourceBlob, destinationBlob); } else { missingBlob = true; log.LogWarning("Missing blob :" + fileName); } indexFile++; } } containers.Add(asset.Container); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } } var response = new JObject { { "success", true }, { "assetName", assetName }, { "container", new JArray(containers) }, { "missingBlob", missingBlob }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var generalOutputInfos = new List <GeneralOutputInfo>(); var liveEventName = (string)data.liveEventName; if (liveEventName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON")); } var deleteAsset = true; if (data.deleteAsset != null) { deleteAsset = (bool)data.deleteAsset; } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } var clientTasks = new List <Task>(); foreach (var region in azureRegions) { Task task = Task.Run(async() => { Task LiveOutputsDeleteTask = null; Task LiveEventStopTask = null; 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; MediaServicesHelpers.LogInformation(log, "live event : " + liveEventName, region); var liveEvent = client.LiveEvents.Get(config.ResourceGroup, config.AccountName, liveEventName); if (liveEvent == null) { throw new Exception($"Live event {liveEventName} does not exist."); } // let's purge all live output for now var ps = client.LiveOutputs.List(config.ResourceGroup, config.AccountName, liveEventName); foreach (var p in ps) { var assetName = p.AssetName; var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName); // let's store name of the streaming policy string streamingPolicyName = null; var streamingLocatorsNames = client.Assets.ListStreamingLocators(config.ResourceGroup, config.AccountName, assetName).StreamingLocators.Select(l => l.Name); foreach (var locatorName in streamingLocatorsNames) { if (locatorName != null) { var streamingLocator = await client.StreamingLocators.GetAsync(config.ResourceGroup, config.AccountName, locatorName); if (streamingLocator != null) { streamingPolicyName = streamingLocator.StreamingPolicyName; } } } MediaServicesHelpers.LogInformation(log, "deleting live output : " + p.Name, region); LiveOutputsDeleteTask = client.LiveOutputs.DeleteAsync(config.ResourceGroup, config.AccountName, liveEvent.Name, p.Name); if (deleteAsset) { MediaServicesHelpers.LogInformation(log, "deleting asset : " + assetName, region); await client.Assets.DeleteAsync(config.ResourceGroup, config.AccountName, assetName); if (streamingPolicyName != null && streamingPolicyName.StartsWith(liveEventName) ) // let's delete the streaming policy if custom { MediaServicesHelpers.LogInformation(log, "deleting streaming policy : " + streamingPolicyName, region); await client.StreamingPolicies.DeleteAsync(config.ResourceGroup, config.AccountName, streamingPolicyName); } } } if (LiveOutputsDeleteTask != null) { await LiveOutputsDeleteTask; // live output deletion task } if (liveEvent.ResourceState == LiveEventResourceState.Running) { MediaServicesHelpers.LogInformation(log, "stopping live event : " + liveEvent.Name, region); LiveEventStopTask = client.LiveEvents.StopAsync(config.ResourceGroup, config.AccountName, liveEvent.Name); } else if (liveEvent.ResourceState == LiveEventResourceState.Stopping) { var liveevt = liveEvent; while (liveevt.ResourceState == LiveEventResourceState.Stopping) { Thread.Sleep(2000); liveevt = client.LiveEvents.Get(config.ResourceGroup, config.AccountName, liveEvent.Name); } } if (LiveEventStopTask != null) { await LiveEventStopTask; // live event stop task } MediaServicesHelpers.LogInformation(log, "deleting live event : " + liveEventName, region); await client.LiveEvents.DeleteAsync(config.ResourceGroup, config.AccountName, liveEventName); if (!await CosmosHelpers.DeleteGeneralInfoDocument(new LiveEventEntry { LiveEventName = liveEventName, AMSAccountName = config.AccountName })) { MediaServicesHelpers.LogWarning(log, "Error when deleting Cosmos document.", region); } }); clientTasks.Add(task); } try { Task.WaitAll(clientTasks.ToArray()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var response = new JObject { { "liveEventName", liveEventName }, { "success", true }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response.ToString() )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var assetName = (string)data.assetName; if (assetName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON")); } var vttContent = (string)data.vttContent; if (vttContent == null) { return(IrdetoHelpers.ReturnErrorException(log, "Please pass vttContent in the input object")); } var vttFileName = (string)data.vttFileName; if (vttFileName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Please pass vttFileName in the input object")); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } 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; MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, region); try { var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, assetName); // Access to container ListContainerSasInput input = new ListContainerSasInput() { Permissions = AssetContainerPermission.ReadWrite, ExpiryTime = DateTime.Now.AddHours(6).ToUniversalTime() }; var responseListSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, asset.Name, input.Permissions, input.ExpiryTime); string uploadSasUrl = responseListSas.AssetContainerSasUrls.First(); var sasUri = new Uri(uploadSasUrl); var destinationBlobContainer = new CloudBlobContainer(sasUri); var destinationBlob = destinationBlobContainer.GetBlockBlobReference(vttFileName); // Base 64 decoding byte[] dataVtt = Convert.FromBase64String(vttContent); string decodedString = Encoding.UTF8.GetString(dataVtt); // Uploading data await destinationBlob.UploadTextAsync(decodedString); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } } var response = new JObject { { "success", true }, { "assetName", assetName }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var generalOutputInfos = new List <GeneralOutputInfo>(); var liveEventName = (string)data.liveEventName; if (liveEventName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON")); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } var clientTasks = new List <Task <LiveEventEntry> >(); foreach (var region in azureRegions) { var task = Task <LiveEventEntry> .Run(async() => { 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; // LIVE EVENT STOP MediaServicesHelpers.LogInformation(log, "Live event stopping...", region); // let's check that the channel exists var liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName); if (liveEvent == null) { throw new Exception($"Live event {liveEventName} does not exist."); } if (liveEvent.ResourceState == LiveEventResourceState.Stopped) { throw new Exception($"Live event {liveEventName} already stopped !"); } await client.LiveEvents.StopAsync(config.ResourceGroup, config.AccountName, liveEventName); var generalOutputInfo = GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> { liveEvent }); if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0])) { MediaServicesHelpers.LogWarning(log, "Cosmos access not configured.", region); } return(generalOutputInfo.LiveEvents[0]); }); clientTasks.Add(task); } try { Task.WaitAll(clientTasks.ToArray()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } return(new OkObjectResult( JsonConvert.SerializeObject(new GeneralOutputInfo { Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList() }, Formatting.Indented) )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, Microsoft.Azure.WebJobs.ExecutionContext execContext) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var assetName = (string)data.assetName; if (assetName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass assetName in the JSON")); } List <string> fileNames = new List <string>(); ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddEnvironmentVariables() .Build(), null ); MediaServicesHelpers.LogInformation(log, "connecting to AMS account : " + config.AccountName, null); 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; MediaServicesHelpers.LogInformation(log, "asset name : " + assetName, null); Asset asset = new Asset(); try { asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, assetName); ListContainerSasInput input = new ListContainerSasInput() { Permissions = AssetContainerPermission.Read, ExpiryTime = DateTime.Now.AddHours(2).ToUniversalTime() }; var responseAssetContSas = await client.Assets.ListContainerSasAsync(config.ResourceGroup, config.AccountName, assetName, input.Permissions, input.ExpiryTime); string uploadSasUrl = responseAssetContSas.AssetContainerSasUrls.First(); Uri sasUri = new Uri(uploadSasUrl); var container = new CloudBlobContainer(sasUri); BlobContinuationToken continuationToken = null; var blobs = new List <IListBlobItem>(); do { BlobResultSegment segment = await container.ListBlobsSegmentedAsync(null, false, BlobListingDetails.Metadata, null, continuationToken, null, null); blobs.AddRange(segment.Results); foreach (IListBlobItem blob in segment.Results) { if (blob.GetType() == typeof(CloudBlockBlob)) { CloudBlockBlob bl = (CloudBlockBlob)blob; fileNames.Add(bl.Name); } } continuationToken = segment.ContinuationToken; }while (continuationToken != null); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var response = new JObject { { "success", true }, { "assetName", assetName }, { "assetId", asset.AssetId }, { "fileNames", new JArray(fileNames) }, { "container", asset.Container }, { "storageAccountName", asset.StorageAccountName }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var generalOutputInfos = new List <GeneralOutputInfo>(); var liveEventName = (string)data.liveEventName; if (liveEventName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass liveEventName in the JSON")); } // default settings var eventInfoFromCosmos = new LiveEventSettingsInfo() { LiveEventName = liveEventName }; // Load config from Cosmos try { var setting = await CosmosHelpers.ReadSettingsDocument(liveEventName); eventInfoFromCosmos = setting ?? eventInfoFromCosmos; if (setting == null) { log.LogWarning("Settings not read from Cosmos."); } } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } // init default var uniquenessAssets = Guid.NewGuid().ToString().Substring(0, 13); var streamingLocatorGuid = Guid.NewGuid(); // same locator for the two ouputs if 2 live event namle created var uniquenessLocator = streamingLocatorGuid.ToString().Substring(0, 13); var streamingLocatorName = "locator-" + uniquenessLocator; string uniquenessPolicyName = Guid.NewGuid().ToString().Substring(0, 13); var manifestName = liveEventName.ToLower(); var useDRM = data.useDRM != null ? (bool)data.useDRM : true; if (data.archiveWindowLength != null) { eventInfoFromCosmos.ArchiveWindowLength = (int)data.archiveWindowLength; } if (data.inputProtocol != null && ((string)data.inputProtocol).ToUpper() == "RTMP") { eventInfoFromCosmos.InputProtocol = LiveEventInputProtocol.RTMP; } if (data.liveEventAutoStart != null) { eventInfoFromCosmos.AutoStart = (bool)data.liveEventAutoStart; } if (data.InputACL != null) { eventInfoFromCosmos.LiveEventInputACL = (List <string>)data.InputACL; } if (data.PreviewACL != null) { eventInfoFromCosmos.LiveEventPreviewACL = (List <string>)data.PreviewACL; } if (data.lowLatency != null) { eventInfoFromCosmos.LowLatency = (bool)data.lowLatency; } if (data.useStaticHostname != null) { eventInfoFromCosmos.UseStaticHostname = (bool)data.useStaticHostname; } var cencKey = new StreamingLocatorContentKey(); var cbcsKey = new StreamingLocatorContentKey(); if (useDRM) { try { ConfigWrapper config = new ConfigWrapper(new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddEnvironmentVariables() .Build(), null); MediaServicesHelpers.LogInformation(log, "Irdeto call..."); cencKey = await IrdetoHelpers.GenerateAndRegisterCENCKeyToIrdeto(liveEventName, config); cbcsKey = await IrdetoHelpers.GenerateAndRegisterCBCSKeyToIrdeto(liveEventName, config); MediaServicesHelpers.LogInformation(log, "Irdeto call done."); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex, "Irdeto response error")); } } var clientTasks = new List <Task <LiveEventEntry> >(); foreach (var region in azureRegions) { var task = Task <LiveEventEntry> .Run(async() => { Asset asset = null; LiveEvent liveEvent = null; LiveOutput liveOutput = null; StreamingPolicy streamingPolicy = null; string storageName = null; 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); if (eventInfoFromCosmos.BaseStorageName != null) { storageName = eventInfoFromCosmos.BaseStorageName + config.AzureRegionCode; } if (data.storageAccountName != null) { storageName = (string)data.storageAccountName; } 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; // LIVE EVENT CREATION MediaServicesHelpers.LogInformation(log, "Live event creation...", region); // let's check that the channel does not exist already liveEvent = await client.LiveEvents.GetAsync(config.ResourceGroup, config.AccountName, liveEventName); if (liveEvent != null) { throw new Exception("Error : live event already exists !"); } // IP ACL for preview URL var ipsPreview = new List <IPRange>(); if (eventInfoFromCosmos.LiveEventPreviewACL == null || eventInfoFromCosmos.LiveEventPreviewACL.Count == 0) { MediaServicesHelpers.LogInformation(log, "preview all", region); var ip = new IPRange { Name = "AllowAll", Address = IPAddress.Parse("0.0.0.0").ToString(), SubnetPrefixLength = 0 }; ipsPreview.Add(ip); } else { foreach (var ipacl in eventInfoFromCosmos.LiveEventPreviewACL) { var ipaclcomp = ipacl.Split('/'); // notation can be "192.168.0.1" or "192.168.0.1/32" var subnet = ipaclcomp.Count() > 1 ? Convert.ToInt32(ipaclcomp[1]) : 0; var ip = new IPRange { Name = "ip", Address = IPAddress.Parse(ipaclcomp[0]).ToString(), SubnetPrefixLength = subnet }; ipsPreview.Add(ip); } } var liveEventPreview = new LiveEventPreview { AccessControl = new LiveEventPreviewAccessControl(new IPAccessControl(ipsPreview)) }; // IP ACL for input URL var ipsInput = new List <IPRange>(); if (eventInfoFromCosmos.LiveEventInputACL == null || eventInfoFromCosmos.LiveEventInputACL.Count == 0) { MediaServicesHelpers.LogInformation(log, "input all", region); var ip = new IPRange { Name = "AllowAll", Address = IPAddress.Parse("0.0.0.0").ToString(), SubnetPrefixLength = 0 }; ipsInput.Add(ip); } else { foreach (var ipacl in eventInfoFromCosmos.LiveEventInputACL) { var ipaclcomp = ipacl.Split('/'); // notation can be "192.168.0.1" or "192.168.0.1/32" var subnet = ipaclcomp.Count() > 1 ? Convert.ToInt32(ipaclcomp[1]) : 0; var ip = new IPRange { Name = "ip", Address = IPAddress.Parse(ipaclcomp[0]).ToString(), SubnetPrefixLength = subnet }; ipsInput.Add(ip); } } var liveEventInput = new LiveEventInput( eventInfoFromCosmos.InputProtocol, accessControl: new LiveEventInputAccessControl(new IPAccessControl(ipsInput)), accessToken: config.LiveIngestAccessToken ); liveEvent = new LiveEvent( name: liveEventName, location: config.Region, description: "", useStaticHostname: eventInfoFromCosmos.UseStaticHostname, encoding: new LiveEventEncoding { EncodingType = LiveEventEncodingType.None }, input: liveEventInput, preview: liveEventPreview, streamOptions: new List <StreamOptionsFlag?> { // Set this to Default or Low Latency eventInfoFromCosmos.LowLatency?StreamOptionsFlag.LowLatency: StreamOptionsFlag.Default } ); liveEvent = await client.LiveEvents.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveEvent, eventInfoFromCosmos.AutoStart); MediaServicesHelpers.LogInformation(log, "Live event created.", region); if (useDRM) { MediaServicesHelpers.LogInformation(log, "Trying to read streaming policy from Cosmos.", region); string streamingPolicyName = null; // Load streaming policy info from Cosmos try { var info = await CosmosHelpers.ReadStreamingPolicyDocument(new StreamingPolicyInfo(false) { AMSAccountName = config.AccountName }); if (info == null) { log.LogWarning("Streaming policy not read from Cosmos."); } else { streamingPolicyName = info.StreamingPolicyName; } } catch (Exception ex) { throw new Exception("Error reading Cosmos DB", ex); } // STREAMING POLICY CREATION if (streamingPolicyName == null) // not found in Cosmos let's create a new one { MediaServicesHelpers.LogInformation(log, "Creating streaming policy.", region); try { streamingPolicy = await IrdetoHelpers.CreateStreamingPolicyIrdeto(config, client, uniquenessPolicyName); } catch (Exception ex) { throw new Exception("Streaming policy creation error", ex); } try { if (!await CosmosHelpers.CreateOrUpdatePolicyDocument(new StreamingPolicyInfo(false) { AMSAccountName = config.AccountName, StreamingPolicyName = streamingPolicy.Name })) { log.LogWarning("Cosmos access not configured or error."); } } catch (Exception ex) { throw new Exception("Streaming policy write error to Cosmos", ex); } } else { MediaServicesHelpers.LogInformation(log, "Getting streaming policy in AMS.", region); try { streamingPolicy = await client.StreamingPolicies.GetAsync(config.ResourceGroup, config.AccountName, streamingPolicyName); } catch (Exception ex) { throw new Exception("Error when getting streaming policy " + streamingPolicy, ex); } } } // LIVE OUTPUT CREATION MediaServicesHelpers.LogInformation(log, "Live output creation...", region); try { MediaServicesHelpers.LogInformation(log, "Asset creation...", region); asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName, "asset-" + uniquenessAssets, new Asset(storageAccountName: storageName)); Hls hlsParam = null; liveOutput = new LiveOutput(asset.Name, TimeSpan.FromMinutes(eventInfoFromCosmos.ArchiveWindowLength), null, "output-" + uniquenessAssets, null, null, manifestName, hlsParam); //we put the streaming locator in description MediaServicesHelpers.LogInformation(log, "await task...", region); MediaServicesHelpers.LogInformation(log, "create live output...", region); await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveOutput.Name, liveOutput); } catch (Exception ex) { throw new Exception("live output creation error", ex); } try { // let's get the asset // in v3, asset name = asset if in v2 (without prefix) MediaServicesHelpers.LogInformation(log, "Asset configuration.", region); StreamingLocator locator = null; if (useDRM) { locator = await IrdetoHelpers.SetupDRMAndCreateLocatorWithNewKeys(config, streamingPolicy.Name, streamingLocatorName, client, asset, cencKey, cbcsKey, streamingLocatorGuid, liveEventName); } else // no DRM { locator = await IrdetoHelpers.CreateClearLocator(config, streamingLocatorName, client, asset, streamingLocatorGuid); } MediaServicesHelpers.LogInformation(log, "locator : " + locator.Name, region); } catch (Exception ex) { throw new Exception("locator creation error", ex); } // let's build info for the live event and output var generalOutputInfo = GenerateInfoHelpers.GenerateOutputInformation(config, client, new List <LiveEvent> { liveEvent }); if (!await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(generalOutputInfo.LiveEvents[0])) { log.LogWarning("Cosmos access not configured."); } return(generalOutputInfo.LiveEvents[0]); }); clientTasks.Add(task); } try { Task.WaitAll(clientTasks.ToArray()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } return(new OkObjectResult( JsonConvert.SerializeObject(new GeneralOutputInfo { Success = true, LiveEvents = clientTasks.Select(i => i.Result).ToList() }, Formatting.Indented) )); }
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)); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } var streamingLocatorName = (string)data.streamingLocatorName; if (streamingLocatorName == null) { return(IrdetoHelpers.ReturnErrorException(log, "Error - please pass streamingLocatorName in the JSON")); } // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } foreach (var region in azureRegions) { ConfigWrapper config = null; try { config = new ConfigWrapper(new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddEnvironmentVariables() .Build(), region ); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } 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 { client.StreamingLocators.Delete(config.ResourceGroup, config.AccountName, streamingLocatorName); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } } var response = new JObject { { "streamingLocatorName", streamingLocatorName }, { "success", true }, { "operationsVersion", AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Version.ToString() } }; return(new OkObjectResult( response.ToString() )); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { MediaServicesHelpers.LogInformation(log, "C# HTTP trigger function processed a request."); dynamic data; try { data = JsonConvert.DeserializeObject(new StreamReader(req.Body).ReadToEnd()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } ConfigWrapper config = null; var generalOutputInfos = new List <GeneralOutputInfo>(); // Azure region management var azureRegions = new List <string>(); if ((string)data.azureRegion != null) { azureRegions = ((string)data.azureRegion).Split(',').ToList(); } else { azureRegions.Add((string)null); } foreach (var region in azureRegions) { try { config = new ConfigWrapper(new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddEnvironmentVariables() .Build(), region ); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } 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; var liveEvents = client.LiveEvents.List(config.ResourceGroup, config.AccountName); // object to store the output of the function var generalOutputInfo = new GeneralOutputInfo(); // let's list live events try { generalOutputInfo = GenerateInfoHelpers.GenerateOutputInformation(config, client, liveEvents.ToList()); } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } try { var success = new List <bool>(); foreach (var le in generalOutputInfo.LiveEvents) { success.Add(await CosmosHelpers.CreateOrUpdateGeneralInfoDocument(le)); } if (success.Any(b => b == false)) { log.LogWarning("Cosmos access not configured."); } } catch (Exception ex) { return(IrdetoHelpers.ReturnErrorException(log, ex)); } generalOutputInfos.Add(generalOutputInfo); } return(new OkObjectResult( JsonConvert.SerializeObject(new GeneralOutputInfo { Success = true, LiveEvents = generalOutputInfos.SelectMany(i => i.LiveEvents).ToList() }, Formatting.Indented) )); }