Criar, programar e gerenciar pausas de mídia

Este artigo mostra como criar, programar e gerenciar pausas de mídia para seu aplicativo de reprodução de mídia. Quebras de mídia geralmente são usadas para inserir anúncios de áudio ou vídeos no conteúdo de mídia. A partir do Windows 10, versão 1607, você pode usar a classe MediaBreakManager de forma rápida e fácil para adicionar quebras de mídia a qualquer MediaPlaybackItem que você usar com um MediaPlayer.

Depois de programar uma ou mais interrupções de mídia, o sistema reproduzirá automaticamente seu conteúdo de mídia no horário especificado durante a reprodução. O MediaBreakManager fornece eventos para que seu aplicativo possa reagir quando as pausas de mídia começarem, terminarem ou quando forem ignoradas pelo usuário. Você também pode acessar uma MediaPlaybackSession para que suas pausas de mídia monitorem eventos, como download e atualizações do andamento de buffer.

Programar pausas de mídia

Cada objeto MediaPlaybackItem tem sua própria MediaBreakSchedule que você usa para configurar as pausas de mídia que serão executadas quando o item for reproduzido. A primeira etapa para usar pausas de mídia em seu aplicativo é criar um MediaPlaybackItem para o conteúdo de reprodução principal.

MediaPlaybackItem moviePlaybackItem =
    new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("http://www.fabrikam.com/movie.mkv")));

Para obter mais informações sobre como trabalhar com MediaPlaybackItem, MediaPlaybackList e outras APIs de reprodução de mídia fundamentais, consulte Itens de mídia, playlists e faixas.

O próximo exemplo mostra como adicionar uma pausa de pré-rolagem ao MediaPlaybackItem, o que significa que o sistema reproduzirá a pausa de mídia antes de executar o item de reprodução ao qual pertence a pausa. Primeiro, um novo objeto MediaBreak é instanciado. Neste exemplo, o construtor é chamado com MediaBreakInsertionMethod.Interrupt, o que significa que o conteúdo principal será pausado enquanto o conteúdo da pausa for executado.

Em seguida, um novo MediaPlaybackItem é criado para o conteúdo que será executado durante a pausa, como um anúncio. A propriedade CanSkip desse item de reprodução é definida como false. Isso significa que o usuário não poderá ignorar o item usando os controles de mídia integrada. Seu aplicativo ainda pode optar por ignorar a adição programaticamente chamando SkipCurrentBreak.

A propriedade PlaybackList da pausa de mídia é uma MediaPlaybackList que permite reproduzir vários itens de mídia como uma playlist. Adicione um ou mais objetos MediaPlaybackItem da coleção de itens da lista para incluí-los na playlist da pausa de mídia.

Por fim, programe a pausa de mídia usando a propriedade BreakSchedule do item de reprodução de conteúdo principal. Especifique a pausa como uma pausa de pré-rolagem atribuindo-a à propriedade PrerollBreak do objeto da programação.

MediaBreak preRollMediaBreak = new MediaBreak(MediaBreakInsertionMethod.Interrupt);
MediaPlaybackItem prerollAd = 
    new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("http://www.fabrikam.com/preroll_ad.mp4")));
prerollAd.CanSkip = false;
preRollMediaBreak.PlaybackList.Items.Add(prerollAd);

moviePlaybackItem.BreakSchedule.PrerollBreak = preRollMediaBreak;

Agora você pode reproduzir o item de mídia principal, e a pausa de mídia que você criou será reproduzida antes do conteúdo principal. Crie um novo objeto MediaPlayer e, opcionalmente, defina a propriedade AutoPlay como true para iniciar a reprodução automaticamente. Defina a propriedade Source do MediaPlayer como seu item de reprodução de conteúdo principal. Não é obrigatório, mas você pode atribuir o MediaPlayer a um MediaPlayerElement para renderizar a mídia em uma página XAML. Para obter mais informações sobre como usar MediaPlayer, consulte Reproduzir áudio e vídeo com MediaPlayer.

_mediaPlayer = new MediaPlayer();
_mediaPlayer.AutoPlay = true;
_mediaPlayer.Source = moviePlaybackItem;
mediaPlayerElement.SetMediaPlayer(_mediaPlayer);

Adicione uma pausa de pós-rolagem que será reproduzida após o término da reprodução do MediaPlaybackItem que apresenta o conteúdo principal, usando a mesma técnica que uma pausa de pré-rolagem, exceto que o objeto MediaBreak é atribuído à propriedade PostrollBreak.

MediaBreak postrollMediaBreak = new MediaBreak(MediaBreakInsertionMethod.Interrupt);
MediaPlaybackItem postRollAd =
    new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("http://www.fabrikam.com/postroll_ad.mp4")));
postrollMediaBreak.PlaybackList.Items.Add(postRollAd);

