static void Main(string[] args) { ConfigWrapper config = new ConfigWrapper(); try{ IAzureMediaServicesClient client = CreateMediaServicesClient(config); // Set the polling interval for long running operations to 2 seconds. // The default value is 30 seconds for the .NET client SDK client.LongRunningOperationRetryTimeout = 2; // Creating a unique suffix so that we don't have name collisions if you run the sample // multiple times without cleaning up. string uniqueness = Guid.NewGuid().ToString().Substring(0, 13); string jobName = "job-" + uniqueness; string outputAssetName = "output-" + uniqueness; string inputAssetName = "input-" + uniqueness; // Ensure that you have the desired encoding Transform. This is really a one time setup operation. Transform videoAnalyzerTransform = EnsureTransformExists(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, new VideoAnalyzerPreset("en-US")); // Create a new input Asset and upload the specified local video file into it. CreateInputAsset(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName); // Use the name of the created input asset to create the job input. JobInput jobInput = new JobInputAsset(assetName: inputAssetName); // Output from the encoding Job must be written to an Asset, so let's create one Asset outputAsset = client.Assets.CreateOrUpdate(config.ResourceGroup, config.AccountName, outputAssetName, new Asset()); Job job = SubmitJob(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName, jobInput, outputAssetName); // In this demo code, we will poll for Job status // Polling is not a recommended best practice for production applications because of the latency it introduces. // Overuse of this API may trigger throttling. Developers should instead use Event Grid. job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, VideoAnalyzerTransformName, jobName); if (job.State == JobState.Finished) { Console.WriteLine("Job finished."); if (!Directory.Exists(OutputFolder)) { Directory.CreateDirectory(OutputFolder); } DownloadResults(client, config.ResourceGroup, config.AccountName, outputAssetName, OutputFolder); } Console.WriteLine("Done."); Console.WriteLine("Press Enter to Continue"); Console.ReadLine(); } catch (ApiErrorException ex) { Console.WriteLine("{0}", ex.Message); Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}", ex.Body.Error.Code, ex.Body.Error.Message); } }
/// <summary> /// Run the sample async. /// </summary> /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param> /// <returns></returns> // <RunAsync> private static async Task RunAsync(ConfigWrapper config) { IAzureMediaServicesClient client = await CreateMediaServicesClientAsync(config); // Set the polling interval for long running operations to 2 seconds. // The default value is 30 seconds for the .NET client SDK client.LongRunningOperationRetryTimeout = 2; // Creating a unique suffix so that we don't have name collisions if you run the sample // multiple times without cleaning up. string uniqueness = Guid.NewGuid().ToString("N"); string jobName = $"job-{uniqueness}"; string locatorName = $"locator-{uniqueness}"; string outputAssetName = $"output-{uniqueness}"; // Ensure that you have the desired encoding Transform. This is really a one time setup operation. Transform transform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName); // Output from the encoding Job must be written to an Asset, so let's create one Asset outputAsset = await CreateOutputAssetAsync(client, config.ResourceGroup, config.AccountName, outputAssetName); Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAsset.Name, jobName); // In this demo code, we will poll for Job status // Polling is not a recommended best practice for production applications because of the latency it introduces. // Overuse of this API may trigger throttling. Developers should instead use Event Grid. job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName); if (job.State == JobState.Finished) { // Set a token signing key that you want to use TokenSigningKey = Convert.FromBase64String(config.SymmetricKey); // Create the content key policy that configures how the content key is delivered to end clients // via the Key Delivery component of Azure Media Services. // We are using the ContentKeyIdentifierClaim in the ContentKeyPolicy which means that the token presented // to the Key Delivery Component must have the identifier of the content key in it. ContentKeyPolicy policy = await GetOrCreateContentKeyPolicyAsync(client, config.ResourceGroup, config.AccountName, ContentKeyPolicyName, TokenSigningKey); StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName, ContentKeyPolicyName); // In this example, we want to play the PlayReady (CENC) encrypted stream. // We need to get the key identifier of the content key where its type is CommonEncryptionCenc. string keyIdentifier = locator.ContentKeys.Where(k => k.Type == StreamingLocatorContentKeyType.CommonEncryptionCenc).First().Id.ToString(); Console.WriteLine($"KeyIdentifier = {keyIdentifier}"); // In order to generate our test token we must get the ContentKeyId to put in the ContentKeyIdentifierClaim claim. string token = GetTokenAsync(Issuer, Audience, keyIdentifier, TokenSigningKey); string dashPath = await GetDASHStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locator.Name); Console.WriteLine("Copy and paste the following URL in your browser to play back the file in the Azure Media Player."); Console.WriteLine("You can use Edge/IE11 for PlayReady and Chrome/Firefox Widevine."); Console.WriteLine(); Console.WriteLine($"https://ampdemo.azureedge.net/?url={dashPath}&playready=true&widevine=true&token=Bearer%3D{token}"); Console.WriteLine(); } Console.WriteLine("When finished testing press enter to cleanup."); Console.Out.Flush(); Console.ReadLine(); Console.WriteLine("Cleaning up..."); await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, ContentKeyPolicyName); }
public static async Task <object> Run([HttpTrigger(WebHookType = "genericJson")] HttpRequestMessage req, TraceWriter log) { log.Info($"AMS v3 Function - create_transform was triggered!"); string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); // Validate input objects if (data.transformName == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass transformName in the input object" })); } if (data.builtInStandardEncoderPreset == null && data.videoAnalyzerPreset == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Please pass preset in the input object" })); } string transformName = data.transformName; MediaServicesConfigWrapper amsconfig = new MediaServicesConfigWrapper(); string transformId = null; try { IAzureMediaServicesClient client = CreateMediaServicesClient(amsconfig); // Does a Transform already exist with the desired name? Assume that an existing Transform with the desired name // also uses the same recipe or Preset for processing content. Transform transform = client.Transforms.Get(amsconfig.ResourceGroup, amsconfig.AccountName, transformName); if (transform == null) { // You need to specify what you want it to produce as an output var transformOutputList = new List <TransformOutput>(); // BuiltInStandardEncoderPreset if (data.builtInStandardEncoderPreset != null) { EncoderNamedPreset preset = EncoderNamedPreset.AdaptiveStreaming; if (data.builtInStandardEncoderPreset.presetName != null) { string presetName = data.builtInStandardEncoderPreset.presetName; if (encoderPreset.ContainsKey(presetName)) { preset = encoderPreset[presetName]; } } TransformOutput encoderTransform = new TransformOutput { // The preset for the Transform is set to one of Media Services built-in sample presets. // You can customize the encoding settings by changing this to use "StandardEncoderPreset" class. Preset = new BuiltInStandardEncoderPreset() { // This sample uses the built-in encoding preset for Adaptive Bitrate Streaming. PresetName = preset } }; transformOutputList.Add(encoderTransform); } // VideoAnalyzerPreset if (data.builtInStandardEncoderPreset != null) { bool audioInsightsOnly = false; string audioLanguage = "en-US"; if (data.videoAnalyzerPreset.audioInsightsOnly != null) { audioInsightsOnly = data.videoAnalyzerPreset.audioInsightsOnly; } if (data.videoAnalyzerPreset.audioLanguage != null) { audioLanguage = data.videoAnalyzerPreset.audioLanguage; } TransformOutput encoderTransform = new TransformOutput { // The preset for the Transform is set to one of Media Services built-in sample presets. // You can customize the encoding settings by changing this to use "StandardEncoderPreset" class. Preset = new VideoAnalyzerPreset(audioLanguage, audioInsightsOnly) }; transformOutputList.Add(encoderTransform); } // You need to specify what you want it to produce as an output TransformOutput[] output = transformOutputList.ToArray(); // Create the Transform with the output defined above transform = client.Transforms.CreateOrUpdate(amsconfig.ResourceGroup, amsconfig.AccountName, transformName, output); transformId = transform.Id; } } catch (ApiErrorException e) { log.Info($"ERROR: AMS API call failed with error code: {e.Body.Error.Code} and message: {e.Body.Error.Message}"); return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "AMS API call error: " + e.Message })); } return(req.CreateResponse(HttpStatusCode.OK, new { transformId = transformId })); }
// </CreateMediaServicesClient> /// <summary> /// Create the content key policy that configures how the content key is delivered to end clients /// via the Key Delivery component of Azure Media Services. /// </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="contentKeyPolicyName">The name of the content key policy resource.</param> /// <returns></returns> // <GetOrCreateContentKeyPolicy> private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync( IAzureMediaServicesClient client, string resourceGroupName, string accountName, string contentKeyPolicyName, byte[] tokenSigningKey) { ContentKeyPolicy policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName); if (policy == null) { ContentKeyPolicySymmetricTokenKey primaryKey = new ContentKeyPolicySymmetricTokenKey(tokenSigningKey); List <ContentKeyPolicyTokenClaim> requiredClaims = new List <ContentKeyPolicyTokenClaim>() { ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim }; List <ContentKeyPolicyRestrictionTokenKey> alternateKeys = null; ContentKeyPolicyTokenRestriction restriction = new ContentKeyPolicyTokenRestriction(Issuer, Audience, primaryKey, ContentKeyPolicyRestrictionTokenType.Jwt, alternateKeys, requiredClaims); ContentKeyPolicyPlayReadyConfiguration playReadyConfig = ConfigurePlayReadyLicenseTemplate(); ContentKeyPolicyWidevineConfiguration widevineConfig = ConfigureWidevineLicenseTempate(); // ContentKeyPolicyFairPlayConfiguration fairplayConfig = ConfigureFairPlayPolicyOptions(); List <ContentKeyPolicyOption> options = new List <ContentKeyPolicyOption>(); options.Add( new ContentKeyPolicyOption() { Configuration = playReadyConfig, // If you want to set an open restriction, use // Restriction = new ContentKeyPolicyOpenRestriction() Restriction = restriction }); options.Add( new ContentKeyPolicyOption() { Configuration = widevineConfig, Restriction = restriction }); // add CBCS ContentKeyPolicyOption into the list // options.Add( // new ContentKeyPolicyOption() // { // Configuration = fairplayConfig, // Restriction = restriction, // Name = "ContentKeyPolicyOption_CBCS" // }); policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options); } else { // Get the signing key from the existing policy. var policyProperties = await client.ContentKeyPolicies.GetPolicyPropertiesWithSecretsAsync(resourceGroupName, accountName, contentKeyPolicyName); var restriction = policyProperties.Options[0].Restriction as ContentKeyPolicyTokenRestriction; if (restriction != null) { var signingKey = restriction.PrimaryVerificationKey as ContentKeyPolicySymmetricTokenKey; if (signingKey != null) { TokenSigningKey = signingKey.KeyValue; } } } return(policy); }
static void Main(string[] args) { ConfigWrapper config = new ConfigWrapper(); try { IAzureMediaServicesClient client = CreateMediaServicesClient(config); // Set the polling interval for long running operations to 2 seconds. // The default value is 30 seconds for the .NET client SDK client.LongRunningOperationRetryTimeout = 2; // Creating a unique suffix so that we don't have name collisions if you run the sample // multiple times without cleaning up. string uniqueness = Guid.NewGuid().ToString().Substring(0, 13); string jobName = "job-" + uniqueness; string locatorName = "locator-" + uniqueness; string outputAssetName = "output-" + uniqueness; // Ensure that you have the desired encoding Transform. This is really a one time setup operation. Transform transform = EnsureTransformExists(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName); // Output from the encoding Job must be written to an Asset, so let's create one Asset outputAsset = CreateOutputAsset(client, config.ResourceGroup, config.AccountName, outputAssetName); Job job = SubmitJob(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAsset.Name, jobName); // In this demo code, we will poll for Job status // Polling is not a recommended best practice for production applications because of the latency it introduces. // Overuse of this API may trigger throttling. Developers should instead use Event Grid. job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName); if (job.State == JobState.Finished) { Console.WriteLine("Job finished."); if (!Directory.Exists(OutputFolder)) { Directory.CreateDirectory(OutputFolder); } // In case you don't want to stream the results from Media Services, you can choose to download the files // DownloadResults(client, config.ResourceGroup, config.AccountName, outputAsset.Name, OutputFolder); StreamingLocator locator = CreateStreamingLocator(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName); IList <string> urls = GetStreamingURLs(client, config.ResourceGroup, config.AccountName, locator.Name); foreach (var url in urls) { Console.WriteLine(url); } } Console.WriteLine("Done. Copy and paste the Streaming URL into the Azure Media Player at http://ampdemo.azureedge.net/"); Console.WriteLine("Press Enter to Continue"); Console.ReadLine(); } catch (ApiErrorException ex) { Console.WriteLine("{0}", ex.Message); Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}", ex.Body.Error.Code, ex.Body.Error.Message); } }