Tutorial: Stream ao vivo com Serviços de Multimédia utilizando .NET 5.0

Em Serviços de Multimédia do Azure, os eventos ao vivo são responsáveis pelo processamento de conteúdos de streaming ao vivo. Um evento ao vivo fornece um ponto final de entrada (ingest URL) que você fornece a um codificadores ao vivo. O evento ao vivo recebe streams de entrada a partir do codificadores ao vivo e os disponibiliza para streaming através de um ou mais pontos finais de streaming. Os eventos ao vivo também fornecem um ponto final de pré-visualização (URL de pré-visualização) que utiliza para visualizar e validar o seu fluxo antes de ser processado e entregue.

Este tutorial mostra como usar .NET 5.0 para criar um tipo de evento ao vivo. Neste tutorial, vai:

Nota

Mesmo que o tutorial utilize exemplos .NET SDK , os passos gerais são os mesmos para REST API, CLI ou outros SDKs suportados.

Pré-requisitos

Precisa dos seguintes itens para completar o tutorial:

Precisa destes itens adicionais para software de streaming em direto:

  • Uma câmara ou um dispositivo (como um portátil) que é usado para transmitir um evento.

  • Um codificadora de software no local que codifica o fluxo da sua câmara e envia-o para o serviço de streaming Serviços de Multimédia através do Real-Time Protocolo de Mensagens (RTMP). Para mais informações, consulte os codificadores recomendados no local. O fluxo tem de ser em formato RTMP ou de transmissão em fluxo uniforme.

    Esta amostra pressupõe que você usará o Open Broadcaster Software (OBS) Studio para transmitir RTMP para o ponto final de ingestão. Instale o estúdio OBS.

Dica

Reveja o streaming ao vivo com Serviços de Multimédia v3 antes de prosseguir.

Descarregue e configuure a amostra

Clone o repositório GitHub que contém a amostra de streaming em direto .NET para a sua máquina utilizando o seguinte comando:

git clone https://github.com/Azure-Samples/media-services-v3-dotnet.git

A amostra de transmissão em direto está na pasta Live .

Abra appsettings.json no seu projeto descarregado. Substitua os valores por credenciais que obteve ao aceder às APIs.

Nota

Também pode utilizar o formato de ficheiro .env na raiz do projeto para definir as variáveis ambientais apenas uma vez para todos os projetos no repositório de amostras .NET. Basta copiar o ficheiro sample.env e, em seguida, preencher as informações que obteve da página de acesso Serviços de Multimédia API no portal do Azure ou do Azure CLI. Mude o nome do ficheiro sample.env para apenas .env para usá-lo em todos os projetos.

O ficheiro .gitignore já está configurado para evitar a publicação deste ficheiro no seu repositório forcado.

Importante

Esta amostra utiliza um sufixo único para cada recurso. Se cancelar a depurar ou encerrar a aplicação sem a executar, acabará com vários eventos ao vivo na sua conta.

Certifique-se de parar os eventos ao vivo. Caso contrário, será cobrado!

Examinar o código que efetua a transmissão em fluxo em direto

Esta secção examina as funções definidas no ficheiro Autenticação.cs (na pasta Common_Utils) e no ficheiro .cs programa do projeto LiveEventWithDVR .

A amostra cria um sufixo único para cada recurso para que não tenha colisões de nomes se executar a amostra várias vezes sem limpar.

Comece a utilizar apis Serviços de Multimédia com o .NET SDK

Autenticação.cs cria um AzureMediaServicesClient objeto utilizando credenciais fornecidas nos ficheiros de configuração locais (appsettings.json ou .env).

Um AzureMediaServicesClient objeto permite-lhe começar a utilizar Serviços de Multimédia APIs com .NET. Para criar o objeto, é necessário fornecer credenciais para que o cliente se conecte ao Azure utilizando Azure Ative Directory, que é implementado em GetCredentialsAsync. Outra opção é utilizar a autenticação interativa, que é implementada em GetCredentialsInteractiveAuthAsync.

public static async Task<IAzureMediaServicesClient> CreateMediaServicesClientAsync(ConfigWrapper config, bool interactive = false)
{
    ServiceClientCredentials credentials;
    if (interactive)
        credentials = await GetCredentialsInteractiveAuthAsync(config);
    else
        credentials = await GetCredentialsAsync(config);

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

No código que clonou no início do artigo, a GetCredentialsAsync função cria o ServiceClientCredentials objeto com base nas credenciais fornecidas no ficheiro de configuração local (appsettings.json) ou através do ficheiro de variáveis ambientais .env na raiz do repositório.

private static async Task<ServiceClientCredentials> GetCredentialsAsync(ConfigWrapper config)
{
    // Use ConfidentialClientApplicationBuilder.AcquireTokenForClient to get a token using a service principal with symmetric key

    var scopes = new[] { config.ArmAadAudience + "/.default" };

    var app = ConfidentialClientApplicationBuilder.Create(config.AadClientId)
        .WithClientSecret(config.AadSecret)
        .WithAuthority(AzureCloudInstance.AzurePublic, config.AadTenantId)
        .Build();

    var authResult = await app.AcquireTokenForClient(scopes)
                                             .ExecuteAsync()
                                             .ConfigureAwait(false);

    return new TokenCredentials(authResult.AccessToken, TokenType);
}

No caso de autenticação interativa, a GetCredentialsInteractiveAuthAsync função cria o ServiceClientCredentials objeto com base numa autenticação interativa e nos parâmetros de ligação fornecidos no ficheiro de configuração local (appsettings.json) ou através do ficheiro de variáveis ambientais .env na raiz do repositório. Nesse caso, a AADCLIENTID e a AADSECRET não são necessárias no ficheiro de variáveis de configuração ou ambiente.

private static async Task<ServiceClientCredentials> GetCredentialsInteractiveAuthAsync(ConfigWrapper config)
{
    var scopes = new[] { config.ArmAadAudience + "/user_impersonation" };

    // client application of Az Cli
    string ClientApplicationId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46";

    AuthenticationResult result = null;

    IPublicClientApplication app = PublicClientApplicationBuilder.Create(ClientApplicationId)
        .WithAuthority(AzureCloudInstance.AzurePublic, config.AadTenantId)
        .WithRedirectUri("http://localhost")
        .Build();

    var accounts = await app.GetAccountsAsync();

    try
    {
        result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        try
        {
            result = await app.AcquireTokenInteractive(scopes).ExecuteAsync();
        }
        catch (MsalException maslException)
        {
            Console.Error.WriteLine($"ERROR: MSAL interactive authentication exception with code '{maslException.ErrorCode}' and message '{maslException.Message}'.");
        }
    }
    catch (MsalException maslException)
    {
        Console.Error.WriteLine($"ERROR: MSAL silent authentication exception with code '{maslException.ErrorCode}' and message '{maslException.Message}'.");
    }

    return new TokenCredentials(result.AccessToken, TokenType);
}

Criar um evento em direto

Esta secção mostra como criar um tipo de evento ao vivo (LiveEventEncodingType definido para None). Para obter informações sobre os tipos disponíveis, consulte os tipos de eventos Live. Além de passar, você pode usar um evento de transcoding ao vivo para codificação de nuvem bitrate adaptativa de 720p ou 1080p.

É melhor especificar as seguintes coisas quando estiver a criar o evento ao vivo:

  • O protocolo de ingestão para o evento ao vivo. Atualmente, os protocolos RTMP, RTMPS e Smooth Streaming são suportados. Não é possível alterar a opção de protocolo enquanto o evento ao vivo ou as suas saídas ao vivo associadas estiverem em execução. Se precisar de protocolos diferentes, crie um evento ao vivo separado para cada protocolo de streaming.

  • Restrições ip sobre a ingestão e pré-visualização. Pode definir os endereços IP que podem ingerir um vídeo para este evento ao vivo. Os endereços IP autorizados podem ser especificados como uma destas opções:

    • Um único endereço IP (por exemplo, 10.0.0.1)
    • Uma gama IP que utiliza um endereço IP e uma máscara de sub-rede de encaminhamento de Inter-Domain (CIDR) sem classe (por exemplo, 10.0.0.1/22)
    • Uma gama IP que usa um endereço IP e uma máscara de sub-rede decimal pontilhada (por exemplo, 10.0.0.1(255.255.252.0))

    Se não forem especificados endereços IP e não houver definição de regra, nenhum endereço IP será permitido. Para permitir qualquer endereço IP, crie uma regra e desaponhe 0.0.0.0/0. Os endereços IP devem estar num dos seguintes formatos: endereço IPv4 com quatro números ou uma gama de endereços CIDR.

  • Inicie automaticamente um evento à medida que o cria. Quando o arranque automático estiver programado para, o evento ao vivo começará após a truecriação. Isso significa que a faturação começa assim que o evento ao vivo começa a funcionar. Você deve explicitamente apelar Stop ao recurso do evento ao vivo para parar a faturação adicional. Para mais informações, consulte estados de eventos ao vivo e faturação.

    Os modos de espera estão disponíveis para iniciar o evento ao vivo num estado "atribuído" de baixo custo que torna mais rápido a mudança para um estado de funcionamento. Isto é útil para situações como piscinas quentes que precisam distribuir canais rapidamente para streamers.

  • Um nome de hospedeiro estático e um GUID único. Para que um URL inger seja preditivo e mais fácil de manter em um codificadora ao vivo baseado em hardware, coloque a useStaticHostname propriedade em true. Para obter informações detalhadas, consulte live event inger URLs.

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

// Creating the LiveEvent - the primary object for live streaming in AMS. 
// See the overview - https://docs.microsoft.com/azure/media-services/latest/live-streaming-overview

// Create the LiveEvent

// Understand the concepts of what a live event and a live output is in AMS first!
// Read the following - https://docs.microsoft.com/azure/media-services/latest/live-events-outputs-concept
// 1) Understand the billing implications for the various states
// 2) Understand the different live event types, pass-through and encoding
// 3) Understand how to use long-running async operations 
// 4) Understand the available Standby mode and how it differs from the Running Mode. 
// 5) Understand the differences between a LiveOutput and the Asset that it records to.  They are two different concepts.
//    A live output can be considered as the "tape recorder" and the Asset is the tape that is inserted into it for recording.
// 6) Understand the advanced options such as low latency, and live transcription/captioning support. 
//    Live Transcription - https://docs.microsoft.com/en-us/azure/media-services/latest/live-transcription
//    Low Latency - https://docs.microsoft.com/en-us/azure/media-services/latest/live-event-latency

// When broadcasting to a live event, please use one of the verified on-premises live streaming encoders.
// While operating this tutorial, it is recommended to start out using OBS Studio before moving to another encoder. 

// 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(
    name: "AllowAll",
    address: "0.0.0.0",
    subnetPrefixLength: 0
);

