예제 #1
0
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The param is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client;

            try
            {
                client = await CreateMediaServicesClientAsync(config);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("TIP: Make sure that you have filled out the appsettings.json file before running this sample.");
                Console.Error.WriteLine($"{e.Message}");
                return;
            }

            // 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             liveEventName               = "liveevent-" + uniqueness;
            string             assetName                   = "archiveAsset" + uniqueness;
            string             liveOutputName              = "liveOutput" + uniqueness;
            string             drvStreamingLocatorName     = "streamingLocator" + uniqueness;
            string             archiveStreamingLocatorName = "fullLocator-" + uniqueness;
            string             drvAssetFilterName          = "filter-" + uniqueness;
            string             streamingEndpointName       = "default"; // Change this to your Endpoint name.
            EventProcessorHost eventProcessorHost          = null;
            bool stopEndpoint = false;

            try
            {
                // Getting the mediaServices account so that we can use the location to create the
                // LiveEvent and StreamingEndpoint
                MediaService mediaService = await client.Mediaservices.GetAsync(config.ResourceGroup, config.AccountName);

                Console.WriteLine($"Creating a live event named {liveEventName}");
                Console.WriteLine();

                // Note: When creating a LiveEvent, you can specify allowed IP addresses in one of the following formats:
                //      IpV4 address with 4 numbers
                //      CIDR address range

                IPRange allAllowIPRange = new IPRange(
                    name: "AllowAll",
                    address: "0.0.0.0",
                    subnetPrefixLength: 0
                    );

                // Create the LiveEvent input IP access control.
                LiveEventInputAccessControl liveEventInputAccess = new LiveEventInputAccessControl
                {
                    Ip = new IPAccessControl(
                        allow: new IPRange[]
                    {
                        allAllowIPRange
                    }
                        )
                };

                // Create the LiveEvent Preview IP access control
                LiveEventPreview liveEventPreview = new LiveEventPreview
                {
                    AccessControl = new LiveEventPreviewAccessControl(
                        ip: new IPAccessControl(
                            allow: new IPRange[]
                    {
                        allAllowIPRange
                    }
                            )
                        )
                };

                // To get the same ingest URL for the same LiveEvent name:
                // 1. Set vanityUrl to true so you have ingest like:
                //        rtmps://liveevent-hevc12-eventgridmediaservice-usw22.channel.media.azure.net:2935/live/522f9b27dd2d4b26aeb9ef8ab96c5c77
                // 2. Set accessToken to a desired GUID string (with or without hyphen)

                LiveEvent liveEvent = new LiveEvent(
                    location: mediaService.Location,
                    description: "Sample LiveEvent for testing",
                    vanityUrl: false,
                    encoding: new LiveEventEncoding(
                        // Set this to Standard to enable a trans-coding LiveEvent, and None to enable a pass-through LiveEvent
                        encodingType: LiveEventEncodingType.Premium1080p,
                        presetName: null
                        ),
                    input: new LiveEventInput(LiveEventInputProtocol.RTMP, liveEventInputAccess),
                    preview: liveEventPreview,
                    streamOptions: new List <StreamOptionsFlag?>()
                {
                    // Set this to Default or Low Latency
                    // When using Low Latency mode, you must configure the Azure Media Player to use the
                    // quick start heuristic profile or you won't notice the change.
                    // In the AMP player client side JS options, set -  heuristicProfile: "Low Latency Heuristic Profile".
                    // To use low latency optimally, you should tune your encoder settings down to 1 second GOP size instead of 2 seconds.
                    // StreamOptionsFlag.LowLatency
                }
                    );
                Console.WriteLine($"Creating the LiveEvent, be patient this can take time...");

                // When autostart is set to true, the Live Event will be started after creation.
                // That means, the billing starts as soon as the Live Event starts running.
                // You must explicitly call Stop on the Live Event resource to halt further billing.
                // The following operation can sometimes take awhile. Be patient.
                liveEvent = await client.LiveEvents.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveEvent, autoStart : true);

                // Start monitoring LiveEvent events.
                try
                {
                    // Please refer README for Event Hub and storage settings.
                    Console.WriteLine("Starting monitoring LiveEvent events...");
                    string StorageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                                                                   config.StorageAccountName, config.StorageAccountKey);

                    // Create a new host to process events from an Event Hub.
                    Console.WriteLine("Creating a new host to process events from an Event Hub...");
                    eventProcessorHost = new EventProcessorHost(config.EventHubName,
                                                                PartitionReceiver.DefaultConsumerGroupName, config.EventHubConnectionString,
                                                                StorageConnectionString, config.StorageContainerName);

                    // Registers the Event Processor Host and starts receiving messages.
                    await eventProcessorHost.RegisterEventProcessorFactoryAsync(new MediaServicesEventProcessorFactory(liveEventName),
                                                                                EventProcessorOptions.DefaultOptions);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Failed to connect to Event Hub, please refer README for Event Hub and storage settings. Skipping event monitoring...");
                    Console.WriteLine(e.Message);
                }



                // Get the input endpoint to configure the on premise encoder with
                string ingestUrl = liveEvent.Input.Endpoints.First().Url;
                Console.WriteLine($"The ingest url to configure the on premise encoder with is:");
                Console.WriteLine($"\t{ingestUrl}");
                Console.WriteLine();

                // Use the previewEndpoint to preview and verify
                // that the input from the encoder is actually being received
                string previewEndpoint = liveEvent.Preview.Endpoints.First().Url;
                Console.WriteLine($"The preview url is:");
                Console.WriteLine($"\t{previewEndpoint}");
                Console.WriteLine();

                Console.WriteLine($"Open the live preview in your browser and use the Azure Media Player to monitor the preview playback:");
                Console.WriteLine($"\thttps://ampdemo.azureedge.net/?url={previewEndpoint}"); // &heuristicprofile=lowlatency");
                Console.WriteLine();

                Console.WriteLine("Start the live stream now, sending the input to the ingest url and verify that it is arriving with the preview url.");
                Console.WriteLine("IMPORTANT TIP!: Make ABSOLUTLEY CERTAIN that the video is flowing to the Preview URL before continuing!");
                Console.WriteLine("******************************");
                Console.WriteLine("* Press ENTER to continue... *");
                Console.WriteLine("******************************");
                Console.WriteLine();
                Console.Out.Flush();

                var ignoredInput = Console.ReadLine();

                // Create an Asset for the LiveOutput to use
                Console.WriteLine($"Creating an asset named {assetName}");
                Console.WriteLine();
                Asset asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName, assetName, new Asset());

                //AssetFilter drvAssetFilter = new AssetFilter(
                //    presentationTimeRange: new PresentationTimeRange(
                //        forceEndTimestamp:false,
                //        // 300 seconds sliding window
                //        presentationWindowDuration: 3000000000L,
                //        // This value defines the latest live position that a client can seek back to 10 seconds, must be smaller than sliding window.
                //        liveBackoffDuration: 100000000L)
                //);

                //drvAssetFilter = await client.AssetFilters.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName,
                //    assetName, drvAssetFilterName, drvAssetFilter);

                // Create the LiveOutput
                string manifestName = "output";
                Console.WriteLine($"Creating a live output named {liveOutputName}");
                Console.WriteLine();

                // withArchiveWindowLength: Can be set from 3 minutes to 25 hours. content that falls outside of ArchiveWindowLength
                // is continuously discarded from storage and is non-recoverable. For a full event archive, set to the maximum, 25 hours.
                LiveOutput liveOutput = new LiveOutput(assetName: asset.Name, manifestName: manifestName, archiveWindowLength: TimeSpan.FromHours(2));
                liveOutput = await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveOutputName, liveOutput);

                // Create the StreamingLocator
                Console.WriteLine($"Creating a streaming locator named {drvStreamingLocatorName}");
                Console.WriteLine();

                //IList<string> filters = new List<string>();
                ////filters.Add(drvAssetFilterName);
                //StreamingLocator locator = await client.StreamingLocators.CreateAsync(config.ResourceGroup,
                //    config.AccountName,
                //    drvStreamingLocatorName,
                //    new StreamingLocator
                //    {
                //        AssetName = assetName,
                //        StreamingPolicyName = PredefinedStreamingPolicy.ClearStreamingOnly,
                //        Filters = filters   // Associate filters with StreamingLocator.
                //    });

                // Set a token signing key that you want to use
                TokenSigningKey = Convert.FromBase64String(config.SymmetricKeyPR);

                // 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);

                // Sets StreamingLocator.StreamingPolicyName to "Predefined_MultiDrmCencStreaming" policy.
                StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, asset.Name, drvStreamingLocatorName, 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);

                StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup,
                                                                                               config.AccountName, DefaultStreamingEndpointName);

                // If it's not running, Start it.
                if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running)
                {
                    Console.WriteLine("Streaming Endpoint was Stopped, restarting now..");
                    await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, streamingEndpointName);

                    // Since we started the endpoint, we should stop it in cleanup.
                    stopEndpoint = true;
                }
                string dashPath = await GetDASHStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locator.Name, streamingEndpoint);

                if (dashPath.Length > 0)
                {
                    Console.WriteLine("---Encrypted URL for IE or Edge---");
                    Console.WriteLine($"\thttps://ampdemo.azureedge.net/?url={dashPath}&playready=true&token=Bearer%3D{token}");
                    Console.WriteLine("---Encrypted URL for Chrome or Firefox---");
                    Console.WriteLine($"\thttps://ampdemo.azureedge.net/?url={dashPath}&widevine=true&token=Bearer%3D{token}");
                    Console.WriteLine("-------------------");
                    Console.WriteLine("If you see an error in Azure Media Player, wait a few moments and try again.");
                    Console.WriteLine("Continue experimenting with the stream until you are ready to finish.");
                    Console.WriteLine();
                    Console.WriteLine("***********************************************");
                    Console.WriteLine("* Press ENTER anytime to stop the LiveEvent.  *");
                    Console.WriteLine("***********************************************");
                    Console.WriteLine();
                    Console.Out.Flush();
                    ignoredInput = Console.ReadLine();

                    Console.WriteLine("Cleaning up LiveEvent and output...");
                    await CleanupLiveEventAndOutputAsync(client, config.ResourceGroup, config.AccountName, liveEventName);

                    Console.WriteLine("The LiveOutput and LiveEvent are now deleted.  The event is available as an archive and can still be streamed.");

                    // If we started the endpoint, we'll stop it. Otherwise, we'll keep the endpoint running and print urls
                    // that can be played even after this sample ends.
                    if (!stopEndpoint)
                    {
                        StreamingLocator archiveLocator = await client.StreamingLocators.CreateAsync(config.ResourceGroup,
                                                                                                     config.AccountName,
                                                                                                     archiveStreamingLocatorName,
                                                                                                     new StreamingLocator
                        {
                            AssetName           = assetName,
                            StreamingPolicyName = PredefinedStreamingPolicy.ClearStreamingOnly
                        });

                        Console.WriteLine("To playback the archived files, Use the following urls:");
                        await PrintPaths(client, config.ResourceGroup, config.AccountName, archiveStreamingLocatorName, streamingEndpoint);
                    }
                }
            }
            catch (ApiErrorException e)
            {
                Console.WriteLine("Hit ApiErrorException");
                Console.WriteLine($"\tCode: {e.Body.Error.Code}");
                Console.WriteLine($"\tCode: {e.Body.Error.Message}");
                Console.WriteLine();
                Console.WriteLine("Exiting, cleanup may be necessary...");
                Console.ReadLine();
            }
            finally
            {
                await CleanupLiveEventAndOutputAsync(client, config.ResourceGroup, config.AccountName, liveEventName);

                await CleanupLocatorAsync(client, config.ResourceGroup, config.AccountName, drvStreamingLocatorName);

                // Stop event monitoring.
                if (eventProcessorHost != null)
                {
                    await eventProcessorHost.UnregisterEventProcessorAsync();
                }

                if (stopEndpoint)
                {
                    // Because we started the endpoint, we'll stop it.
                    await client.StreamingEndpoints.StopAsync(config.ResourceGroup, config.AccountName, streamingEndpointName);
                }
                else
                {
                    // We will keep the endpoint running because it was not started by us. There are costs to keep it running.
                    // Please refer https://azure.microsoft.com/en-us/pricing/details/media-services/ for pricing.
                    Console.WriteLine($"The endpoint {streamingEndpointName} is running. To halt further billing on the endpoint, please stop it in azure portal or AMS Explorer.");
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Creates the AzureMediaServicesClient object based on the credentials
        /// supplied in local configuration file.
        /// </summary>
        /// <param name="config">The param is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        private static async Task <IAzureMediaServicesClient> CreateMediaServicesClientAsync(ConfigWrapper config)
        {
            var credentials = await GetCredentialsAsync(config);

            return(new AzureMediaServicesClient(config.ArmEndpoint, credentials)
            {
                SubscriptionId = config.SubscriptionId,
            });
        }