Come eseguire lo streaming live con codificatori locali mediante .NETHow to perform live streaming with on-premises encoders using .NET

Questa esercitazione illustra come usare l'SDK di Servizi multimediali di Azure per .NET per creare un canale configurato per la distribuzione pass-through.This tutorial walks you through the steps of using the Azure Media Services .NET SDK to create a Channel that is configured for a pass-through delivery.

PrerequisitiPrerequisites

Per completare l'esercitazione è necessario quanto segue:The following are required to complete the tutorial:

È consigliabile esaminare i seguenti articoli:Recommended to review the following articles:

Creare e configurare un progetto di Visual StudioCreate and configure a Visual Studio project

Configurare l'ambiente di sviluppo e popolare il file app.config con le informazioni di connessione, come descritto in Sviluppo di applicazioni di Servizi multimediali con .NET.Set up your development environment and populate the app.config file with connection information, as described in Media Services development with .NET.

EsempioExample

Il seguente esempio di codice illustra come ottenere le attività seguenti:The following code example demonstrates how to achieve the following tasks:

  • Connettersi a Servizi multimedialiConnect to Media Services
  • Creare un canaleCreate a channel
  • Aggiornare il canaleUpdate the channel
  • Recuperare l'endpoint di input del canale.Retrieve the channel’s input endpoint. È necessario fornire l'endpoint di input al codificatore live locale.The input endpoint should be provided to the on-premises live encoder. Il codificatore live converte i segnali dalla fotocamera ai flussi che vengono inviati all'endpoint di input del canale (inserimento).The live encoder converts signals from the camera to streams that are sent to the channel’s input (ingest) endpoint.
  • Recuperare l'endpoint di anteprima del canaleRetrieve the channel’s preview endpoint
  • Creare e avviare un programmaCreate and start a program
  • Creare un localizzatore necessario per accedere al programmaCreate a locator needed to access the program
  • Creare e avviare uno StreamingEndpointCreate and start a StreamingEndpoint
  • Aggiornare l'endpoint di streamingUpdate the streaming endpoint
  • Arresto delle risorseShut down resources

Importante

Verificare che l'endpoint di streaming da cui si vuole trasmettere il contenuto sia nello stato In esecuzione.Make sure the streaming endpoint from which you want to stream content is in the Running state.

Nota

È previsto un limite di 1.000.000 di criteri per i diversi criteri AMS (ad esempio per i criteri Locator o ContentKeyAuthorizationPolicy).There is a limit of 1,000,000 policies for different AMS policies (for example, for Locator policy or ContentKeyAuthorizationPolicy). Usare lo stesso ID criterio se si usano sempre gli stessi giorni/autorizzazioni di accesso, come nel cado di criteri per i localizzatori che devono rimanere attivi per molto tempo (criteri di non caricamento).You should use the same policy ID if you are always using the same days / access permissions, for example, policies for locators that are intended to remain in place for a long time (non-upload policies). Per altre informazioni, vedere questo argomento.For more information, see this topic.

Per informazioni su come configurare un codificatore live, vedere Codificatori live e supporto RTMP di Servizi multimediali di Azure.For information on how to configure a live encoder, see Azure Media Services RTMP Support and Live Encoders.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using Microsoft.WindowsAzure.MediaServices.Client;

namespace AMSLiveTest
{
    class Program
    {
    private const string StreamingEndpointName = "streamingendpoint001";
    private const string ChannelName = "channel001";
    private const string AssetlName = "asset001";
    private const string ProgramlName = "program001";

    // Read values from the App.config file.
    private static readonly string _AADTenantDomain =
    ConfigurationManager.AppSettings["AADTenantDomain"];
    private static readonly string _RESTAPIEndpoint =
    ConfigurationManager.AppSettings["MediaServiceRESTAPIEndpoint"];

    private static CloudMediaContext _context = null;

    static void Main(string[] args)
    {
        var tokenCredentials = new AzureAdTokenCredentials(_AADTenantDomain, AzureEnvironments.AzureCloudEnvironment);
        var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

        _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);

        IChannel channel = CreateAndStartChannel();

        // Set the Live Encoder to point to the channel's input endpoint:
        string ingestUrl = channel.Input.Endpoints.FirstOrDefault().Url.ToString();