// Create the LiveEvent input IP access control object
// this will control the IP that the encoder is running on and restrict access to only that encoder IP range.
LiveEventInputAccessControl liveEventInputAccess = new()
{
    Ip = new IPAccessControl(
            allow: new IPRange[]
            {
                // re-use the same range here for the sample, but in production you can lock this
                // down to the ip range for your on-premises live encoder, laptop, or device that is sending
                // the live stream
                allAllowIPRange
            }
        )

};

// Create the LiveEvent Preview IP access control object. 
// This will restrict which clients can view the preview endpoint
LiveEventPreview liveEventPreview = new()
{
    AccessControl = new LiveEventPreviewAccessControl(
        ip: new IPAccessControl(
            allow: new IPRange[]
            {
                 // re-use the same range here for the sample, but in production you can lock this to the IPs of your 
                // devices that would be monitoring the live preview. 
                allAllowIPRange
            }
        )
    )
};

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

// See REST API documentation for details on each setting value
// https://docs.microsoft.com/rest/api/media/liveevents/create 

LiveEvent liveEvent = new(
    location: mediaService.Location,
    description: "Sample LiveEvent from .NET SDK sample",
    // Set useStaticHostname to true to make the ingest and preview URL host name the same. 
    // This can slow things down a bit. 
    useStaticHostname: true,

    // 1) Set up the input settings for the Live event...
    input: new LiveEventInput(
        streamingProtocol: LiveEventInputProtocol.RTMP,  // options are RTMP or Smooth Streaming ingest format.
                                                         // This sets a static access token for use on the ingest path. 
                                                         // Combining this with useStaticHostname:true will give you the same ingest URL on every creation.
                                                         // This is helpful when you only want to enter the URL into a single encoder one time for this Live Event name
        accessToken: "acf7b6ef-8a37-425f-b8fc-51c2d6a5a86a",  // Use this value when you want to make sure the ingest URL is static and always the same. If omitted, the service will generate a random GUID value.
        accessControl: liveEventInputAccess, // controls the IP restriction for the source encoder.
        keyFrameIntervalDuration: "PT2S" // Set this to match the ingest encoder's settings
    ),
    // 2) Set the live event to use pass-through or cloud encoding modes...
    encoding: new LiveEventEncoding(
        // Set this to Standard (720P) or Premium1080P to use the cloud live encoder.
        // See https://go.microsoft.com/fwlink/?linkid=2095101 for more information
        // Otherwise, set to PassthroughBasic or PassthroughStandard to use the two different pass-through modes. 
        encodingType: LiveEventEncodingType.PassthroughStandard // Choose the type of live event - standard or basic pass-through, or the encoding types for 720P or 1080P
                                                                // OPTIONAL settings when using live cloud encoding type:
                                                                // keyFrameInterval: "PT2S", //If this value is not set for an encoding live event, the fragment duration defaults to 2 seconds. The value cannot be set for pass-through live events.
                                                                // presetName: null, // only used for custom defined presets. 
                                                                //stretchMode: "None" // can be used to determine stretch on encoder mode
    ),
    // 3) Set up the Preview endpoint for monitoring based on the settings above we already set.
    preview: liveEventPreview,
    // 4) Set up more advanced options on the live event. Low Latency is the most common one.
    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
    }
//,
// 5) Optionally enable live transcriptions if desired. This is only supported on PassthroughStandard, and the transcoding live event types. It is not supported on Basic pass-through type.
// WARNING : This is extra cost ($$$), so please check pricing before enabling.
/*transcriptions:new List<LiveEventTranscription>(){
    new LiveEventTranscription(
        // The value should be in BCP-47 format (e.g: 'en-US'). See https://go.microsoft.com/fwlink/?linkid=2133742
        language: "en-us",
        outputTranscriptionTrack : new LiveEventOutputTranscriptionTrack(
            trackName: "English" // set the name you want to appear in the output manifest
        )
    )
}*/
);

// Start monitoring LiveEvent events using Event Grid and Event Hub
try
{
    // 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);

    mediaEventProcessor = new MediaServicesEventProcessor(null, null, liveEventName);
    processorClient.ProcessEventAsync += mediaEventProcessor.ProcessEventsAsync;
    processorClient.ProcessErrorAsync += mediaEventProcessor.ProcessErrorAsync;

    await processorClient.StartProcessingAsync();
}
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);
}

Console.WriteLine("Creating the LiveEvent, please be patient as this can take time to complete async.");
Console.WriteLine("Live Event creation is an async operation in Azure and timing can depend on resources available.");

// 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.
// On optional workflow is to first call allocate() instead of create. 
// https://docs.microsoft.com/en-us/rest/api/media/liveevents/allocate 
// This allows you to allocate the resources and place the live event into a "Standby" mode until 
// you are ready to transition to "Running". This is useful when you want to pool resources in a warm "Standby" state at a reduced cost.
// The transition from Standby to "Running" is much faster than cold creation to "Running" using the autostart property.
// Returns a long running operation polling object that can be used to poll until completion.

Stopwatch watch = Stopwatch.StartNew();
liveEvent = await client.LiveEvents.CreateAsync(
    config.ResourceGroup,
    config.AccountName,
    liveEventName,
    liveEvent,
    // When autostart is set to true, you should "await" this method operation to complete. 
    // The Live Event will be started after creation. 
    // You may choose not to do this, but create the object, and then start it using the standby state to 
    // keep the resources "warm" and billing at a lower cost until you are ready to go live. 
    // That increases the speed of startup when you are ready to go live. 
    autoStart: false);
watch.Stop();
string elapsedTime = String.Format(":{0:00}.{1:00}", watch.Elapsed.Seconds, watch.Elapsed.Milliseconds / 10);
Console.WriteLine($"Create Live Event run time : {elapsedTime}");

Obter URLs de inserção

Após a criação do Live Event, poderá obter URLs ingeridos que irá fornecer ao codificadores ao vivo. O codificador utiliza estes URLs para exibir uma transmissão um fluxo direto.

// Get the RTMP ingest URL to configure in OBS Studio. 
// The endpoints is a collection of RTMP primary and secondary, and RTMPS primary and secondary URLs. 
// to get the primary secure RTMPS, it is usually going to be index 3, but you could add a loop here to confirm...
string ingestUrl = liveEvent.Input.Endpoints.First().Url;
Console.WriteLine($"The RTMP ingest URL to enter into OBS Studio is:");
Console.WriteLine($"\t{ingestUrl}");
Console.WriteLine("Make sure to enter a Stream Key into the OBS studio settings. It can be any value or you can repeat the accessToken used in the ingest URL path.");
Console.WriteLine();

Obter o URL de pré-visualização

Utilize previewEndpoint para pré-visualizar e verificar se a entrada do codificante está a ser recebida.

Importante

Certifique-se de que o vídeo está a fluir para o URL de pré-visualização antes de continuar.

// Use the previewEndpoint to preview and verify
// that the input from the encoder is actually being received
// The preview endpoint URL also support the addition of various format strings for HLS (format=m3u8-cmaf) and DASH (format=mpd-time-cmaf) for example.
// The default manifest is Smooth. 
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();

Criar e gerir eventos ao vivo e saídas ao vivo

Depois de ter o stream fluindo para o evento ao vivo, você pode começar o evento de streaming criando um ativo, saída ao vivo e localizador de streaming. Isto irá arquivar o fluxo e disponibilizá-lo aos espectadores através do ponto final de streaming.

Quando se aprende estes conceitos, é útil pensar no objeto do ativo como a fita que se insere num gravador de vídeo nos velhos tempos. A saída ao vivo é a máquina de gravadores. O evento ao vivo é apenas o sinal de vídeo que entra na parte de trás da máquina.

Primeiro cria-se o sinal criando o evento ao vivo. O sinal não flui até iniciar o evento ao vivo e ligar o codificante à entrada.

A "fita" pode ser criada a qualquer momento. É apenas um ativo vazio que vai entregar ao objeto de saída ao vivo, o "gravador" nesta analogia.

O "gravador" também pode ser criado a qualquer momento. Pode criar uma saída viva antes de iniciar o fluxo de sinal, ou depois. Se precisar de acelerar as coisas, às vezes é útil criar a saída antes de iniciar o fluxo de sinal.

Para parar o "gravador", ligue deleteLiveOutput. Esta ação não apaga o conteúdo da "fita" (ativo). O ativo é sempre mantido com o conteúdo de vídeo arquivado até que ligue delete explicitamente sobre o próprio ativo.

A próxima secção caminhará pela criação do ativo e pela produção ao vivo.

Criar um recurso

Criar um ativo para a saída ao vivo usar. Na nossa analogia, esta será a "fita" em que gravamos o sinal de vídeo ao vivo. Os espectadores poderão ver o conteúdo ao vivo ou a pedido desta fita virtual.