moviePlaybackItem.BreakSchedule.PostrollBreak = postrollMediaBreak;

Você também pode programar uma ou mais pausas de meio de rolagem que são executadas em um horário especificado na reprodução do conteúdo principal. No exemplo a seguir, a MediaBreak é criada com a sobrecarga do construtor que aceita um objeto TimeSpan, o que especifica o horário na reprodução do item de mídia principal quando a pausa será reproduzida. Novamente, MediaBreakInsertionMethod.Interrupt é especificado para indicar que a reprodução do conteúdo principal será pausada durante a reprodução da pausa. A pausa de meio de rolagem é adicionada à programação chamando InsertMidrollBreak. Você pode obter uma lista de somente leitura das pausas de meio de rolagem atuais na programação acessando a propriedade MidrollBreaks.

MediaBreak midrollMediaBreak = new MediaBreak(MediaBreakInsertionMethod.Interrupt, TimeSpan.FromMinutes(10));
midrollMediaBreak.PlaybackList.Items.Add(
    new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("http://www.fabrikam.com/midroll_ad_1.mp4"))));
midrollMediaBreak.PlaybackList.Items.Add(
    new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("http://www.fabrikam.com/midroll_ad_2.mp4"))));
moviePlaybackItem.BreakSchedule.InsertMidrollBreak(midrollMediaBreak);

O próximo exemplo de pausa de meio de rolagem mostrado usa o método de inserção MediaBreakInsertionMethod.Replace, o que significa que o sistema continuará a processar o conteúdo principal durante a reprodução da pausa. Essa opção é normalmente usada por aplicativos de mídia de streaming ao vivo, quando você não deseja que o conteúdo seja pausado e fique atrás do fluxo ao vivo enquanto o anúncio é reproduzido.

Este exemplo também utiliza uma sobrecarga do construtor MediaPlaybackItem que aceita dois parâmetros TimeSpan. O primeiro parâmetro especifica o ponto de partida no item de pausa de mídia em que a reprodução será iniciada. O segundo parâmetro especifica a duração em que a pausa de mídia será reproduzida. Portanto, no exemplo a seguir, a MediaBreak começará aos 20 minutos do conteúdo principal. Durante sua reprodução, o item de mídia começará 30 segundos após o início do item de pausa de mídia e será reproduzido por 15 segundos antes de o conteúdo de mídia principal retomar a reprodução.

midrollMediaBreak = new MediaBreak(MediaBreakInsertionMethod.Replace, TimeSpan.FromMinutes(20));
MediaPlaybackItem ad = 
    new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("http://www.fabrikam.com/midroll_ad_3.mp4")),
    TimeSpan.FromSeconds(30),
    TimeSpan.FromSeconds(15));
ad.CanSkip = false;
midrollMediaBreak.PlaybackList.Items.Add(ad);

Ignorar pausas de mídia

Como mencionado anteriormente neste artigo, a propriedade CanSkip de um MediaPlaybackItem podem ser definido para impedir que o usuário ignore o conteúdo com os controles internos. No entanto, você pode chamar SkipCurrentBreak do seu código a qualquer momento para ignorar a pausa atual.

private void SkipButton_Click(object sender, RoutedEventArgs e) => _mediaPlayer.BreakManager.SkipCurrentBreak();

Tratar eventos de MediaBreak

Há vários eventos relacionados a pausas de mídia que você pode assinar para agir com base na alteração das estado das pausas.

_mediaPlayer.BreakManager.BreakStarted += BreakManager_BreakStarted;
_mediaPlayer.BreakManager.BreakEnded += BreakManager_BreakEnded;
_mediaPlayer.BreakManager.BreakSkipped += BreakManager_BreakSkipped;
_mediaPlayer.BreakManager.BreaksSeekedOver += BreakManager_BreaksSeekedOver;

O BreakStarted é acionado quando uma pausa de mídia é iniciada. É possível atualizar sua interface do usuário para informar o usuário que o conteúdo de pausa de mídia será reproduzido. Este exemplo usa o MediaBreakStartedEventArgs transmitido para o manipulador para obter uma referência da pausa de mídia iniciada. A propriedade CurrentItemIndex é usada para determinar qual item de mídia na playlist da pausa está sendo reproduzido. Em seguida, a interface do usuário é atualizada para mostrar ao usuário o índice de anúncios atual e o número de anúncios restantes na pausa. Lembre-se de que as atualizações da interface do usuário devem ser feitas no thread da interface do usuário, portanto, a chamada deve ser feita dentro de uma chamada para RunAsync.

private async void BreakManager_BreakStarted(MediaBreakManager sender, MediaBreakStartedEventArgs args)
{
    MediaBreak currentBreak = sender.CurrentBreak;
    var currentIndex = currentBreak.PlaybackList.CurrentItemIndex;
    var itemCount = currentBreak.PlaybackList.Items.Count;

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>            
        statusTextBlock.Text = $"Playing ad {currentIndex + 1} of {itemCount}");
}