        // Use the previewEndpoint to preview and verify
        // that the input from the encoder is actually reaching the Channel.
        string previewEndpoint = channel.Preview.Endpoints.FirstOrDefault().Url.ToString();

        IProgram program = CreateAndStartProgram(channel);
        ILocator locator = CreateLocatorForAsset(program.Asset, program.ArchiveWindowLength);
        IStreamingEndpoint streamingEndpoint = CreateAndStartStreamingEndpoint(false);

        // Once you are done streaming, clean up your resources.
        Cleanup(streamingEndpoint, channel);
    }

    public static IChannel CreateAndStartChannel()
    {
        //If you want to change the Smooth fragments to HLS segment ratio, you would set the ChannelCreationOptions’s Output property.

        IChannel channel = _context.Channels.Create(
        new ChannelCreationOptions
        {
        Name = ChannelName,
        Input = CreateChannelInput(),
        Preview = CreateChannelPreview()
        });

        //Starting and stopping Channels can take some time to execute. To determine the state of operations after calling Start or Stop, query the IChannel.State .

        channel.Start();

        return channel;
    }

    private static ChannelInput CreateChannelInput()
    {
        return new ChannelInput
        {
        StreamingProtocol = StreamingProtocol.RTMP,
        AccessControl = new ChannelAccessControl
        {
            IPAllowList = new List<IPRange>
                {
                new IPRange
                {
                Name = "TestChannelInput001",
                // Setting 0.0.0.0 for Address and 0 for SubnetPrefixLength
                // will allow access to IP addresses.
                Address = IPAddress.Parse("0.0.0.0"),
                SubnetPrefixLength = 0
                }
            }
        }
        };
    }

    private static ChannelPreview CreateChannelPreview()
    {
        return new ChannelPreview
        {
        AccessControl = new ChannelAccessControl
        {
            IPAllowList = new List<IPRange>
            {
                new IPRange
                {
                Name = "TestChannelPreview001",
                // Setting 0.0.0.0 for Address and 0 for SubnetPrefixLength
                // will allow access to IP addresses.
                Address = IPAddress.Parse("0.0.0.0"),
                SubnetPrefixLength = 0
                }
            }
        }
        };
    }

    public static void UpdateCrossSiteAccessPoliciesForChannel(IChannel channel)
    {
        var clientPolicy =
        @"<?xml version=""1.0"" encoding=""utf-8""?>
        <access-policy>
            <cross-domain-access>
            <policy>
                <allow-from http-request-headers=""*"" http-methods=""*"">
                <domain uri=""*""/>
                </allow-from>
                <grant-to>
                   <resource path=""/"" include-subpaths=""true""/>
                </grant-to>
            </policy>
            </cross-domain-access>
        </access-policy>";

        var xdomainPolicy =
        @"<?xml version=""1.0"" ?>
        <cross-domain-policy>
            <allow-access-from domain=""*"" />
        </cross-domain-policy>";

        channel.CrossSiteAccessPolicies.ClientAccessPolicy = clientPolicy;
        channel.CrossSiteAccessPolicies.CrossDomainPolicy = xdomainPolicy;

        channel.Update();
    }

    public static IProgram CreateAndStartProgram(IChannel channel)
    {
        IAsset asset = _context.Assets.Create(AssetlName, AssetCreationOptions.None);

        // Create a Program on the Channel. You can have multiple Programs that overlap or are sequential;
        // however each Program must have a unique name within your Media Services account.
        IProgram program = channel.Programs.Create(ProgramlName, TimeSpan.FromHours(3), asset.Id);
        program.Start();

        return program;
    }

    public static ILocator CreateLocatorForAsset(IAsset asset, TimeSpan ArchiveWindowLength)
    {
        // You cannot create a streaming locator using an AccessPolicy that includes write or delete permissions.            

        var locator = _context.Locators.CreateLocator
        (
            LocatorType.OnDemandOrigin,
            asset,
            _context.AccessPolicies.Create
            (
            "Live Stream Policy",
            ArchiveWindowLength,
            AccessPermissions.Read
            )
        );

        return locator;
    }

