/// <summary> /// Get or create a custom streaming policy for FairPlay. /// </summary> /// <param name="client">The Media Services client.</param> /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param> /// <param name="accountName"> The Media Services account name.</param> /// <param name="streamingPolicyName">The streaming policy name.</param> /// <returns>StreamingPolicy</returns> private static async Task <StreamingPolicy> GetOrCreateCustomStreamingPolicyForFairPlay(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string streamingPolicyName) { // In Media Services v3, the Get method on entities will return an ErrorResponseException if the resource is not found. bool createPolicy = false; StreamingPolicy streamingPolicy = null; try { streamingPolicy = await client.StreamingPolicies.GetAsync(resourceGroupName, accountName, streamingPolicyName); Console.WriteLine($"Warning: The streaming policy named {streamingPolicyName} already exists."); } catch (ErrorResponseException ex) when(ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound) { // Content key policy does not exist createPolicy = true; } if (createPolicy) { streamingPolicy = new StreamingPolicy { CommonEncryptionCbcs = new CommonEncryptionCbcs() { Drm = new CbcsDrmConfiguration() { FairPlay = new StreamingPolicyFairPlayConfiguration() { AllowPersistentLicense = true // this enables offline mode } }, EnabledProtocols = new EnabledProtocols() { Hls = true, Dash = true //Even though DASH under CBCS is not supported for either CSF or CMAF, HLS-CMAF-CBCS uses DASH-CBCS fragments in its HLS playlist }, ContentKeys = new StreamingPolicyContentKeys() { //Default key must be specified if keyToTrackMappings is present DefaultKey = new DefaultKey() { Label = "CBCS_DefaultKeyLabel" } } } }; streamingPolicy = await client.StreamingPolicies.CreateAsync(resourceGroupName, accountName, streamingPolicyName, streamingPolicy); } return(streamingPolicy); }
public void StreamingPolicyComboTest() { using (MockContext context = this.StartMockContextAndInitializeClients(this.GetType())) { try { CreateMediaServicesAccount(); // List StreamingPolicies, which should only contain the predefined policies var policies = MediaClient.StreamingPolicies.List(ResourceGroup, AccountName); Assert.Empty(policies.Where(p => !p.Name.StartsWith("Predefined_"))); string policyName = TestUtilities.GenerateName("StreamingPolicy"); // Get the StreamingPolicy, which should not exist StreamingPolicy policy = MediaClient.StreamingPolicies.Get(ResourceGroup, AccountName, policyName); Assert.Null(policy); // Create a new StreamingPolicy string defaultContentKeyPolicyName = null; CommonEncryptionCbcs commonEncryptionCbcs = null; CommonEncryptionCenc commonEncryptionCenc = null; EnvelopeEncryption envelopeEncryption = new EnvelopeEncryption(enabledProtocols: new EnabledProtocols(false, false, true, false)); NoEncryption noEncryption = null; var input = new StreamingPolicy(envelopeEncryption: envelopeEncryption); StreamingPolicy createdPolicy = MediaClient.StreamingPolicies.Create(ResourceGroup, AccountName, policyName, input); ValidateStreamingPolicy(createdPolicy, policyName, defaultContentKeyPolicyName, commonEncryptionCbcs, commonEncryptionCenc, envelopeEncryption, noEncryption); // List StreamingPolicies and validate the newly created one shows up policies = MediaClient.StreamingPolicies.List(ResourceGroup, AccountName); policy = policies.Where(p => !p.Name.StartsWith("Predefined_")).First(); ValidateStreamingPolicy(policy, policyName, defaultContentKeyPolicyName, commonEncryptionCbcs, commonEncryptionCenc, envelopeEncryption, noEncryption); // Get the newly created StreamingPolicy policy = MediaClient.StreamingPolicies.Get(ResourceGroup, AccountName, policyName); Assert.NotNull(policy); ValidateStreamingPolicy(policy, policyName, defaultContentKeyPolicyName, commonEncryptionCbcs, commonEncryptionCenc, envelopeEncryption, noEncryption); // Delete the StreamingPolicy MediaClient.StreamingPolicies.Delete(ResourceGroup, AccountName, policyName); // List StreamingPolicies, which should only contain the predefined policies policies = MediaClient.StreamingPolicies.List(ResourceGroup, AccountName); Assert.Empty(policies.Where(p => !p.Name.StartsWith("Predefined_"))); // Get the StreamingPolicy, which should not exist policy = MediaClient.StreamingPolicies.Get(ResourceGroup, AccountName, policyName); Assert.Null(policy); } finally { DeleteMediaServicesAccount(); } } }
public static async Task <StreamingPolicy> CreateStreamingPolicyIrdeto(ConfigWrapper config, IAzureMediaServicesClient client, string uniqueness = null) { if (uniqueness == null) { uniqueness = Guid.NewGuid().ToString().Substring(0, 13); } var dash_smooth_protocol = new EnabledProtocols(false, true, false, true); var hls_dash_protocol = new EnabledProtocols(false, true, true, false); var cenc_config = new CencDrmConfiguration( new StreamingPolicyPlayReadyConfiguration { CustomLicenseAcquisitionUrlTemplate = config.IrdetoPlayReadyLAURL }, new StreamingPolicyWidevineConfiguration { CustomLicenseAcquisitionUrlTemplate = config.IrdetoWidevineLAURL } ); var cbcs_config = new CbcsDrmConfiguration( new StreamingPolicyFairPlayConfiguration { CustomLicenseAcquisitionUrlTemplate = config.IrdetoFairPlayLAURL } ); var ContentKeysEnc = new StreamingPolicyContentKeys { DefaultKey = new DefaultKey { Label = labelCenc } }; var ContentKeysCbcsc = new StreamingPolicyContentKeys { DefaultKey = new DefaultKey { Label = labelCbcs } }; var cenc = new CommonEncryptionCenc(dash_smooth_protocol, null, ContentKeysEnc, cenc_config); var cbcs = new CommonEncryptionCbcs(hls_dash_protocol, null, ContentKeysCbcsc, cbcs_config); var policyName = uniqueness; var streamingPolicy = new StreamingPolicy(Guid.NewGuid().ToString(), policyName, null, DateTime.Now, null, null, cenc, cbcs, null); streamingPolicy = await client.StreamingPolicies.CreateAsync(config.ResourceGroup, config.AccountName, policyName, streamingPolicy); return(streamingPolicy); }
internal static void ValidateStreamingPolicy( StreamingPolicy policy, string expectedName, string expectedDefaultContentKeyPolicyName, CommonEncryptionCbcs expectedCommonEncryptionCbcs, CommonEncryptionCenc expectedCommonEncryptionCenc, EnvelopeEncryption expectedEnvelopeEncryption, NoEncryption expectedNoEncryption) { Assert.Equal(expectedName, policy.Name); Assert.Equal(expectedDefaultContentKeyPolicyName, policy.DefaultContentKeyPolicyName); Assert.False(string.IsNullOrEmpty(policy.Id)); if (expectedCommonEncryptionCbcs == null) { Assert.Null(policy.CommonEncryptionCbcs); } else { ValidateEnabledProtocols(expectedCommonEncryptionCbcs.EnabledProtocols, policy.CommonEncryptionCbcs.EnabledProtocols); } if (expectedCommonEncryptionCenc == null) { Assert.Null(policy.CommonEncryptionCenc); } else { ValidateEnabledProtocols(expectedCommonEncryptionCenc.EnabledProtocols, policy.CommonEncryptionCenc.EnabledProtocols); } if (expectedEnvelopeEncryption == null) { Assert.Null(policy.EnvelopeEncryption); } else { ValidateEnabledProtocols(expectedEnvelopeEncryption.EnabledProtocols, policy.EnvelopeEncryption.EnabledProtocols); } if (expectedNoEncryption == null) { Assert.Null(policy.NoEncryption); } else { ValidateEnabledProtocols(expectedNoEncryption.EnabledProtocols, policy.NoEncryption.EnabledProtocols); } }
/// <summary> /// Creates a StreamingLocator for the specified asset and with the specified streaming policy name. /// Once the StreamingLocator is created the output asset is available to clients for playback. /// </summary> /// <param name="client">The Media Services client.</param> /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param> /// <param name="accountName"> The Media Services account name.</param> /// <param name="assetName">The name of the output asset.</param> /// <param name="locatorName">The StreamingLocator name (unique in this case).</param> /// <returns></returns> private static async Task <StreamingLocator> CreateStreamingLocatorAsync( IAzureMediaServicesClient client, string resourceGroup, string accountName, string assetName, string locatorName, string contentPolicyName) { StreamingLocator locator; // Let's check if the locator exists already try { locator = await client.StreamingLocators.GetAsync(resourceGroup, accountName, locatorName); } catch (ErrorResponseException ex) when(ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound) { // Name collision! This should not happen in this sample. If it does happen, in order to get the sample to work, // let's just go ahead and create a unique name. // Note that the returned locatorName can have a different name than the one specified as an input parameter. // You may want to update this part to throw an Exception instead, and handle name collisions differently. Console.WriteLine("Warning – found an existing Streaming Locator with name = " + locatorName); string uniqueness = $"-{Guid.NewGuid():N}"; locatorName += uniqueness; Console.WriteLine("Creating a Streaming Locator with this name instead: " + locatorName); } StreamingPolicy customStreamingPolicy = await GetOrCreateCustomStreamingPolicyForFairPlay(client, resourceGroup, accountName, FairPlayStreamingPolicyName); Console.WriteLine("Creating a streaming locator..."); locator = await client.StreamingLocators.CreateAsync( resourceGroup, accountName, locatorName, new StreamingLocator { AssetName = assetName, StreamingPolicyName = customStreamingPolicy.Name, // Custom StreamingPolicy DefaultContentKeyPolicyName = contentPolicyName }); return(locator); }
/// <summary> /// Get or create a custom streaming policy for FairPlay. /// </summary> /// <param name="client">The Media Services client.</param> /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param> /// <param name="accountName"> The Media Services account name.</param> /// <param name="streamingPolicyName">The streaming policy name.</param> /// <returns>StreamingPolicy</returns> private static async Task <StreamingPolicy> GetOrCreateCustomStreamingPloliyForFairPlay(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string streamingPolicyName) { StreamingPolicy streamingPolicy = await client.StreamingPolicies.GetAsync(resourceGroupName, accountName, streamingPolicyName); if (streamingPolicy == null) { streamingPolicy = new StreamingPolicy { CommonEncryptionCbcs = new CommonEncryptionCbcs() { Drm = new CbcsDrmConfiguration() { FairPlay = new StreamingPolicyFairPlayConfiguration() { AllowPersistentLicense = true // this enables offline mode } }, EnabledProtocols = new EnabledProtocols() { Hls = true, Dash = true //Even though DASH under CBCS is not supported for either CSF or CMAF, HLS-CMAF-CBCS uses DASH-CBCS fragments in its HLS playlist }, ContentKeys = new StreamingPolicyContentKeys() { //Default key must be specified if keyToTrackMappings is present DefaultKey = new DefaultKey() { Label = "CBCS_DefaultKeyLabel" } } } }; streamingPolicy = await client.StreamingPolicies.CreateAsync(resourceGroupName, accountName, streamingPolicyName, streamingPolicy); } return(streamingPolicy); }
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) )); }
/// <summary> /// Create a Streaming Policy /// </summary> /// <remarks> /// Create a Streaming Policy in the Media Services account /// </remarks> /// <param name='resourceGroupName'> /// The name of the resource group within the Azure subscription. /// </param> /// <param name='accountName'> /// The Media Services account name. /// </param> /// <param name='streamingPolicyName'> /// The Streaming Policy name. /// </param> /// <param name='parameters'> /// The request parameters /// </param> /// <param name='customHeaders'> /// Headers that will be added to request. /// </param> /// <param name='cancellationToken'> /// The cancellation token. /// </param> /// <exception cref="ApiErrorException"> /// Thrown when the operation returned an invalid status code /// </exception> /// <exception cref="SerializationException"> /// Thrown when unable to deserialize the response /// </exception> /// <exception cref="ValidationException"> /// Thrown when a required parameter is null /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown when a required parameter is null /// </exception> /// <return> /// A response object containing the response body and response headers. /// </return> public async Task <AzureOperationResponse <StreamingPolicy> > CreateWithHttpMessagesAsync(string resourceGroupName, string accountName, string streamingPolicyName, StreamingPolicy parameters, Dictionary <string, List <string> > customHeaders = null, CancellationToken cancellationToken = default(CancellationToken)) { if (Client.SubscriptionId == null) { throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.SubscriptionId"); } if (resourceGroupName == null) { throw new ValidationException(ValidationRules.CannotBeNull, "resourceGroupName"); } if (accountName == null) { throw new ValidationException(ValidationRules.CannotBeNull, "accountName"); } if (streamingPolicyName == null) { throw new ValidationException(ValidationRules.CannotBeNull, "streamingPolicyName"); } if (parameters == null) { throw new ValidationException(ValidationRules.CannotBeNull, "parameters"); } if (parameters != null) { parameters.Validate(); } string apiVersion = "2020-05-01"; // Tracing bool _shouldTrace = ServiceClientTracing.IsEnabled; string _invocationId = null; if (_shouldTrace) { _invocationId = ServiceClientTracing.NextInvocationId.ToString(); Dictionary <string, object> tracingParameters = new Dictionary <string, object>(); tracingParameters.Add("resourceGroupName", resourceGroupName); tracingParameters.Add("accountName", accountName); tracingParameters.Add("streamingPolicyName", streamingPolicyName); tracingParameters.Add("parameters", parameters); tracingParameters.Add("apiVersion", apiVersion); tracingParameters.Add("cancellationToken", cancellationToken); ServiceClientTracing.Enter(_invocationId, this, "Create", tracingParameters); } // Construct URL var _baseUrl = Client.BaseUri.AbsoluteUri; var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Media/mediaServices/{accountName}/streamingPolicies/{streamingPolicyName}").ToString(); _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(Client.SubscriptionId)); _url = _url.Replace("{resourceGroupName}", System.Uri.EscapeDataString(resourceGroupName)); _url = _url.Replace("{accountName}", System.Uri.EscapeDataString(accountName)); _url = _url.Replace("{streamingPolicyName}", System.Uri.EscapeDataString(streamingPolicyName)); List <string> _queryParameters = new List <string>(); if (apiVersion != null) { _queryParameters.Add(string.Format("api-version={0}", System.Uri.EscapeDataString(apiVersion))); } if (_queryParameters.Count > 0) { _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters); } // Create HTTP transport objects var _httpRequest = new HttpRequestMessage(); HttpResponseMessage _httpResponse = null; _httpRequest.Method = new HttpMethod("PUT"); _httpRequest.RequestUri = new System.Uri(_url); // Set Headers if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value) { _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString()); } if (Client.AcceptLanguage != null) { if (_httpRequest.Headers.Contains("accept-language")) { _httpRequest.Headers.Remove("accept-language"); } _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage); } if (customHeaders != null) { foreach (var _header in customHeaders) { if (_httpRequest.Headers.Contains(_header.Key)) { _httpRequest.Headers.Remove(_header.Key); } _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value); } } // Serialize Request string _requestContent = null; if (parameters != null) { _requestContent = Rest.Serialization.SafeJsonConvert.SerializeObject(parameters, Client.SerializationSettings); _httpRequest.Content = new StringContent(_requestContent, System.Text.Encoding.UTF8); _httpRequest.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); } // Set Credentials if (Client.Credentials != null) { cancellationToken.ThrowIfCancellationRequested(); await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false); } // Send Request if (_shouldTrace) { ServiceClientTracing.SendRequest(_invocationId, _httpRequest); } cancellationToken.ThrowIfCancellationRequested(); _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false); if (_shouldTrace) { ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse); } HttpStatusCode _statusCode = _httpResponse.StatusCode; cancellationToken.ThrowIfCancellationRequested(); string _responseContent = null; if ((int)_statusCode != 201) { var ex = new ApiErrorException(string.Format("Operation returned an invalid status code '{0}'", _statusCode)); try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); ApiError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject <ApiError>(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex.Body = _errorBody; } } catch (JsonException) { // Ignore the exception } ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent); ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent); if (_shouldTrace) { ServiceClientTracing.Error(_invocationId, ex); } _httpRequest.Dispose(); if (_httpResponse != null) { _httpResponse.Dispose(); } throw ex; } // Create Result var _result = new AzureOperationResponse <StreamingPolicy>(); _result.Request = _httpRequest; _result.Response = _httpResponse; if (_httpResponse.Headers.Contains("x-ms-request-id")) { _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault(); } // Deserialize Response if ((int)_statusCode == 201) { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject <StreamingPolicy>(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { _httpRequest.Dispose(); if (_httpResponse != null) { _httpResponse.Dispose(); } throw new SerializationException("Unable to deserialize the response.", _responseContent, ex); } } if (_shouldTrace) { ServiceClientTracing.Exit(_invocationId, _result); } return(_result); }
public static async Task <AssetEntry> GenerateAssetInformation(ConfigWrapper config, IAzureMediaServicesClient client, Asset asset, VodSemaphore semaphore, string contentId = null, string region = null) { var assetEntry = new AssetEntry() { AMSAccountName = config.AccountName, Region = config.Region, ResourceGroup = config.ResourceGroup, AssetStorageAccountName = asset?.StorageAccountName, AssetName = asset.Name, Urn = semaphore?.Urn, Semaphore = semaphore, StreamingLocators = new List <StreamingLocatorEntry>(), CreatedTime = asset.Created.ToUniversalTime().ToString(AssetEntry.DateFormat), ContentId = contentId, }; var urls = new List <OutputUrl>(); string streamingPolicyName = null; StreamingPolicy streamingPolicy = null; var streamingLocatorsNames = client.Assets.ListStreamingLocators(config.ResourceGroup, config.AccountName, asset.Name).StreamingLocators.Select(l => l.Name); foreach (var locatorName in streamingLocatorsNames) { string cenckeyId = null; string cbcskeyId = null; StreamingLocator streamingLocator = null; if (locatorName != null) { streamingLocator = client.StreamingLocators.Get(config.ResourceGroup, config.AccountName, locatorName); if (streamingLocator != null) { streamingPolicyName = streamingLocator.StreamingPolicyName; if (streamingLocator.ContentKeys .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCenc) .FirstOrDefault() != null && streamingLocator.ContentKeys .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCbcs) .FirstOrDefault() != null) { cenckeyId = streamingLocator.ContentKeys .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCenc) .FirstOrDefault().Id.ToString(); cbcskeyId = streamingLocator.ContentKeys .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCbcs) .FirstOrDefault().Id.ToString(); } // let's get the manifest name string manifestName = null; List <IListBlobItem> blobs = new List <IListBlobItem>(); try { ListContainerSasInput input = new ListContainerSasInput() { Permissions = AssetContainerPermission.Read, ExpiryTime = DateTime.Now.AddHours(2).ToUniversalTime() }; var responseListSas = client.Assets.ListContainerSas(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); BlobContinuationToken continuationToken = null; do { var response = await container.ListBlobsSegmentedAsync(continuationToken); continuationToken = response.ContinuationToken; blobs.AddRange(response.Results); }while (continuationToken != null); // let's take the first manifest file. It should exist manifestName = blobs.Where(b => (b.GetType() == typeof(CloudBlockBlob))).Select(b => (CloudBlockBlob)b).Where(b => b.Name.ToLower().EndsWith(".ism")).FirstOrDefault().Name; } catch { } if (manifestName != null) // there is a manifest { urls = MediaServicesHelpers.GetUrls(config, client, streamingLocator, manifestName, true, true, true, true, true); } else // no manifest { urls = MediaServicesHelpers.GetDownloadUrls(config, client, streamingLocator, blobs); } } } if (streamingPolicyName != null) { streamingPolicy = client.StreamingPolicies.Get(config.ResourceGroup, config.AccountName, streamingPolicyName); } var drmlist = new List <Drm>(); if (streamingPolicy != null) { if (streamingPolicy.CommonEncryptionCbcs != null) { var enProt = MediaServicesHelpers.ReturnOutputProtocolsListCbcs(streamingPolicy .CommonEncryptionCbcs.EnabledProtocols); drmlist.Add(new Drm { Type = "FairPlay", LicenseUrl = streamingPolicy?.CommonEncryptionCbcs?.Drm.FairPlay .CustomLicenseAcquisitionUrlTemplate.Replace("{ContentKeyId}", cbcskeyId).Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId), Protocols = enProt, CertificateUrl = config.IrdetoFairPlayCertificateUrl }); } if (streamingPolicy.CommonEncryptionCenc != null) { var enProtW = MediaServicesHelpers.ReturnOutputProtocolsListCencWidevine(streamingPolicy .CommonEncryptionCbcs.EnabledProtocols); var enProtP = MediaServicesHelpers.ReturnOutputProtocolsListCencPlayReady(streamingPolicy .CommonEncryptionCbcs.EnabledProtocols); drmlist.Add(new Drm { Type = "PlayReady", LicenseUrl = streamingPolicy?.CommonEncryptionCenc?.Drm.PlayReady .CustomLicenseAcquisitionUrlTemplate.Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId), Protocols = enProtP }); drmlist.Add(new Drm { Type = "Widevine", LicenseUrl = streamingPolicy?.CommonEncryptionCenc?.Drm.Widevine .CustomLicenseAcquisitionUrlTemplate.Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId), Protocols = enProtW }); } } var StreamingLocatorInfo = new StreamingLocatorEntry { StreamingLocatorName = locatorName, StreamingPolicyName = streamingPolicyName, CencKeyId = cenckeyId, CbcsKeyId = cbcskeyId, Drm = drmlist, Urls = urls.Select(url => new UrlEntry { Protocol = url.Protocol.ToString(), Url = url.Url }) .ToList() }; assetEntry.StreamingLocators.Add(StreamingLocatorInfo); } return(assetEntry); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation($"AMS v3 Function - CreateStreamingPolicy was triggered!"); string requestBody = new StreamReader(req.Body).ReadToEnd(); dynamic data = JsonConvert.DeserializeObject(requestBody); if (data.streamingPolicyName == null) { return(new BadRequestObjectResult("Please pass streamingPolicyName in the input object")); } if (data.defaultContentKeyPolicyName == null) { return(new BadRequestObjectResult("Please pass defaultContentKeyPolicyName in the input object")); } string streamingPolicyName = data.streamingPolicyName; string defaultContentKeyPolicyName = data.defaultContentKeyPolicyName; string mode = data.mode; if (mode != "simple" && mode != "advanced") { return(new BadRequestObjectResult("Please pass valid mode in the input object")); } // // Simple Mode // if (mode == "simple") { if (data.noEncryptionProtocols == null && data.cbcsProtocols == null && data.cencProtocols == null && data.envelopeProtocols == null) { return(new BadRequestObjectResult("Please pass one protocol for any encryption scheme at least in the input object")); } } // // Advanced Mode // if (mode == "advanced") { if (data.jsonNoEncryption == null && data.jsonCommonEncryptionCbcs == null && data.jsonCommonEncryptionCenc == null && data.jsonEnvelopeEncryption == null) { return(new BadRequestObjectResult("Please pass one encryption scheme JSON at least in the input object")); } } MediaServicesConfigWrapper amsconfig = new MediaServicesConfigWrapper(); StreamingPolicy policy = null; JsonConverter[] jsonReaders = { new MediaServicesHelperJsonReader(), new MediaServicesHelperTimeSpanJsonConverter() }; try { IAzureMediaServicesClient client = MediaServicesHelper.CreateMediaServicesClientAsync(amsconfig); policy = client.StreamingPolicies.Get(amsconfig.ResourceGroup, amsconfig.AccountName, streamingPolicyName); if (policy == null) { StreamingPolicy parameters = new StreamingPolicy(); parameters.DefaultContentKeyPolicyName = defaultContentKeyPolicyName; if (mode == "simple") { // NoEncryption Arguments if (data.noEncryptionProtocols != null) { String[] noEncryptionProtocols = data.noEncryptionProtocols.ToString().Split(';'); if (Array.IndexOf(noEncryptionProtocols, "Dash") > -1) { parameters.NoEncryption.EnabledProtocols.Dash = true; } if (Array.IndexOf(noEncryptionProtocols, "Download") > -1) { parameters.NoEncryption.EnabledProtocols.Download = true; } if (Array.IndexOf(noEncryptionProtocols, "Hls") > -1) { parameters.NoEncryption.EnabledProtocols.Hls = true; } if (Array.IndexOf(noEncryptionProtocols, "SmoothStreaming") > -1) { parameters.NoEncryption.EnabledProtocols.SmoothStreaming = true; } } // Common Encryption CBCS Argument if (data.cbcsClearTracks != null) { List <TrackSelection> tracks = JsonConvert.DeserializeObject <List <TrackSelection> >(data.cbcsClearTracks.ToString(), jsonReaders); parameters.CommonEncryptionCbcs.ClearTracks = tracks; } if (data.cbcsDefaultKeyLabel != null) { parameters.CommonEncryptionCbcs.ContentKeys.DefaultKey.Label = data.cbcsDefaultKeyLabel; } if (data.cbcsDefaultKeyPolicyName != null) { parameters.CommonEncryptionCbcs.ContentKeys.DefaultKey.PolicyName = data.cbcsDefaultKeyPolicyName; } if (data.cbcsClearTracks != null) { List <StreamingPolicyContentKey> mappings = JsonConvert.DeserializeObject <List <StreamingPolicyContentKey> >(data.cbcsKeyToTrackMappings.ToString(), jsonReaders); parameters.CommonEncryptionCbcs.ContentKeys.KeyToTrackMappings = mappings; } if (data.cbcsFairPlayTemplate != null) { parameters.CommonEncryptionCbcs.Drm.FairPlay.CustomLicenseAcquisitionUrlTemplate = data.cbcsFairPlayTemplate; } if (data.cbcsFairPlayAllowPersistentLicense != null) { parameters.CommonEncryptionCbcs.Drm.FairPlay.AllowPersistentLicense = data.cbcsFairPlayAllowPersistentLicense; } if (data.cbcsPlayReadyTemplate != null) { parameters.CommonEncryptionCbcs.Drm.PlayReady.CustomLicenseAcquisitionUrlTemplate = data.cbcsPlayReadyTemplate; } if (data.cbcsPlayReadyAttributes != null) { parameters.CommonEncryptionCbcs.Drm.PlayReady.PlayReadyCustomAttributes = data.cbcsPlayReadyAttributes; } if (data.cbcsWidevineTemplate != null) { parameters.CommonEncryptionCbcs.Drm.Widevine.CustomLicenseAcquisitionUrlTemplate = data.cbcsWidevineTemplate; } if (data.cbcsProtocols != null) { String[] commonEncryptionCbcsProtocols = data.cbcsProtocols.ToString().Split(';'); if (Array.IndexOf(commonEncryptionCbcsProtocols, "Dash") > -1) { parameters.CommonEncryptionCbcs.EnabledProtocols.Dash = true; } if (Array.IndexOf(commonEncryptionCbcsProtocols, "Download") > -1) { parameters.CommonEncryptionCbcs.EnabledProtocols.Download = true; } if (Array.IndexOf(commonEncryptionCbcsProtocols, "Hls") > -1) { parameters.CommonEncryptionCbcs.EnabledProtocols.Hls = true; } if (Array.IndexOf(commonEncryptionCbcsProtocols, "SmoothStreaming") > -1) { parameters.CommonEncryptionCbcs.EnabledProtocols.SmoothStreaming = true; } } // Common Encryption CENC Argument if (data.cencClearTracks != null) { List <TrackSelection> tracks = JsonConvert.DeserializeObject <List <TrackSelection> >(data.cencClearTracks.ToString(), jsonReaders); parameters.CommonEncryptionCenc.ClearTracks = tracks; } if (data.cencDefaultKeyLabel != null) { parameters.CommonEncryptionCenc.ContentKeys.DefaultKey.Label = data.cencDefaultKeyLabel; } if (data.cencDefaultKeyPolicyName != null) { parameters.CommonEncryptionCenc.ContentKeys.DefaultKey.PolicyName = data.cencDefaultKeyPolicyName; } if (data.cencClearTracks != null) { List <StreamingPolicyContentKey> mappings = JsonConvert.DeserializeObject <List <StreamingPolicyContentKey> >(data.cencKeyToTrackMappings.ToString(), jsonReaders); parameters.CommonEncryptionCenc.ContentKeys.KeyToTrackMappings = mappings; } if (data.cencPlayReadyTemplate != null) { parameters.CommonEncryptionCenc.Drm.PlayReady.CustomLicenseAcquisitionUrlTemplate = data.cencPlayReadyTemplate; } if (data.cencPlayReadyAttributes != null) { parameters.CommonEncryptionCenc.Drm.PlayReady.PlayReadyCustomAttributes = data.cencPlayReadyAttributes; } if (data.cencWidevineTemplate != null) { parameters.CommonEncryptionCenc.Drm.Widevine.CustomLicenseAcquisitionUrlTemplate = data.cencWidevineTemplate; } if (data.cencProtocols != null) { String[] commonEncryptionCencProtocols = data.cencProtocols.ToString().Split(';'); if (Array.IndexOf(commonEncryptionCencProtocols, "Dash") > -1) { parameters.CommonEncryptionCenc.EnabledProtocols.Dash = true; } if (Array.IndexOf(commonEncryptionCencProtocols, "Download") > -1) { parameters.CommonEncryptionCenc.EnabledProtocols.Download = true; } if (Array.IndexOf(commonEncryptionCencProtocols, "Hls") > -1) { parameters.CommonEncryptionCenc.EnabledProtocols.Hls = true; } if (Array.IndexOf(commonEncryptionCencProtocols, "SmoothStreaming") > -1) { parameters.CommonEncryptionCenc.EnabledProtocols.SmoothStreaming = true; } } // Envelope Encryption Argument if (data.envelopeClearTracks != null || data.envelopeDefaultKeyLabel != null || data.envelopeDefaultKeyPolicyName != null || data.envelopeClearTracks || data.envelopeTemplate != null || data.envelopeTemplate != null || data.envelopeProtocols != null) { parameters.EnvelopeEncryption = new EnvelopeEncryption(); if (data.envelopeClearTracks != null) { List <TrackSelection> tracks = JsonConvert.DeserializeObject <List <TrackSelection> >(data.envelopeClearTracks.ToString(), jsonReaders); parameters.EnvelopeEncryption.ClearTracks = tracks; } parameters.EnvelopeEncryption.ContentKeys = new StreamingPolicyContentKeys(); parameters.EnvelopeEncryption.ContentKeys.DefaultKey = new DefaultKey(data.envelopeDefaultKeyLabel as string, data.envelopeDefaultKeyPolicyName as string); if (data.envelopeClearTracks != null) { List <StreamingPolicyContentKey> mappings = JsonConvert.DeserializeObject <List <StreamingPolicyContentKey> >(data.envelopeKeyToTrackMappings.ToString(), jsonReaders); parameters.EnvelopeEncryption.ContentKeys.KeyToTrackMappings = mappings; } if (data.envelopeTemplate != null) { parameters.EnvelopeEncryption.CustomKeyAcquisitionUrlTemplate = data.envelopeTemplate; } if (data.envelopeProtocols != null) { parameters.EnvelopeEncryption.EnabledProtocols = new EnabledProtocols(); String[] envelopeEncryptionProtocols = data.envelopeProtocols.ToString().Split(';'); if (Array.IndexOf(envelopeEncryptionProtocols, "Dash") > -1) { parameters.EnvelopeEncryption.EnabledProtocols.Dash = true; } if (Array.IndexOf(envelopeEncryptionProtocols, "Download") > -1) { parameters.EnvelopeEncryption.EnabledProtocols.Download = true; } if (Array.IndexOf(envelopeEncryptionProtocols, "Hls") > -1) { parameters.EnvelopeEncryption.EnabledProtocols.Hls = true; } if (Array.IndexOf(envelopeEncryptionProtocols, "SmoothStreaming") > -1) { parameters.EnvelopeEncryption.EnabledProtocols.SmoothStreaming = true; } } } } else if (mode == "advanced") { NoEncryption noEncryptionArguments = null; CommonEncryptionCbcs commonEncryptionCbcsArguments = null; CommonEncryptionCenc commonEncryptionCencArguments = null; EnvelopeEncryption envelopeEncryptionArguments = null; if (data.jsonNoEncryption != null) { noEncryptionArguments = JsonConvert.DeserializeObject <NoEncryption>(data.configNoEncryption.ToString(), jsonReaders); } if (data.jsonCommonEncryptionCbcs != null) { commonEncryptionCbcsArguments = JsonConvert.DeserializeObject <CommonEncryptionCbcs>(data.jsonCommonEncryptionCbcs.ToString(), jsonReaders); } if (data.jsonCommonEncryptionCenc != null) { commonEncryptionCencArguments = JsonConvert.DeserializeObject <CommonEncryptionCenc>(data.jsonCommonEncryptionCenc.ToString(), jsonReaders); } if (data.jsonEnvelopeEncryption != null) { envelopeEncryptionArguments = JsonConvert.DeserializeObject <EnvelopeEncryption>(data.jsonEnvelopeEncryption.ToString(), jsonReaders); } parameters.NoEncryption = noEncryptionArguments; parameters.CommonEncryptionCbcs = commonEncryptionCbcsArguments; parameters.CommonEncryptionCenc = commonEncryptionCencArguments; parameters.EnvelopeEncryption = envelopeEncryptionArguments; } parameters.Validate(); policy = client.StreamingPolicies.Create(amsconfig.ResourceGroup, amsconfig.AccountName, streamingPolicyName, parameters); } } 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)); } return((ActionResult) new OkObjectResult(new { streamingPolicyName = streamingPolicyName, streamingPolicyId = policy.Id })); }
/// <summary> /// Create a Streaming Policy /// </summary> /// <remarks> /// Create a Streaming Policy in the Media Services account /// </remarks> /// <param name='operations'> /// The operations group for this extension method. /// </param> /// <param name='resourceGroupName'> /// The name of the resource group within the Azure subscription. /// </param> /// <param name='accountName'> /// The Media Services account name. /// </param> /// <param name='streamingPolicyName'> /// The Streaming Policy name. /// </param> /// <param name='parameters'> /// The request parameters /// </param> /// <param name='cancellationToken'> /// The cancellation token. /// </param> public static async Task <StreamingPolicy> CreateAsync(this IStreamingPoliciesOperations operations, string resourceGroupName, string accountName, string streamingPolicyName, StreamingPolicy parameters, CancellationToken cancellationToken = default(CancellationToken)) { using (var _result = await operations.CreateWithHttpMessagesAsync(resourceGroupName, accountName, streamingPolicyName, parameters, null, cancellationToken).ConfigureAwait(false)) { return(_result.Body); } }
/// <summary> /// Create a Streaming Policy /// </summary> /// <remarks> /// Create a Streaming Policy in the Media Services account /// </remarks> /// <param name='operations'> /// The operations group for this extension method. /// </param> /// <param name='resourceGroupName'> /// The name of the resource group within the Azure subscription. /// </param> /// <param name='accountName'> /// The Media Services account name. /// </param> /// <param name='streamingPolicyName'> /// The Streaming Policy name. /// </param> /// <param name='parameters'> /// The request parameters /// </param> public static StreamingPolicy Create(this IStreamingPoliciesOperations operations, string resourceGroupName, string accountName, string streamingPolicyName, StreamingPolicy parameters) { return(operations.CreateAsync(resourceGroupName, accountName, streamingPolicyName, parameters).GetAwaiter().GetResult()); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation($"AMS v3 Function - PublishAsset was triggered!"); string requestBody = new StreamReader(req.Body).ReadToEnd(); dynamic data = JsonConvert.DeserializeObject(requestBody); // Validate input objects if (data.assetName == null) { return(new BadRequestObjectResult("Please pass assetName in the input object")); } if (data.streamingPolicyName == null) { return(new BadRequestObjectResult("Please pass streamingPolicyName in the input object")); } string assetName = data.assetName; string streamingPolicyName = data.streamingPolicyName; string alternativeMediaId = null; if (data.alternativeMediaId != null) { alternativeMediaId = data.alternativeMediaId; } string contentKeyPolicyName = null; if (data.contentKeyPolicyName != null) { contentKeyPolicyName = data.contentKeyPolicyName; } List <StreamingLocatorContentKey> contentKeys = new List <StreamingLocatorContentKey>(); DateTime startDateTime = new DateTime(0); if (data.startDateTime != null) { startDateTime = data.startDateTime; } DateTime endDateTime = new DateTime(0); if (data.endDateTime != null) { endDateTime = data.endDateTime; } Guid streamingLocatorId = Guid.NewGuid(); if (data.streamingLocatorId != null) { streamingLocatorId = new Guid((string)(data.streamingLocatorId)); } string streamingLocatorName = "streaminglocator-" + streamingLocatorId.ToString(); MediaServicesConfigWrapper amsconfig = new MediaServicesConfigWrapper(); StreamingLocator streamingLocator = null; Asset asset = null; StreamingPolicy streamingPolicy = null; try { IAzureMediaServicesClient client = MediaServicesHelper.CreateMediaServicesClientAsync(amsconfig); asset = client.Assets.Get(amsconfig.ResourceGroup, amsconfig.AccountName, assetName); if (asset == null) { return(new BadRequestObjectResult("Asset not found")); } streamingPolicy = client.StreamingPolicies.Get(amsconfig.ResourceGroup, amsconfig.AccountName, streamingPolicyName); if (streamingPolicy == null) { return(new BadRequestObjectResult("StreamingPolicy not found")); } if (contentKeyPolicyName != null) { ContentKeyPolicy contentKeyPolicy = null; contentKeyPolicy = client.ContentKeyPolicies.Get(amsconfig.ResourceGroup, amsconfig.AccountName, contentKeyPolicyName); if (contentKeyPolicy == null) { return(new BadRequestObjectResult("ContentKeyPolicy not found")); } } if (data.contentKeys != null) { JsonConverter[] jsonConverters = { new MediaServicesHelperJsonReader() }; contentKeys = JsonConvert.DeserializeObject <List <StreamingLocatorContentKey> >(data.contentKeys.ToString(), jsonConverters); } streamingLocator = new StreamingLocator() { AssetName = assetName, StreamingPolicyName = streamingPolicyName, AlternativeMediaId = alternativeMediaId, DefaultContentKeyPolicyName = contentKeyPolicyName, StartTime = null, EndTime = null, StreamingLocatorId = streamingLocatorId, }; if (!startDateTime.Equals(new DateTime(0))) { streamingLocator.StartTime = startDateTime; } if (!endDateTime.Equals(new DateTime(0))) { streamingLocator.EndTime = endDateTime; } if (contentKeys.Count != 0) { streamingLocator.ContentKeys = contentKeys; } streamingLocator.Validate(); client.StreamingLocators.Create(amsconfig.ResourceGroup, amsconfig.AccountName, streamingLocatorName, streamingLocator); } 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)); } return((ActionResult) new OkObjectResult(new { streamingLocatorName = streamingLocatorName, streamingLocatorId = streamingLocator.StreamingLocatorId.ToString() })); }
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 GeneralOutputInfo GenerateOutputInformation(ConfigWrapper config, IAzureMediaServicesClient client, List <LiveEvent> liveEvents) { var generalOutputInfo = new GeneralOutputInfo { Success = true, LiveEvents = new List <LiveEventEntry>() }; foreach (var liveEventenum in liveEvents) { var liveEvent = client.LiveEvents.Get(config.ResourceGroup, config.AccountName, liveEventenum.Name); // we refresh the object var liveOutputs = client.LiveOutputs.List(config.ResourceGroup, config.AccountName, liveEvent.Name); // let's provide DASH format for preview var previewE = liveEvent.Preview.Endpoints .Select(a => new PreviewInfo { Protocol = a.Protocol, Url = a.Url }).ToList(); /* * // Code to expose Preview DASH and not Smooth * if (previewE.Count == 1 && previewE[0].Protocol == "FragmentedMP4") * { * previewE[0].Protocol = "DashCsf"; * previewE[0].Url = previewE[0].Url + "(format=mpd-time-csf)"; * } */ // output info var liveEventInfo = new LiveEventEntry() { LiveEventName = liveEvent.Name, ResourceState = liveEvent.ResourceState.ToString(), VanityUrl = liveEvent.VanityUrl, Input = liveEvent.Input.Endpoints .Select(endPoint => new UrlEntry { Protocol = endPoint.Protocol, Url = endPoint.Url }).ToList(), InputACL = liveEvent.Input.AccessControl?.Ip.Allow .Select(ip => ip.Address + "/" + ip.SubnetPrefixLength).ToList(), Preview = previewE .Select(endPoint => new UrlEntry { Protocol = endPoint.Protocol, Url = endPoint.Url }).ToList(), PreviewACL = liveEvent.Preview.AccessControl?.Ip.Allow .Select(ip => ip.Address + "/" + ip.SubnetPrefixLength).ToList(), LiveOutputs = new List <LiveOutputEntry>(), AMSAccountName = config.AccountName, Region = config.Region, ResourceGroup = config.ResourceGroup, LowLatency = liveEvent.StreamOptions?.Contains(StreamOptionsFlag.LowLatency) }; generalOutputInfo.LiveEvents.Add(liveEventInfo); foreach (var liveOutput in liveOutputs) { var urls = new List <OutputUrl>(); string streamingPolicyName = null; StreamingPolicy streamingPolicy = null; var asset = client.Assets.Get(config.ResourceGroup, config.AccountName, liveOutput.AssetName); // output info var liveOutputInfo = new LiveOutputEntry { LiveOutputName = liveOutput.Name, ResourceState = liveOutput.ResourceState, ArchiveWindowLength = (int)liveOutput.ArchiveWindowLength.TotalMinutes, AssetName = liveOutput.AssetName, AssetStorageAccountName = asset?.StorageAccountName, StreamingLocators = new List <StreamingLocatorEntry>() }; liveEventInfo.LiveOutputs.Add(liveOutputInfo); var streamingLocatorsNames = client.Assets.ListStreamingLocators(config.ResourceGroup, config.AccountName, liveOutput.AssetName).StreamingLocators.Select(l => l.Name); foreach (var locatorName in streamingLocatorsNames) { string cenckeyId = null; string cbcskeyId = null; StreamingLocator streamingLocator = null; if (locatorName != null) { streamingLocator = client.StreamingLocators.Get(config.ResourceGroup, config.AccountName, locatorName); if (streamingLocator != null) { streamingPolicyName = streamingLocator.StreamingPolicyName; if (streamingLocator.ContentKeys .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCenc) .FirstOrDefault() != null && streamingLocator.ContentKeys .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCbcs) .FirstOrDefault() != null) { cenckeyId = streamingLocator.ContentKeys .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCenc) .FirstOrDefault().Id.ToString(); cbcskeyId = streamingLocator.ContentKeys .Where(k => k.LabelReferenceInStreamingPolicy == IrdetoHelpers.labelCbcs) .FirstOrDefault().Id.ToString(); } urls = MediaServicesHelpers.GetUrls(config, client, streamingLocator, liveOutput.ManifestName, true, true, true, true, true); } } if (streamingPolicyName != null) { streamingPolicy = client.StreamingPolicies.Get(config.ResourceGroup, config.AccountName, streamingPolicyName); } var drmlist = new List <Drm>(); if (streamingPolicy != null) { if (streamingPolicy.CommonEncryptionCbcs != null) { var enProt = MediaServicesHelpers.ReturnOutputProtocolsListCbcs(streamingPolicy .CommonEncryptionCbcs.EnabledProtocols); drmlist.Add(new Drm { Type = "FairPlay", LicenseUrl = streamingPolicy?.CommonEncryptionCbcs?.Drm.FairPlay .CustomLicenseAcquisitionUrlTemplate.Replace("{ContentKeyId}", cbcskeyId).Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId), Protocols = enProt, CertificateUrl = config.IrdetoFairPlayCertificateUrl }); } if (streamingPolicy.CommonEncryptionCenc != null) { var enProtW = MediaServicesHelpers.ReturnOutputProtocolsListCencWidevine(streamingPolicy .CommonEncryptionCbcs.EnabledProtocols); var enProtP = MediaServicesHelpers.ReturnOutputProtocolsListCencPlayReady(streamingPolicy .CommonEncryptionCbcs.EnabledProtocols); drmlist.Add(new Drm { Type = "PlayReady", LicenseUrl = streamingPolicy?.CommonEncryptionCenc?.Drm.PlayReady .CustomLicenseAcquisitionUrlTemplate.Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId), Protocols = enProtP }); drmlist.Add(new Drm { Type = "Widevine", LicenseUrl = streamingPolicy?.CommonEncryptionCenc?.Drm.Widevine .CustomLicenseAcquisitionUrlTemplate.Replace("{AlternativeMediaId}", streamingLocator.AlternativeMediaId), Protocols = enProtW }); } } var StreamingLocatorInfo = new StreamingLocatorEntry { StreamingLocatorName = locatorName, StreamingPolicyName = streamingPolicyName, CencKeyId = cenckeyId, CbcsKeyId = cbcskeyId, Drm = drmlist, Urls = urls.Select(url => new UrlEntry { Protocol = url.Protocol.ToString(), Url = url.Url }) .ToList() }; liveOutputInfo.StreamingLocators.Add(StreamingLocatorInfo); } } } return(generalOutputInfo); }
/// <inheritdoc/> public Task <StreamingPolicy> StreamingPolicyCreateAsync(string streamingPolicyName, StreamingPolicy parameters, CancellationToken cancellationToken = default) => _client.StreamingPolicies.CreateAsync(_amsResourceGroup, _amsAccountName, streamingPolicyName, parameters, cancellationToken);