BreakEnded é acionado quando a reprodução de todos os itens da mídia na pausa termina ou eles são ignorados. Você pode usar o manipulador desse evento para atualizar a interface do usuário a fim de indicar que o conteúdo da quebra de mídia não está mais sendo reproduzido.

private async void BreakManager_BreakEnded(MediaBreakManager sender, MediaBreakEndedEventArgs args)
{
    // Update UI to show that the MediaBreak is no longer playing
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => statusTextBlock.Text = "");

    args.MediaBreak.CanStart = false;
}

O evento BreakSkipped é acionado quando o usuário pressiona o botão Avançar na interface do usuário interna durante a reprodução de um item para o qual CanSkip é true, ou quando você ignora uma pausa em seu código chamando SkipCurrentBreak.

O exemplo a seguir usa a propriedade Source do MediaPlayer para obter uma referência do item de mídia para o conteúdo principal. A pausa de mídia ignorada pertence à programação de pausa desse item. Em seguida, o código verifica se a pausa de mídia que foi ignorada é a mesma que a pausa de mídia definida como a propriedade PrerollBreak da programação. Em caso afirmativo, isso significa que a pausa de pré-rolagem foi a pausa ignorada e, nesse caso, uma nova pausa de meio de rolagem é criada e programada para ser reproduzida 10 minutos no conteúdo principal.

private async void BreakManager_BreakSkipped(MediaBreakManager sender, MediaBreakSkippedEventArgs args)
{
    // Update UI to show that the MediaBreak is no longer playing
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => statusTextBlock.Text = "");

    MediaPlaybackItem currentItem = _mediaPlayer.Source as MediaPlaybackItem;
    if(!(currentItem.BreakSchedule.PrerollBreak is  null) 
        && currentItem.BreakSchedule.PrerollBreak == args.MediaBreak)
    {
        MediaBreak mediaBreak = new MediaBreak(MediaBreakInsertionMethod.Interrupt, TimeSpan.FromMinutes(10));
        mediaBreak.PlaybackList.Items.Add(await GetAdPlaybackItem());
        currentItem.BreakSchedule.InsertMidrollBreak(mediaBreak);
    }
}

BreaksSeekedOver é acionado quando a posição de reprodução do item de mídia principal ultrapassa o tempo programado para uma ou mais pausas de mídia. O exemplo a seguir verifica se mais de uma pausa de mídia foi buscada, se a posição de reprodução foi avançada e se ela foi avançada menos de 10 minutos. Se sim, a primeira pausa buscada, obtida da coleção SeekedOverBreaks exposta pelos argumentos do evento será executada imediatamente com uma chamada para o método PlayBreak do MediaPlayer.BreakManager.

private void BreakManager_BreaksSeekedOver(MediaBreakManager sender, MediaBreakSeekedOverEventArgs args)
{
    if(args.SeekedOverBreaks.Count > 1
        && args.NewPosition.TotalMinutes > args.OldPosition.TotalMinutes
        && args.NewPosition.TotalMinutes - args.OldPosition.TotalMinutes < 10.0)
        _mediaPlayer.BreakManager.PlayBreak(args.SeekedOverBreaks[0]);
}

Acessar a sessão de reprodução atual

O objeto MediaPlaybackSession usa a classe MediaPlayer para fornecer dados e eventos relacionados ao conteúdo de mídia que está em execução no momento. O MediaBreakManager também tem uma MediaPlaybackSession que você pode acessar para obter dados e eventos especificamente relacionados ao conteúdo da pausa de mídia que está em reprodução. As informações que você pode obter da sessão de reprodução incluem o estado atual da reprodução, em reprodução ou pausado, e a posição de reprodução atual no conteúdo. Você pode usar as propriedades NaturalVideoWidth e NaturalVideoHeight e o NaturalVideoSizeChanged para ajustar sua interface do usuário de vídeo se o conteúdo da pausa de mídia tiver uma taxa de proporção diferente de seu conteúdo principal. Você também pode receber eventos como BufferingStarted, BufferingEnded e DownloadProgressChanged que podem fornecer dados de telemetria valiosos sobre o desempenho do seu aplicativo.

O exemplo a seguir registra um manipulador para o evento BufferingProgressChanged; no manipulador de eventos, ele atualiza a interface do usuário para mostrar o andamento atual do buffer.

_mediaPlayer.BreakManager.PlaybackSession.BufferingProgressChanged += PlaybackSession_BufferingProgressChanged;
private async void PlaybackSession_BufferingProgressChanged(MediaPlaybackSession sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        bufferingProgressBar.Value = sender.BufferingProgress);
}