    public static IStreamingEndpoint CreateAndStartStreamingEndpoint(bool createNew)
    {
        IStreamingEndpoint streamingEndpoint = null;
        if (createNew)
        {
        var options = new StreamingEndpointCreationOptions
        {
            Name = StreamingEndpointName,
            ScaleUnits = 1,
            AccessControl = GetAccessControl(),
            CacheControl = GetCacheControl()
        };

        streamingEndpoint = _context.StreamingEndpoints.Create(options);
        }
        else
        {
        streamingEndpoint = _context.StreamingEndpoints.FirstOrDefault();
        }


        if (streamingEndpoint.State == StreamingEndpointState.Stopped)
        streamingEndpoint.Start();

        return streamingEndpoint;
    }

    private static StreamingEndpointAccessControl GetAccessControl()
    {
        return new StreamingEndpointAccessControl
        {
        IPAllowList = new List<IPRange>
            {
            new IPRange
            {
                Name = "Allow all",
                Address = IPAddress.Parse("0.0.0.0"),
                SubnetPrefixLength = 0
            }
            },

        AkamaiSignatureHeaderAuthenticationKeyList = new List<AkamaiSignatureHeaderAuthenticationKey>
            {
            new AkamaiSignatureHeaderAuthenticationKey
            {
                Identifier = "My key",
                Expiration = DateTime.UtcNow + TimeSpan.FromDays(365),
                Base64Key = Convert.ToBase64String(GenerateRandomBytes(16))
            }
            }
        };
    }

    private static byte[] GenerateRandomBytes(int length)
    {
        var bytes = new byte[length];
        using (var rng = new RNGCryptoServiceProvider())
        {
        rng.GetBytes(bytes);
        }

        return bytes;
    }

    private static StreamingEndpointCacheControl GetCacheControl()
    {
        return new StreamingEndpointCacheControl
        {
        MaxAge = TimeSpan.FromSeconds(1000)
        };
    }

    public static void UpdateCrossSiteAccessPoliciesForStreamingEndpoint(IStreamingEndpoint streamingEndpoint)
    {
        var clientPolicy =
        @"<?xml version=""1.0"" encoding=""utf-8""?>
        <access-policy>
            <cross-domain-access>
            <policy>
                <allow-from http-request-headers=""*"" http-methods=""*"">
                <domain uri=""*""/>
                </allow-from>
                <grant-to>
                   <resource path=""/"" include-subpaths=""true""/>
                </grant-to>
            </policy>
            </cross-domain-access>
        </access-policy>";

        var xdomainPolicy =
        @"<?xml version=""1.0"" ?>
        <cross-domain-policy>
            <allow-access-from domain=""*"" />
        </cross-domain-policy>";

        streamingEndpoint.CrossSiteAccessPolicies.ClientAccessPolicy = clientPolicy;
        streamingEndpoint.CrossSiteAccessPolicies.CrossDomainPolicy = xdomainPolicy;

        streamingEndpoint.Update();
    }

    public static void Cleanup(IStreamingEndpoint streamingEndpoint,
                    IChannel channel)
    {
        if (streamingEndpoint != null)
        {
        streamingEndpoint.Stop();
        if(streamingEndpoint.Name != "default")
            streamingEndpoint.Delete();
        }

        IAsset asset;
        if (channel != null)
        {

        foreach (var program in channel.Programs)
        {
            asset = _context.Assets.Where(se => se.Id == program.AssetId)
                        .FirstOrDefault();

            program.Stop();
            program.Delete();

            if (asset != null)
            {
            foreach (var l in asset.Locators)
                l.Delete();

            asset.Delete();
            }
        }

        channel.Stop();
        channel.Delete();
        }
    }
    }
}

Passaggio successivoNext Step

Analizzare i percorsi di apprendimento dei Servizi multimedialiReview Media Services learning paths

Altre informazioni sui percorsi di apprendimento di Servizi multimediali di Azure:Read about the Azure Media Services learning paths:

Fornire commenti e suggerimentiProvide feedback

Usare il forum di suggerimenti degli utenti per fornire commenti e suggerimenti su come migliorare Servizi multimediali di Azure.Use the User Voice forum to provide feedback and make suggestions on how to improve Azure Media Services. È anche possibile passare direttamente a una delle categorie seguenti:You also can go directly to one of the following categories: