private async Task <StreamingEndpoint> GetStreamingEndpointAsync(string streamingEndpoint) { StreamingEndpoint endpoint = await Client.StreamingEndpoints.GetAsync( resourceGroupName : Config.ResourceGroup, accountName : Config.AccountName, streamingEndpointName : streamingEndpoint ); LoggerService.Info("Got the streaming endpoint", LoggerService.Locators); return(endpoint); }
public static StreamEndpointType ReturnTypeSE(StreamingEndpoint mySE) { if (mySE.ScaleUnits > 0) { return(StreamEndpointType.Premium); } else { return(StreamEndpointType.Standard); } }
public async Task StopStreamingEndpointAsync(string assetName, string streamingEndpointName) { // Get the default Streaming Endpoint on the account: StreamingEndpoint streamingEndpoint = await _azureMediaServicesClient.StreamingEndpoints.GetAsync(_config.ResourceGroup, _config.AccountName, streamingEndpointName); // If it's running, stop it: if (streamingEndpoint.ResourceState == StreamingEndpointResourceState.Running) { Console.WriteLine("Streaming Endpoint was running, stopping now..."); await _azureMediaServicesClient.StreamingEndpoints.StopAsync(_config.ResourceGroup, _config.AccountName, streamingEndpointName); } }
public static async Task <(Uri, bool)> GetValidOnDemandSmoothURIAsync(Asset asset, IAzureMediaServicesClient client, string resourceGroup, string accountName, string useThisLocatorName = null, LiveOutput liveOutput = null) { bool emptyLiveOutput = false; // used to signal the live output is empty (do not use ListPathsAsync) IList <AssetStreamingLocator> locators = (await client.Assets.ListStreamingLocatorsAsync(resourceGroup, accountName, asset.Name)).StreamingLocators; Microsoft.Rest.Azure.IPage <StreamingEndpoint> ses = await client.StreamingEndpoints.ListAsync(resourceGroup, accountName); StreamingEndpoint runningSes = ses.Where(s => s.ResourceState == StreamingEndpointResourceState.Running).FirstOrDefault(); if (runningSes == null) { runningSes = ses.FirstOrDefault(); } if (locators.Count > 0 && runningSes != null) { string locatorName = useThisLocatorName ?? locators.First().Name; AssetStreamingLocator locatorToUse = locators.Where(l => l.Name == locatorName).First(); IList <StreamingPath> streamingPaths = (await client.StreamingLocators.ListPathsAsync(resourceGroup, accountName, locatorName)).StreamingPaths; IEnumerable <StreamingPath> smoothPath = streamingPaths.Where(p => p.StreamingProtocol == StreamingPolicyStreamingProtocol.SmoothStreaming); if (smoothPath.Any(s => s.Paths.Count != 0)) { UriBuilder uribuilder = new() { Host = runningSes.HostName, Path = smoothPath.FirstOrDefault().Paths.FirstOrDefault() }; return(uribuilder.Uri, emptyLiveOutput); } else if (smoothPath.Any() && liveOutput != null) // A live output with no data in it as live event not started. But we can determine the output URLs { UriBuilder uribuilder = new() { Host = runningSes.HostName, Path = locatorToUse.StreamingLocatorId.ToString() + "/" + liveOutput.ManifestName + ".ism/manifest" }; emptyLiveOutput = true; return(uribuilder.Uri, emptyLiveOutput); } else { return(null, emptyLiveOutput); } } else { return(null, emptyLiveOutput); } }
private static void StartEndpointIfNotRunning(ConfigWrapper config) { const string DefaultStreamingEndpointName = "default"; streamingEndpoint = client.StreamingEndpoints.Get(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); if (streamingEndpoint != null) { if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); } } }
/// <summary> /// This function returns a Dash or HLS Uri from the pathResponse. /// It also adds .mpd or .m3u8 at the end of the URL for a better compatibility with media players. /// </summary> /// <param name="pathResponse">Response from AMS on list paths.</param> /// <param name="selectedStreamingEndpoint">The selected streaming endpoint.</param> /// <param name="protocol">The protocol selected.</param> /// <returns>The streaming Uri, if available, or null.</returns> private static Uri GetStreamingUri(ListPathsResponse pathResponse, StreamingEndpoint selectedStreamingEndpoint, StreamingPolicyStreamingProtocol protocol) { string uristr = pathResponse.StreamingPaths.Where(p => p.StreamingProtocol == protocol).FirstOrDefault()?.Paths.FirstOrDefault(); if (uristr != null) { uristr = "https://" + selectedStreamingEndpoint.HostName + uristr; if (!uristr.EndsWith(ExtensionPerProtocol[protocol])) { uristr += ExtensionPerProtocol[protocol]; } } return(uristr != null ? new Uri(uristr) : null); }
private static async Task <StreamingEndpoint> StartStreamingEndpointAsync(IAzureMediaServicesClient client, string resourceGroup, string accountName, string assetName, string streamingEndpointName) { // Get the default Streaming Endpoint on the account StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(resourceGroup, accountName, streamingEndpointName); // If it's not running, Start it. if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { Console.WriteLine("Streaming Endpoint was Stopped, restarting now.."); await client.StreamingEndpoints.StartAsync(resourceGroup, accountName, streamingEndpointName); streamingEndpoint = await client.StreamingEndpoints.GetAsync(resourceGroup, accountName, streamingEndpointName); } return(streamingEndpoint); }
public async Task <StreamingEndpoint> StartStreamingEndpointAsync(string assetName, string streamingEndpointName) { // Get the default Streaming Endpoint on the account: StreamingEndpoint streamingEndpoint = await _azureMediaServicesClient.StreamingEndpoints.GetAsync(_config.ResourceGroup, _config.AccountName, streamingEndpointName); // If it's not running, start it: if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { Console.WriteLine("Streaming Endpoint was Stopped, restarting now.."); await _azureMediaServicesClient.StreamingEndpoints.StartAsync(_config.ResourceGroup, _config.AccountName, streamingEndpointName); streamingEndpoint = await _azureMediaServicesClient.StreamingEndpoints.GetAsync(_config.ResourceGroup, _config.AccountName, streamingEndpointName); } return(streamingEndpoint); }
private async Task <List <StreamingEndpoint> > ReturnSelectedStreamingEndpointsAsync() { List <StreamingEndpoint> SelectedOrigins = new List <StreamingEndpoint>(); foreach (DataGridViewRow Row in dataGridViewStreamingEndpointsV.SelectedRows) { string seName = Row.Cells[dataGridViewStreamingEndpointsV.Columns["Name"].Index].Value.ToString(); StreamingEndpoint se = await GetStreamingEndpointAsync(seName); if (se != null) { SelectedOrigins.Add(se); } } SelectedOrigins.Reverse(); return(SelectedOrigins); }
/// <summary> /// Build and print streaming URLs. /// </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="streamingLocatorName">The streaming locator name.</param> /// <param name="streamingEndpoint">The streaming endpoint.</param> /// <returns></returns> private static async Task <bool> PrintPaths(IAzureMediaServicesClient client, string resourceGroup, string accountName, string streamingLocatorName, StreamingEndpoint streamingEndpoint) { // Get the url to stream the output var paths = await client.StreamingLocators.ListPathsAsync(resourceGroup, accountName, streamingLocatorName); Console.WriteLine("The urls to stream the output from the client:"); Console.WriteLine(); StringBuilder stringBuilder = new StringBuilder(); string playerPath = string.Empty; 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]; stringBuilder.AppendLine($"\t{paths.StreamingPaths[i].StreamingProtocol}-{paths.StreamingPaths[i].EncryptionScheme}"); stringBuilder.AppendLine($"\t\t{uriBuilder.ToString()}"); stringBuilder.AppendLine(); if (paths.StreamingPaths[i].StreamingProtocol == StreamingPolicyStreamingProtocol.Dash) { playerPath = uriBuilder.ToString(); } } } if (stringBuilder.Length > 0) { Console.WriteLine(stringBuilder.ToString()); Console.WriteLine("Open the following URL to play it in the Azure Media Player"); Console.WriteLine($"\t https://ampdemo.azureedge.net/?url={playerPath}&heuristicprofile=lowlatency"); Console.WriteLine(); return(true); } else { Console.WriteLine("No Streaming Paths were detected. Has the Stream been started?"); return(false); } }
public async Task <StatusOutputModel> GetStatusAsync(InputRequestModel input) { LoggerService.Info("Beginning the status procedure", LoggerService.Status); StreamingEndpoint endpoint = await GetStreamingEndpointAsync(input.StreamingEndpoint); List <LiveEvent> liveEvents = await GetLiveEventsAsync(input.LiveEvents); StatusOutputModel.Resource mappedEndpoint = MapStreamingResourceToOurResource(endpoint); List <StatusOutputModel.Resource> mappedEvents = MapLiveEventResourceToOurResource(liveEvents); return(new StatusOutputModel { LiveEvents = mappedEvents, StreamingEndpoint = mappedEndpoint, Summary = DetermineSummary(mappedEndpoint, mappedEvents) }); }
// </GetToken> /// <summary> /// Checks if the "default" streaming endpoint is in the running state, /// if not, starts it. /// Then, builds the streaming URLs. /// </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="locatorName">The name of the StreamingLocator that was created.</param> /// <returns></returns> // <GetMPEGStreamingUrl> private static async Task <string> GetDASHStreamingUrlAsync( IAzureMediaServicesClient client, string resourceGroupName, string accountName, string locatorName) { const string DefaultStreamingEndpointName = "default"; string dashPath = ""; StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(resourceGroupName, accountName, DefaultStreamingEndpointName); if (streamingEndpoint != null) { if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { await client.StreamingEndpoints.StartAsync(resourceGroupName, accountName, DefaultStreamingEndpointName); } } ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName); foreach (StreamingPath path in paths.StreamingPaths) { UriBuilder uriBuilder = new UriBuilder { Scheme = "https", Host = streamingEndpoint.HostName }; // 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 (path.StreamingProtocol == StreamingPolicyStreamingProtocol.Dash) { uriBuilder.Path = path.Paths[0]; dashPath = uriBuilder.ToString(); } } return(dashPath); }
public async Task <string> GetAvailableMediaTimeRanges(string assetName, string precision, string startTime, string endTime) { string availableMediaTimeRanges = null; try { StreamingLocator sl = GetStreamingLocator(assetName); StreamingEndpoint sep = await GetDefaultStreamingEndpointAsync(); string availableMediaTimeRangesUrl = "https://" + sep.HostName + "/" + sl.StreamingLocatorId + "/content.ism/availableMedia?precision=" + precision + "&startTime=" + startTime + "&endTime=" + endTime; availableMediaTimeRanges = await DownloadFromUrlAsync(availableMediaTimeRangesUrl); } catch (Exception) { } return(availableMediaTimeRanges); }
void Execute(StreamingOptions options) { try { StreamingEndpoint streamingFilter = new StreamingEndpoint(); int count = 0; foreach (Status status in streamingFilter.GetStreamingStatus(options)) { System.Diagnostics.Debug.WriteLine(status); count++; if (count == 5) { break; } } } catch (Exception ex) { Assert.True(false, Util.ExceptionMessage(ex)); } }
private string GetStreamingHost(string streamingEndpointName) { string streamingHostName = null; if (string.IsNullOrEmpty(streamingEndpointName)) { streamingEndpointName = Constant.Media.Stream.DefaultEndpointName; } StreamingEndpoint streamingEndpoint = GetEntity <StreamingEndpoint>(MediaEntity.StreamingEndpoint, streamingEndpointName); if (streamingEndpoint != null) { if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Starting && streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running && streamingEndpoint.ResourceState != StreamingEndpointResourceState.Scaling) { _media.StreamingEndpoints.Start(MediaAccount.ResourceGroupName, MediaAccount.Name, streamingEndpointName); } streamingHostName = streamingEndpoint.HostName; } return(streamingHostName); }
// </CreateStreamingLocator> /// <summary> /// Checks if the "default" streaming endpoint is in the running state, /// if not, starts it. /// Then, builds the streaming URLs. /// </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="locatorName">The name of the StreamingLocator that was created.</param> /// <returns></returns> // <GetStreamingURLs> private static async Task <IList <string> > GetStreamingUrlsAsync( IAzureMediaServicesClient client, string resourceGroupName, string accountName, String locatorName) { const string DefaultStreamingEndpointName = "default"; IList <string> streamingUrls = new List <string>(); StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(resourceGroupName, accountName, DefaultStreamingEndpointName); if (streamingEndpoint != null) { if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { await client.StreamingEndpoints.StartAsync(resourceGroupName, accountName, DefaultStreamingEndpointName); } } ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName); foreach (StreamingPath path in paths.StreamingPaths) { UriBuilder uriBuilder = new UriBuilder { Scheme = "https", Host = streamingEndpoint.HostName, Path = path.Paths[0] }; streamingUrls.Add(uriBuilder.ToString()); } return(streamingUrls); }
/// <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); // 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 streamingLocatorName = "streamingLocator" + uniqueness; string streamingEndpointName = "default"; 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); #region CreateLiveEvent 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 transcoding LiveEvent, and None to enable a pass-through LiveEvent encodingType: LiveEventEncodingType.None, 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 hueristic 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); #endregion // Get the input endpoint to configure the on premise encoder with #region GetIngestUrl 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(); #endregion // Use the previewEndpoint to preview and verify // that the input from the encoder is actually being received #region GetPreviewURLs 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(); #endregion 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("Press enter to continue..."); Console.Out.Flush(); var ignoredInput = Console.ReadLine(); // Create an Asset for the LiveOutput to use #region CreateAsset Console.WriteLine($"Creating an asset named {assetName}"); Console.WriteLine(); Asset asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName, assetName, new Asset()); #endregion // Create the LiveOutput #region CreateLiveOutput string manifestName = "output"; Console.WriteLine($"Creating a live output named {liveOutputName}"); Console.WriteLine(); LiveOutput liveOutput = new LiveOutput(assetName: asset.Name, manifestName: manifestName, archiveWindowLength: TimeSpan.FromMinutes(10)); liveOutput = await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveOutputName, liveOutput); #endregion // Create the StreamingLocator #region CreateStreamingLocator Console.WriteLine($"Creating a streaming locator named {streamingLocatorName}"); Console.WriteLine(); StreamingLocator locator = new StreamingLocator(assetName: asset.Name, streamingPolicyName: PredefinedStreamingPolicy.ClearStreamingOnly); locator = await client.StreamingLocators.CreateAsync(config.ResourceGroup, config.AccountName, streamingLocatorName, locator); // Get the default Streaming Endpoint on the account StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup, config.AccountName, streamingEndpointName); // 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); } #endregion // Get the url to stream the output var paths = await client.StreamingLocators.ListPathsAsync(config.ResourceGroup, config.AccountName, streamingLocatorName); Console.WriteLine("The urls to stream the output from a client:"); Console.WriteLine(); StringBuilder stringBuilder = new StringBuilder(); string playerPath = string.Empty; 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]; stringBuilder.AppendLine($"\t{paths.StreamingPaths[i].StreamingProtocol}-{paths.StreamingPaths[i].EncryptionScheme}"); stringBuilder.AppendLine($"\t\t{uriBuilder.ToString()}"); stringBuilder.AppendLine(); if (paths.StreamingPaths[i].StreamingProtocol == StreamingPolicyStreamingProtocol.Dash) { playerPath = uriBuilder.ToString(); } } } if (stringBuilder.Length > 0) { Console.WriteLine(stringBuilder.ToString()); Console.WriteLine("Open the following URL to playback the published,recording LiveOutput in the Azure Media Player"); Console.WriteLine($"\t https://ampdemo.azureedge.net/?url={playerPath}&heuristicprofile=lowlatency"); Console.WriteLine(); Console.WriteLine("Continue experimenting with the stream until you are ready to finish."); Console.WriteLine("Press enter to stop the LiveOutput..."); Console.Out.Flush(); ignoredInput = Console.ReadLine(); 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."); Console.WriteLine("Press enter to finish cleanup..."); Console.Out.Flush(); ignoredInput = Console.ReadLine(); } else { Console.WriteLine("No Streaming Paths were detected. Has the Stream been started?"); Console.WriteLine("Cleaning up and Exiting..."); } } 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 CleanupLocatorandAssetAsync(client, config.ResourceGroup, config.AccountName, streamingLocatorName, assetName); } }
private static async Task RunAsync2(ConfigWrapper config) { IAzureMediaServicesClient client = await CreateMediaServicesClientAsync(config); // 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 streamingLocatorName = "streamingLocator" + uniqueness; string streamingEndpointName = "default"; try { Task <LiveEvent> liveEventTask = CreateLiveEventAsync(client, config.ResourceGroup, config.AccountName, liveEventName); Task <StreamingLocator> streamingLocatorTask = CreateAssetAndLocatorAsync(client, config.ResourceGroup, config.AccountName, assetName, streamingLocatorName); Task <StreamingEndpoint> startStreamingEndpointTask = StartStreamingEndpointAsync(client, config.ResourceGroup, config.AccountName, assetName, streamingEndpointName); Task[] tasks = new Task[] { liveEventTask, streamingLocatorTask, startStreamingEndpointTask }; Task.WaitAll(tasks); LiveEvent liveEvent = liveEventTask.Result; StreamingEndpoint streamingEndpoint = startStreamingEndpointTask.Result; // 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("Press enter to continue..."); Console.Out.Flush(); var ignoredInput = Console.ReadLine(); // Create the LiveOutput string manifestName = "output"; Console.WriteLine($"Creating a live output named {liveOutputName}"); Console.WriteLine(); LiveOutput liveOutput = new LiveOutput(assetName: assetName, manifestName: manifestName, archiveWindowLength: TimeSpan.FromMinutes(10)); liveOutput = await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveOutputName, liveOutput); // Get the url to stream the output var paths = await client.StreamingLocators.ListPathsAsync(config.ResourceGroup, config.AccountName, streamingLocatorName); Console.WriteLine("The urls to stream the output from a client:"); Console.WriteLine(); StringBuilder stringBuilder = new StringBuilder(); string playerPath = string.Empty; 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]; stringBuilder.AppendLine($"\t{paths.StreamingPaths[i].StreamingProtocol}-{paths.StreamingPaths[i].EncryptionScheme}"); stringBuilder.AppendLine($"\t\t{uriBuilder.ToString()}"); stringBuilder.AppendLine(); if (paths.StreamingPaths[i].StreamingProtocol == StreamingPolicyStreamingProtocol.Dash) { playerPath = uriBuilder.ToString(); } } } if (stringBuilder.Length > 0) { Console.WriteLine(stringBuilder.ToString()); Console.WriteLine("Open the following URL to playback the published,recording LiveOutput in the Azure Media Player"); Console.WriteLine($"\t https://ampdemo.azureedge.net/?url={playerPath}&heuristicprofile=lowlatency"); Console.WriteLine(); Console.WriteLine("Continue experimenting with the stream until you are ready to finish."); Console.WriteLine("Press enter to stop the LiveOutput..."); Console.Out.Flush(); ignoredInput = Console.ReadLine(); 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."); Console.WriteLine("Press enter to finish cleanup..."); Console.Out.Flush(); ignoredInput = Console.ReadLine(); } else { Console.WriteLine("No Streaming Paths were detected. Has the Stream been started?"); Console.WriteLine("Cleaning up and Exiting..."); } } 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 CleanupLocatorandAssetAsync(client, config.ResourceGroup, config.AccountName, streamingLocatorName, assetName); } }
/// <summary> /// Checks if the "default" streaming endpoint is in the running state, /// if not, starts it. /// Then, builds the streaming URLs. /// </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="locatorName">The name of the StreamingLocator that was created.</param> /// <returns></returns> private static async Task <string> GetDASHStreamingUrlAsync(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string locatorName, StreamingEndpoint streamingEndpoint) { string dashPath = ""; ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName); foreach (StreamingPath path in paths.StreamingPaths) { UriBuilder uriBuilder = new() { Scheme = "https", Host = streamingEndpoint.HostName }; // Look for just the DASH path and generate a URL for the Azure Media Player to playback the encrypted DASH content. // Note that the JWT token is set to expire in 1 hour. if (path.StreamingProtocol == StreamingPolicyStreamingProtocol.Dash) { uriBuilder.Path = path.Paths[0]; dashPath = uriBuilder.ToString(); } } return(dashPath); }
/// <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("N"); string jobName = $"job-{uniqueness}"; string locatorName = $"locator-{uniqueness}"; string outputAssetName = $"output-{uniqueness}"; bool stopEndpoint = false; EventProcessorHost eventProcessorHost = null; try { // 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); try { // First we will try to process Job events through Event Hub in real-time. If this fails for any reason, // we will fall-back on polling Job status instead. // Please refer README for Event Hub and storage settings. 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); // Create an AutoResetEvent to wait for the job to finish and pass it to EventProcessor so that it can be set when a final state event is received. AutoResetEvent jobWaitingEvent = new AutoResetEvent(false); // Registers the Event Processor Host and starts receiving messages. Pass in jobWaitingEvent so it can be called back. await eventProcessorHost.RegisterEventProcessorFactoryAsync(new MediaServicesEventProcessorFactory(jobName, jobWaitingEvent), EventProcessorOptions.DefaultOptions); // Create a Task list, adding a job waiting task and a timer task. Other tasks can be added too. IList <Task> tasks = new List <Task>(); // Add a task to wait for the job to finish. jobWaitingEvent will be set when a final state is received by EventProcessor. Task jobTask = Task.Run(() => jobWaitingEvent.WaitOne()); tasks.Add(jobTask); // 30 minutes timeout. var tokenSource = new CancellationTokenSource(); var timeout = Task.Delay(30 * 60 * 1000, tokenSource.Token); tasks.Add(timeout); // Wait for any task to finish. if (await Task.WhenAny(tasks) == jobTask) { // Job finished. Cancel the timer. tokenSource.Cancel(); // Get the latest status of the job. job = await client.Jobs.GetAsync(config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName); } else { // Timeout happened, Something might go wrong with job events. Fall-back on polling instead. jobWaitingEvent.Set(); throw new Exception("Timeout happened."); } } catch (Exception) { Console.WriteLine("Warning: Failed to connect to Event Hub, please refer README for Event Hub and storage settings."); // 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. Console.WriteLine("Polling job status..."); 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); // Sets StreamingLocator.StreamingPolicyName to "Predefined_MultiDrmCencStreaming" policy. StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName, ContentKeyPolicyName); // In this example, we want to play the Widevine (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 (streamingEndpoint != null) { if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { Console.WriteLine("Streaming Endpoint was Stopped, restarting now.."); await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); // 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); 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 Chrome/Firefox for Widevine."); Console.WriteLine(); Console.WriteLine($"https://ampdemo.azureedge.net/?url={dashPath}&widevine=true&token=Bearer%3D{token}"); Console.WriteLine(); } Console.WriteLine("When finished testing press enter to cleanup."); Console.Out.Flush(); Console.ReadLine(); } catch (ApiErrorException e) { Console.WriteLine("Hit ApiErrorException"); Console.WriteLine($"\tCode: {e.Body.Error.Code}"); Console.WriteLine($"\tMessage: {e.Body.Error.Message}"); Console.WriteLine(); Console.WriteLine("Exiting, cleanup may be necessary..."); Console.ReadLine(); } finally { Console.WriteLine("Cleaning up..."); await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAssetName, jobName, ContentKeyPolicyName, stopEndpoint, DefaultStreamingEndpointName); if (eventProcessorHost != null) { Console.WriteLine("Unregistering event processor..."); // Disposes of the Event Processor Host. await eventProcessorHost.UnregisterEventProcessorAsync(); Console.WriteLine(); } } }
/// <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 Authentication.CreateMediaServicesClientAsync(config, UseInteractiveAuth); } catch (Exception e) { Console.Error.WriteLine("TIP: Make sure that you have filled out the appsettings.json or .env 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("N"); string jobName = $"job-{uniqueness}"; string locatorName = $"locator-{uniqueness}"; string outputAssetName = $"output-{uniqueness}"; bool stopEndpoint = false; // In this sample, we use Event Grid to listen to the notifications through an Azure Event Hub. // If you do not provide an Event Hub config in the settings, the sample will fall back to polling the job for status. // For production ready code, it is always recommended to use Event Grid instead of polling on the Job status. EventProcessorClient processorClient = null; BlobContainerClient storageClient = null; MediaServicesEventProcessor mediaEventProcessor = null; try { // 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); try { // First we will try to process Job events through Event Hub in real-time. If this fails for any reason, // we will fall-back on polling Job status instead. // Please refer README for Event Hub and storage settings. // A storage account is required to process the Event Hub events from the Event Grid subscription in this sample. // Create a new host to process events from an Event Hub. Console.WriteLine("Creating a new client to process events from an Event Hub..."); var credential = new DefaultAzureCredential(); var storageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", config.StorageAccountName, config.StorageAccountKey); var blobContainerName = config.StorageContainerName; var eventHubsConnectionString = config.EventHubConnectionString; var eventHubName = config.EventHubName; var consumerGroup = config.EventHubConsumerGroup; storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); processorClient = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName); // Create an AutoResetEvent to wait for the job to finish and pass it to EventProcessor so that it can be set when a final state event is received. AutoResetEvent jobWaitingEvent = new(false); // Create a Task list, adding a job waiting task and a timer task. Other tasks can be added too. IList <Task> tasks = new List <Task>(); // Add a task to wait for the job to finish. jobWaitingEvent will be set when a final state is received by EventProcessor. Task jobTask = Task.Run(() => jobWaitingEvent.WaitOne()); tasks.Add(jobTask); // 30 minutes timeout. var cancellationSource = new CancellationTokenSource(); var timeout = Task.Delay(30 * 60 * 1000, cancellationSource.Token); tasks.Add(timeout); mediaEventProcessor = new MediaServicesEventProcessor(jobName, jobWaitingEvent, null); processorClient.ProcessEventAsync += mediaEventProcessor.ProcessEventsAsync; processorClient.ProcessErrorAsync += mediaEventProcessor.ProcessErrorAsync; // Wait for any task to finish. if (await Task.WhenAny(tasks) == jobTask) { // Job finished. Cancel the timer. cancellationSource.Cancel(); // Get the latest status of the job. job = await client.Jobs.GetAsync(config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName); } else { // Timeout happened, Something might go wrong with job events. Fall-back on polling instead. jobWaitingEvent.Set(); throw new Exception("Timeout happened."); } } catch (Exception) { Console.WriteLine("Warning: Failed to connect to Event Hub, please refer README for Event Hub and storage settings."); // 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. Console.WriteLine("Polling job status..."); job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName); } if (job.State == JobState.Finished) { // 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 = await GetOrCreateContentKeyPolicyAsync(client, config, ContentKeyPolicyName); StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName, policy.Name); StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); // Since we started the endpoint, we should stop it in cleanup. stopEndpoint = true; } string hlsPath = await GetHlsStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locator.Name, streamingEndpoint); Console.WriteLine(); Console.WriteLine("HLS url can be played on your Apple device:"); Console.WriteLine(hlsPath); Console.WriteLine(); } Console.WriteLine("When finished testing press enter to cleanup."); Console.Out.Flush(); Console.ReadLine(); } catch (ErrorResponseException e) { Console.WriteLine("ErrorResponseException"); Console.WriteLine($"\tCode: {e.Body.Error.Code}"); Console.WriteLine($"\tMessage: {e.Body.Error.Message}"); Console.WriteLine(); Console.WriteLine("Exiting, cleanup may be necessary..."); Console.ReadLine(); } finally { Console.WriteLine("Cleaning up..."); await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAssetName, jobName, ContentKeyPolicyName, stopEndpoint, DefaultStreamingEndpointName); if (processorClient != null) { Console.WriteLine("Job final state received, Stopping the event processor..."); await processorClient.StopProcessingAsync(); Console.WriteLine(); // It is encouraged that you unregister your handlers when you have // finished using the Event Processor to ensure proper cleanup. This // is especially important when using lambda expressions or handlers // in any form that may contain closure scopes or hold other references. processorClient.ProcessEventAsync -= mediaEventProcessor.ProcessEventsAsync; processorClient.ProcessErrorAsync -= mediaEventProcessor.ProcessErrorAsync; } } }
/// <summary> /// Builds the HLS streaming URL. /// </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="locatorName">The name of the StreamingLocator that was created.</param> /// <param name="streamingEndpoint">The streaming endpoint.</param> /// <returns></returns> private static async Task <string> GetHlsStreamingUrlAsync(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string locatorName, StreamingEndpoint streamingEndpoint) { string hlsPath = ""; ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName); foreach (StreamingPath path in paths.StreamingPaths) { UriBuilder uriBuilder = new() { Scheme = "https", Host = streamingEndpoint.HostName }; // Look for just the HLS path and generate a URL for Apple device to playback the encrypted content. if (path.StreamingProtocol == StreamingPolicyStreamingProtocol.Hls) { uriBuilder.Path = path.Paths[0]; hlsPath = uriBuilder.ToString(); } } return(hlsPath); }
public StreamingEndpointInformation(StreamingEndpoint streamingEndpoint) { InitializeComponent(); this.Icon = Bitmaps.Azure_Explorer_ico; MySE = streamingEndpoint; }
private async void ChooseStreamingEndpoint_Load(object sender, EventArgs e) { DpiUtils.InitPerMonitorDpi(this); label.Text = string.Format(label.Text, _asset.Name); // SE List await _amsClient.RefreshTokenIfNeededAsync(); // StreamingEndpoint BestSE = Task.Run(async () => await AssetInfo.GetBestStreamingEndpointAsync(_client)).Result; StreamingEndpoint BestSE = await AssetInfo.GetBestStreamingEndpointAsync(_amsClient); var myStreamingEndpoints = Task.Run(() => _amsClient.AMSclient.StreamingEndpoints.ListAsync(_amsClient.credentialsEntry.ResourceGroup, _amsClient.credentialsEntry.AccountName)).GetAwaiter().GetResult(); foreach (StreamingEndpoint se in myStreamingEndpoints) { listBoxSE.Items.Add(new Item(string.Format(AMSExplorer.Properties.Resources.AssetInformation_AssetInformation_Load_012ScaleUnit, se.Name, se.ResourceState, StreamingEndpointInformation.ReturnTypeSE(se)), se.Name + "|" + se.HostName)); if (se.Id == BestSE.Id) { listBoxSE.SelectedIndex = listBoxSE.Items.Count - 1; } foreach (string custom in se.CustomHostNames) { listBoxSE.Items.Add(new Item(string.Format(AMSExplorer.Properties.Resources.AssetInformation_AssetInformation_Load_012ScaleUnitCustomHostname3, se.Name, se.ResourceState, StreamingEndpointInformation.ReturnTypeSE(se), custom), se.Name + "|" + custom)); } } // Filters // asset filters Microsoft.Rest.Azure.IPage <AssetFilter> assetFilters = await _amsClient.AMSclient.AssetFilters.ListAsync(_amsClient.credentialsEntry.ResourceGroup, _amsClient.credentialsEntry.AccountName, _asset.Name); List <string> afiltersnames = assetFilters.Select(a => a.Name).ToList(); listViewFilters.BeginUpdate(); assetFilters.ToList().ForEach(f => { ListViewItem lvitem = new ListViewItem(new string[] { AMSExplorer.Properties.Resources.ChooseStreamingEndpoint_ChooseStreamingEndpoint_Load_AssetFilter + f.Name, f.Name }); if (_filter != null && f.Name == _filter) { lvitem.Checked = true; } listViewFilters.Items.Add(lvitem); } ); // account filters IPage <AccountFilter> acctFilters = await _amsClient.AMSclient.AccountFilters.ListAsync(_amsClient.credentialsEntry.ResourceGroup, _amsClient.credentialsEntry.AccountName); acctFilters.ToList().ForEach(f => { ListViewItem lvitem = new ListViewItem(new string[] { AMSExplorer.Properties.Resources.ChooseStreamingEndpoint_ChooseStreamingEndpoint_Load_GlobalFilter + f.Name, f.Name }); if (_filter != null && f.Name == _filter && listViewFilters.CheckedItems.Count == 0) // only if not already selected (asset filter priority > account filter) { lvitem.Checked = true; } if (afiltersnames.Contains(f.Name)) // global filter with same name than asset filter { lvitem.ForeColor = Color.Gray; } listViewFilters.Items.Add(lvitem); } ); listViewFilters.EndUpdate(); if (_playertype == PlayerType.DASHIFRefPlayer) { radioButtonDASHCSF.Checked = true; } comboBoxBrowser.Items.Add(new Item(AMSExplorer.Properties.Resources.ChooseStreamingEndpoint_ChooseStreamingEndpoint_Load_DefaultBrowser, string.Empty)); if (_displayBrowserSelection) { // let's add the browser options to lplayback the content (IE, Edge, Chrome...) if (IsWindows10()) { comboBoxBrowser.Items.Add(new Item(Constants.BrowserEdge[0], Constants.BrowserEdge[1])); } comboBoxBrowser.Items.Add(new Item(Constants.BrowserIE[0], Constants.BrowserIE[1])); comboBoxBrowser.Items.Add(new Item(Constants.BrowserChrome[0], Constants.BrowserChrome[1])); comboBoxBrowser.SelectedIndex = 0; } comboBoxBrowser.Visible = _displayBrowserSelection; UpdatePreviewUrl(); FillLocatorComboInPolicyTab(); }
/// <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("N"); string jobName = $"job-{uniqueness}"; string locatorName = $"locator-{uniqueness}"; string outputAssetName = $"output-{uniqueness}"; string inputAssetName = $"input-{uniqueness}"; bool stopEndpoint = false; try { // 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); // Create a new input Asset and upload the specified local video file into it. await CreateInputAssetAsync(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName); // 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, transform.Name, jobName, inputAssetName, outputAsset.Name); // 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. To see how to implement the event grid, see the sample // https://github.com/Azure-Samples/media-services-v3-dotnet/tree/master/ContentProtection/BasicAESClearKey. job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, transform.Name, jobName); if (job.State == JobState.Finished) { Console.WriteLine("Job finished."); StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName); StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); if (streamingEndpoint != null) { if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { Console.WriteLine("Streaming Endpoint was Stopped, restarting now.."); await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); // Since we started the endpoint, we should stop it in cleanup. stopEndpoint = true; } IList <string> urls = await GetHLSAndDASHStreamingUrlsAsync(client, config.ResourceGroup, config.AccountName, locator.Name, streamingEndpoint); Console.WriteLine(); foreach (var url in urls) { Console.WriteLine(url); } Console.WriteLine(); Console.WriteLine("Copy and paste the Streaming URL into the Azure Media Player at 'http://aka.ms/azuremediaplayer'."); Console.WriteLine("When finished press enter to cleanup."); Console.Out.Flush(); Console.ReadLine(); } } } catch (ApiErrorException e) { Console.WriteLine("Hit ApiErrorException"); Console.WriteLine($"\tCode: {e.Body.Error.Code}"); Console.WriteLine($"\tMessage: {e.Body.Error.Message}"); Console.WriteLine(); Console.WriteLine("Exiting, cleanup may be necessary..."); Console.ReadLine(); } finally { Console.WriteLine("Cleaning up..."); await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName, inputAssetName, outputAssetName, stopEndpoint, DefaultStreamingEndpointName); Console.WriteLine("Done."); } }
/// <summary> /// Update StreamingEndpoint /// </summary> /// <remarks> /// Updates a existing streaming endpoint. /// </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='streamingEndpointName'> /// The name of the streaming endpoint, maximum length is 24. /// </param> /// <param name='parameters'> /// Streaming endpoint properties needed for creation. /// </param> public static StreamingEndpoint BeginUpdate(this IStreamingEndpointsOperations operations, string resourceGroupName, string accountName, string streamingEndpointName, StreamingEndpoint parameters) { return(operations.BeginUpdateAsync(resourceGroupName, accountName, streamingEndpointName, parameters).GetAwaiter().GetResult()); }
/// <summary> /// Create StreamingEndpoint /// </summary> /// <remarks> /// Creates a streaming endpoint. /// </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='streamingEndpointName'> /// The name of the streaming endpoint, maximum length is 24. /// </param> /// <param name='parameters'> /// Streaming endpoint properties needed for creation. /// </param> /// <param name='autoStart'> /// The flag indicates if the resource should be automatically started on /// creation. /// </param> public static StreamingEndpoint BeginCreate(this IStreamingEndpointsOperations operations, string resourceGroupName, string accountName, string streamingEndpointName, StreamingEndpoint parameters, bool?autoStart = default(bool?)) { return(operations.BeginCreateAsync(resourceGroupName, accountName, streamingEndpointName, parameters, autoStart).GetAwaiter().GetResult()); }
/// <summary> /// Checks if the streaming endpoint is in the running state, /// if not, starts it. Then, builds the streaming URLs. /// </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="locatorName">The name of the StreamingLocator that was created.</param> /// <param name="streamingEndpoint">The streaming endpoint.</param> /// <returns>A task.</returns> private static async Task <IList <string> > GetDashStreamingUrlsAsync(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string locatorName, StreamingEndpoint streamingEndpoint) { IList <string> streamingUrls = new List <string>(); ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName); foreach (StreamingPath path in paths.StreamingPaths) { UriBuilder uriBuilder = new UriBuilder { Scheme = "https", Host = streamingEndpoint.HostName, Path = path.Paths[0] }; if (path.StreamingProtocol == StreamingPolicyStreamingProtocol.Dash) { streamingUrls.Add(uriBuilder.ToString()); } } return(streamingUrls); }
/// <summary> /// Update StreamingEndpoint /// </summary> /// <remarks> /// Updates a existing streaming endpoint. /// </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='streamingEndpointName'> /// The name of the streaming endpoint, maximum length is 24. /// </param> /// <param name='parameters'> /// Streaming endpoint properties needed for creation. /// </param> /// <param name='cancellationToken'> /// The cancellation token. /// </param> public static async Task <StreamingEndpoint> BeginUpdateAsync(this IStreamingEndpointsOperations operations, string resourceGroupName, string accountName, string streamingEndpointName, StreamingEndpoint parameters, CancellationToken cancellationToken = default(CancellationToken)) { using (var _result = await operations.BeginUpdateWithHttpMessagesAsync(resourceGroupName, accountName, streamingEndpointName, parameters, null, cancellationToken).ConfigureAwait(false)) { return(_result.Body); } }
/// <summary> /// Run the sample async. /// </summary> /// <param name="config">This param is of type ConfigWrapper, which reads values from local configuration file.</param> /// <returns>A task.</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 jobName = "job-" + uniqueness; string locatorName = "locator-" + uniqueness; string outputAssetName = "output-" + uniqueness; string assetFilterName = "assetFilter-" + uniqueness; string accountFilterName = "accountFilter-" + uniqueness; string inputAssetName = "input-" + uniqueness; bool stopEndpoint = false; try { // Ensure that you have customized encoding Transform. This is really a one time setup operation. Transform adaptiveEncodeTransform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, adaptiveTransformName); // Create a new input Asset and upload the specified local video file into it. Asset inputAsset = await CreateInputAssetAndUploadVideoAsync(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName); // 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); Console.WriteLine("Creating a job..."); Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, adaptiveTransformName, jobName, inputAssetName, outputAsset.Name); DateTime startedTime = DateTime.Now; // 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. To see how to implement the event grid, see the sample // https://github.com/Azure-Samples/media-services-v3-dotnet/tree/master/ContentProtection/BasicAESClearKey. job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, adaptiveTransformName, jobName); TimeSpan elapsed = DateTime.Now - startedTime; Console.WriteLine($"Job elapsed time: {elapsed}"); if (job.State == JobState.Finished) { Console.WriteLine("Job finished."); // Now that the content has been encoded, publish it for Streaming by creating // a StreamingLocator. StreamingLocator locator = await client.StreamingLocators.CreateAsync( config.ResourceGroup, config.AccountName, locatorName, new StreamingLocator { AssetName = outputAsset.Name, StreamingPolicyName = PredefinedStreamingPolicy.ClearStreamingOnly }); StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); if (streamingEndpoint != null) { if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running) { Console.WriteLine("Streaming Endpoint was Stopped, restarting now.."); await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName); // Since we started the endpoint, we should stop it in cleanup. stopEndpoint = true; } } IList <string> urls = await GetDashStreamingUrlsAsync(client, config.ResourceGroup, config.AccountName, locator.Name, streamingEndpoint); Console.WriteLine("Creating an asset filter..."); Console.WriteLine(); AssetFilter assetFilter = await CreateAssetFilterAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, assetFilterName); Console.WriteLine("Creating an account filter..."); Console.WriteLine(); AccountFilter accountFilter = await CreateAccountFilterAsync(client, config.ResourceGroup, config.AccountName, accountFilterName); Console.WriteLine("We are going to use two different ways to show how to filter content. First, we will append the filters to the url(s)."); Console.WriteLine("Url(s) with filters:"); foreach (var url in urls) { if (url.EndsWith(")")) { Console.WriteLine(Regex.Replace(url, @"\)$", $",filter={assetFilter.Name};{accountFilter.Name})")); } else { Console.WriteLine($"{url}(filter={assetFilter.Name};{accountFilter.Name})"); } } Console.WriteLine(); Console.WriteLine("Copy and paste the streaming URL into the Azure Media Player at 'http://aka.ms/azuremediaplayer'."); Console.WriteLine("Please note that we have used two filters in the url(s), one trimmed the start and the end of the media"); Console.WriteLine("and the other removed high resolution video tracks. To stream the original content, remove the filters"); Console.WriteLine("from the url(s) and update player."); Console.WriteLine("When finished, press ENTER to continue."); Console.WriteLine(); Console.Out.Flush(); Console.ReadLine(); // Create a new StreamingLocator and associate filters with it. Console.WriteLine("Next, we will associate the filters with a new streaming locator."); await client.StreamingLocators.DeleteAsync(config.ResourceGroup, config.AccountName, locatorName); // Delete the old locator. Console.WriteLine("Creating a new streaming locator..."); IList <string> filters = new List <string> { assetFilter.Name, accountFilter.Name }; locator = await client.StreamingLocators.CreateAsync( config.ResourceGroup, config.AccountName, locatorName, new StreamingLocator { AssetName = outputAsset.Name, StreamingPolicyName = PredefinedStreamingPolicy.ClearStreamingOnly, Filters = filters }); urls = await GetDashStreamingUrlsAsync(client, config.ResourceGroup, config.AccountName, locator.Name, streamingEndpoint); Console.WriteLine("Since we have associated filters with the new streaming locator, No need to append filters to the url(s):"); foreach (string url in urls) { Console.WriteLine(url); } Console.WriteLine(); Console.WriteLine("Copy and paste the Streaming URL into the Azure Media Player at 'http://aka.ms/azuremediaplayer'."); Console.WriteLine("When finished, press ENTER to continue."); Console.Out.Flush(); Console.ReadLine(); } 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}"); } } catch (ApiErrorException e) { Console.WriteLine("Hit ApiErrorException"); Console.WriteLine($"\tCode: {e.Body.Error.Code}"); Console.WriteLine($"\tMessage: {e.Body.Error.Message}"); Console.WriteLine(); Console.WriteLine("Exiting, cleanup may be necessary..."); Console.ReadLine(); } finally { Console.WriteLine("Cleaning up..."); await CleanUpAsync(client, config.ResourceGroup, config.AccountName, adaptiveTransformName, jobName, inputAssetName, outputAssetName, accountFilterName, locatorName, stopEndpoint, DefaultStreamingEndpointName); Console.WriteLine("Done."); } }