// Create an Asset for the LiveOutput to use. Think of this as the "tape" that will be recorded to. 
// The asset entity points to a folder/container in your Azure Storage account. 
Console.WriteLine($"Creating an asset named {assetName}");
Console.WriteLine();
Asset asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName, assetName, new Asset());

Criar uma saída ao vivo

As saídas ao vivo começam quando são criadas e param quando são apagadas. Quando elimina a saída ao vivo, não está a excluir o ativo ou conteúdo subjacente no ativo. Pense nisso como ejetar a "fita". O ativo com a gravação durará o tempo que quiser. Quando for ejetada (ou seja, quando a saída ao vivo for eliminada), estará disponível para visualização a pedido imediatamente.

// Create the Live Output - think of this as the "tape recorder for the live event". 
// Live outputs are optional, but are required if you want to archive the event to storage,
// use the asset for on-demand playback later, or if you want to enable cloud DVR time-shifting.
// We will use the asset created above for the "tape" to record to. 
string manifestName = "output";
Console.WriteLine($"Creating a live output named {liveOutputName}");
Console.WriteLine();

watch = Stopwatch.StartNew();
// See the REST API for details on each of the settings on Live Output
// https://docs.microsoft.com/rest/api/media/liveoutputs/create
LiveOutput liveOutput = new(
    assetName: asset.Name,
    manifestName: manifestName, // The HLS and DASH manifest file name. This is recommended to set if you want a deterministic manifest path up front.
                                // archive window 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.
    archiveWindowLength: TimeSpan.FromHours(1)
);
liveOutput = await client.LiveOutputs.CreateAsync(
    config.ResourceGroup,
    config.AccountName,
    liveEventName,
    liveOutputName,
    liveOutput);
elapsedTime = String.Format(":{0:00}.{1:00}", watch.Elapsed.Seconds, watch.Elapsed.Milliseconds / 10);
Console.WriteLine($"Create Live Output run time : {elapsedTime}");
Console.WriteLine();

Criar um localizador de transmissão

Nota

Quando a sua conta Serviços de Multimédia é criada, um ponto final de streaming padrão é adicionado à sua conta no estado parado. Para começar a transmitir o seu conteúdo e aproveitar a embalagem dinâmica e a encriptação dinâmica, o ponto final de streaming a partir do qual pretende transmitir conteúdo tem de estar no estado de execução.

Quando publicar o ativo utilizando um localizador de streaming, o evento ao vivo (até ao comprimento da janela do DVR) continuará a ser visível até à expiração ou supressão do localizador de streaming, o que vier primeiro. É assim que disponibiliza a gravação virtual de "fita" para o seu público ver ao vivo e a pedido. O mesmo URL pode ser usado para assistir ao evento ao vivo, à janela DVR ou ao ativo on-demand quando a gravação estiver completa (quando a saída ao vivo é eliminada).

Console.WriteLine($"Creating a streaming locator named {streamingLocatorName}");
Console.WriteLine();

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

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

    // Since we started the endpoint, we should stop it in cleanup.
    stopEndpoint = true;
}

// Get the URL to stream the output
ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName);

foreach (StreamingPath path in paths.StreamingPaths)
{
    UriBuilder uriBuilder = new UriBuilder();
    uriBuilder.Scheme = "https";
    uriBuilder.Host = streamingEndpoint.HostName;

    uriBuilder.Path = path.Paths[0];
    // Get the URL from the uriBuilder: uriBuilder.ToString()
}

Limpar os recursos na conta dos Serviços de Multimédia

Se já terminou os eventos de streaming e quer limpar os recursos a provisionados anteriormente, utilize o seguinte procedimento:

  1. Termine o envio da transmissão em fluxo do codificador.
  2. Pare o evento ao vivo. Depois que o evento ao vivo for interrompido, não vai incorrer em nenhuma acusação. Quando quiser reiniciar a transmissão, esta terá o mesmo URL de inserção, desta forma, não terá de reconfigurar o codificador.
  3. Pare o seu ponto final de streaming, a menos que queira continuar a fornecer o arquivo do seu evento ao vivo como um fluxo on-demand. Se o evento ao vivo estiver num estado parado, não incorrerá em nenhuma acusação.
