/// <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; try { // Generate a new random token signing key to use RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(TokenSigningKey); //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. ContentKeyPolicy policy = EnsureContentKeyPolicyExists(client, config.ResourceGroup, config.AccountName, ContentKeyPolicyName); // Ensure that you have customized encoding Transform. This is really a one time setup operation. Transform adaptiveEncodeTransform = EnsureTransformExists(client, config.ResourceGroup, config.AccountName, transformName, preset: new BuiltInStandardEncoderPreset(EncoderNamedPreset.AdaptiveStreaming)); // 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 inputAssetName = "input-" + uniqueness; string outputAssetName = "output-" + uniqueness; string streamingLocatorName = "locator-" + uniqueness; Asset asset = client.Assets.CreateOrUpdate(config.ResourceGroup, config.AccountName, inputAssetName, new Asset()); var input = new JobInputHttp( baseUri: "https://nimbuscdn-nimbuspm.streaming.mediaservices.windows.net/2b533311-b215-4409-80af-529c3e853622/", files: new List <String> { "Ignite-short.mp4" }, label: "input1" ); Asset outputAsset = CreateOutputAsset(client, config.ResourceGroup, config.AccountName, outputAssetName); Job job = SubmitJob(client, config.ResourceGroup, config.AccountName, transformName, jobName, input, outputAsset.Name); DateTime startedTime = DateTime.Now; job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, transformName, jobName); TimeSpan elapsed = DateTime.Now - startedTime; if (job.State == JobState.Finished) { Console.WriteLine("Job finished."); // Now that the content has been encoded, publish it for Streaming by creating // a StreamingLocator. Note that we are using one of the PredefinedStreamingPolicies // which tell the Origin component of Azure Media Services how to publish the content // for streaming. In this case it applies AES Envelople encryption, which is also known // ClearKey encryption (because the key is delivered to the playback client via HTTPS and // not instead a DRM license). StreamingLocator locator = new StreamingLocator( assetName: outputAsset.Name, streamingPolicyName: PredefinedStreamingPolicy.ClearKey, defaultContentKeyPolicyName: ContentKeyPolicyName); client.StreamingLocators.Create(config.ResourceGroup, config.AccountName, streamingLocatorName, locator); // 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. Since we didn't specify // a content key when creating the StreamingLocator, the system created a random one for us. In order to // generate our test token we must get the ContentKeyId to put in the ContentKeyIdentifierClaim claim. var response = client.StreamingLocators.ListContentKeys(config.ResourceGroup, config.AccountName, streamingLocatorName); string keyIdentifier = response.ContentKeys.First().Id.ToString(); // We can either use the "default" StreamingEndpoint or we can create a new StreamingEndpoint. // Typically we would just ensure that the default endpoint was started but let's create one // here to illustrate how it is done. // Console.WriteLine($"Creating a streaming endpoint named {endpointName}"); // Console.WriteLine(); //StreamingEndpoint streamingEndpoint = new StreamingEndpoint(location: mediaService.Location); var streamingEndpoint = client.StreamingEndpoints.Get(config.ResourceGroup, config.AccountName, "default"); // Get the URls to stream the output var paths = client.StreamingLocators.ListPaths(config.ResourceGroup, config.AccountName, streamingLocatorName); Console.WriteLine("The urls to stream the output from a client:"); Console.WriteLine(); var token = GetToken(Issuer, Audience, keyIdentifier, TokenSigningKey); for (int i = 0; i < paths.StreamingPaths.Count; i++) { UriBuilder uriBuilder = new UriBuilder(); uriBuilder.Scheme = "https"; uriBuilder.Host = streamingEndpoint.HostName; if (paths.StreamingPaths[i].Paths.Count > 0) { //uriBuilder.Path = paths.StreamingPaths[i].Paths[0]; //Console.WriteLine($"\t{paths.StreamingPaths[i].StreamingProtocol}-{paths.StreamingPaths[i].EncryptionScheme}"); //Console.WriteLine($"\t\t{uriBuilder.ToString()}"); //Console.WriteLine(); // Look for just the DASH path and generate a URL for the Azure Media Player to playback the content with the AES token to decrypt. // Note that the JWT token is set to expire in 1 hour. if (paths.StreamingPaths[i].StreamingProtocol == StreamingPolicyStreamingProtocol.Dash) { uriBuilder.Path = paths.StreamingPaths[i].Paths[0]; var dashPath = uriBuilder.ToString(); Console.WriteLine("Open the following URL in your browser to play back the file in the Azure Media Player"); Console.WriteLine($"https://ampdemo.azureedge.net/?url={dashPath}&aes=true&aestoken=Bearer%3D{token}"); Console.WriteLine(); } } } } else if (job.State == JobState.Error) { Console.WriteLine($"ERROR: Job finished with error message: {job.Outputs[0].Error.Message}"); Console.WriteLine($"ERROR: error details: {job.Outputs[0].Error.Details[0].Message}"); } Console.WriteLine("Try Streaming the content using Azure Media Player - https://ampdemo.azureedge.net."); Console.WriteLine("Use the Advanced options to see or modify the AES Bearer token in the AMP demo page. When finished press enter to cleanup."); Console.Out.Flush(); Console.ReadLine(); Console.WriteLine("Cleaning up..."); Cleanup(client, config.ResourceGroup, config.AccountName, transformName, jobName, outputAsset.Name, input, streamingLocatorName, ContentKeyPolicyName); } catch (ApiErrorException ex) { string code = ex.Body.Error.Code; string message = ex.Body.Error.Message; Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}", code, message); } }
// </GetCredentialsAsync> /// <summary> /// Creates the AzureMediaServicesClient object based on the credentials /// supplied in local configuration file. /// </summary> /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param> /// <returns></returns> // <CreateMediaServicesClient> private static async Task <IAzureMediaServicesClient> CreateMediaServicesClientAsync(ConfigWrapper config) { var credentials = await GetCredentialsAsync(config); return(new AzureMediaServicesClient(config.ArmEndpoint, credentials) { SubscriptionId = config.SubscriptionId, }); }