private static async Task CleanupLiveEventAndOutputAsync(IAzureMediaServicesClient client, string resourceGroup, string accountName, string liveEventName, string liveOutputName)
{
    try
    {
        LiveEvent liveEvent = await client.LiveEvents.GetAsync(resourceGroup, accountName, liveEventName);

        Console.WriteLine("Deleting Live Output");
        Stopwatch watch = Stopwatch.StartNew();

        await client.LiveOutputs.DeleteAsync(resourceGroup, accountName, liveEventName, liveOutputName);

        String elapsedTime = String.Format(":{0:00}.{1:00}", watch.Elapsed.Seconds, watch.Elapsed.Milliseconds / 10);
        Console.WriteLine($"Delete Live Output run time : {elapsedTime}");

        if (liveEvent != null)
        {
            if (liveEvent.ResourceState == LiveEventResourceState.Running)
            {
                watch = Stopwatch.StartNew();
                // If the LiveEvent is running, stop it and have it remove any LiveOutputs
                await client.LiveEvents.StopAsync(resourceGroup, accountName, liveEventName, removeOutputsOnStop: false);
                elapsedTime = String.Format(":{0:00}.{1:00}", watch.Elapsed.Seconds, watch.Elapsed.Milliseconds / 10);
                Console.WriteLine($"Stop Live Event run time : {elapsedTime}");
            }

            // Delete the LiveEvent
            await client.LiveEvents.DeleteAsync(resourceGroup, accountName, liveEventName);
        }
    }
    catch (ErrorResponseException e)
    {
        Console.WriteLine("CleanupLiveEventAndOutputAsync -- Hit ErrorResponseException");
        Console.WriteLine($"\tCode: {e.Body.Error.Code}");
        Console.WriteLine($"\tCode: {e.Body.Error.Message}");
        Console.WriteLine();
    }
}
private static async Task CleanupLocatorandAssetAsync(IAzureMediaServicesClient client, string resourceGroup, string accountName, string streamingLocatorName, string assetName)
{
    try
    {
        // Delete the Streaming Locator
        await client.StreamingLocators.DeleteAsync(resourceGroup, accountName, streamingLocatorName);

        // Delete the Archive Asset
        await client.Assets.DeleteAsync(resourceGroup, accountName, assetName);
    }
    catch (ErrorResponseException e)
    {
        Console.WriteLine("CleanupLocatorandAssetAsync -- Hit ErrorResponseException");
        Console.WriteLine($"\tCode: {e.Body.Error.Code}");
        Console.WriteLine($"\tCode: {e.Body.Error.Message}");
        Console.WriteLine();
    }
}

Ver o evento

Prima Ctrl+F5 para executar o código. Isto irá transmitir URLs de streaming que você pode usar para assistir ao seu evento ao vivo. Copie o URL de streaming que tem de criar um localizador de streaming. Podes usar um media player à tua escolha. A Azure Leitor multimédia está disponível para testar o seu fluxo no site de demonstração de Leitor multimédia.

Um evento ao vivo converte automaticamente eventos em conteúdo sonoro quando é parado. Mesmo depois de parar e apagar o evento, os utilizadores podem transmitir o seu conteúdo arquivado como um vídeo a pedido enquanto não eliminar o ativo. Um ativo não pode ser eliminado se um evento estiver a usá-lo; o evento deve ser apagado primeiro.

Limpar os recursos restantes

Se já não precisar de nenhum dos recursos do seu grupo de recursos, incluindo as contas de Serviços de Multimédia e armazenamento que criou para este tutorial, elimine o grupo de recursos que criou anteriormente.

Executar o seguinte comando CLI:

az group delete --name amsResourceGroup

Importante

Deixar o evento ao vivo a funcionar incorre nos custos de faturação. Esteja ciente de que se o projeto ou programa parar de responder ou estiver fechado por qualquer motivo, poderá deixar o evento ao vivo em funcionamento em estado de faturação.