Condividi tramite


Creare, pianificare e gestire le interruzioni di elementi multimediali

Questo articolo illustra come creare, pianificare e gestire interruzioni multimediali per l'app di riproduzione multimediale. Le interruzioni multimediali vengono in genere usate per inserire annunci audio o video in contenuti multimediali. A partire da Windows 10, versione 1607, si può usare usare la classe MediaBreakManager per aggiungere rapidamente e facilmente interruzioni multimediali a qualsiasi MediaPlaybackItem che si riproduce con un MediaPlayer.

Dopo aver pianificato una o più interruzioni multimediali, il sistema riprodurrà automaticamente il contenuto multimediale al momento specificato durante la riproduzione. MediaBreakManager fornisce eventi in modo che l'app possa reagire quando le interruzioni multimediali iniziano, terminano o quando vengono ignorate dall'utente. È anche possibile accedere a una MediaPlaybackSession per le interruzioni multimediali per monitorare gli eventi, ad esempio gli aggiornamenti dello stato di download e buffering.

Pianificare interruzioni multimediali

Ogni oggetto MediaPlaybackItem ha una propria MediaBreakSchedule usata per configurare le interruzioni multimediali che verranno riprodotte quando viene riprodotto l'elemento. Il primo passaggio per l'uso di interruzioni multimediali nell'app consiste nel creare un oggetto MediaPlaybackItem per il contenuto di riproduzione principale.

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

Per maggiori informazioni sull'uso di MediaPlaybackItem, MediaPlaybackList e altre API di riproduzione multimediale fondamentali, vedere Elementi multimediali, playlist e tracce.

Nell'esempio seguente viene illustrato come aggiungere un'interruzione di preroll a MediaPlaybackItem, il che significa che il sistema eseguirà l'interruzione multimediale prima di riprodurre l'elemento di riproduzione a cui appartiene l'interruzione. Viene creata un'istanza di un nuovo oggetto MediaBreak. In questo esempio il costruttore viene chiamato con MediaBreakInsertionMethod.Interrupt, ovvero il contenuto principale verrà sospeso mentre viene riprodotto il contenuto dell'interruzione.

Viene quindi creato un nuovo oggetto MediaPlaybackItem per il contenuto che verrà riprodotto durante l'interruzione, ad esempio un annuncio. La proprietà CanSkip di questo elemento di riproduzione è impostata su false. Ciò significa che l'utente non sarà in grado di ignorare l'elemento usando i controlli multimediali predefiniti. L'app può comunque scegliere di ignorare l'aggiunta a livello di codice chiamando SkipCurrentBreak.

La proprietà PlaybackList dell'interruzione è una MediaPlaybackList che consente di riprodurre più elementi multimediali come playlist. Aggiungere uno o più oggetti MediaPlaybackItem dall'insieme Items dell'elenco per includerli nella playlist dell'interruzione multimediale.

Infine, pianificare l'interruzione multimediale usando la proprietà BreakSchedule dell'elemento di riproduzione del contenuto principale. Specificare l'interruzione come interruzione di preroll assegnandola alla proprietà PrerollBreak dell'oggetto pianificazione.

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;

È ora possibile riprodurre l'elemento multimediale principale e l'interruzione multimediale creata verrà riprodotta prima del contenuto principale. Creare un nuovo oggetto MediaPlayer e, facoltativamente, impostare la proprietà AutoPlay su true per avviare automaticamente la riproduzione. Impostare la proprietà Source di MediaPlayer sull'elemento di riproduzione del contenuto principale. Non è obbligatorio, ma si può assegnare MediaPlayer a un MediaPlayerElement per eseguire il rendering dei supporti in una pagina XAML. Per altre informazioni sull'uso di MediaPlayer, vedere Riprodurre audio e video con MediaPlayer.

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

Aggiungere un'interruzione postroll che viene riprodotta al termine della riproduzione dell'oggetto MediaPlaybackItem contenente il contenuto principale, usando la stessa tecnica di un'interruzione di preroll, ad eccezione del fatto che si assegna l'oggetto MediaBreak alla proprietà 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;

Si può anche pianificare una o più interruzioni midroll che vengono riprodotte in un determinato momento all'interno della riproduzione del contenuto principale. Nell'esempio seguente viene creato MediaBreak con l'overload del costruttore che accetta un oggetto TimeSpan che specifica l'ora nella riproduzione dell'elemento multimediale principale quando verrà riprodotta l'interruzione. Anche in questo caso, MediaBreakInsertionMethod.Interrupt viene specificato per indicare che la riproduzione del contenuto principale verrà sospesa durante la riproduzione dell'interruzione. L'interruzione midroll viene aggiunta alla pianificazione chiamando InsertMidrollBreak. È possibile ottenere un elenco di sola lettura delle interruzioni di midroll correnti nella pianificazione accedendo alla proprietà 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);

L'esempio di interruzione midroll successivo illustrato usa il metodo di inserimento MediaBreakInsertionMethod.Replace, il che significa che il sistema continuerà a elaborare il contenuto principale durante la riproduzione dell'interruzione. Questa opzione viene in genere usata dalle app multimediali di streaming live in cui non vuoi che il contenuto venga sospeso e si trovi dietro il flusso live mentre viene riprodotto l'annuncio.

In questo esempio viene inoltre utilizzato un overload del costruttore MediaPlaybackItem che accetta due parametri TimeSpan. Il primo parametro specifica il punto iniziale all'interno dell'elemento di interruzione multimediale in cui inizierà la riproduzione. Il secondo parametro specifica la durata per cui verrà riprodotto l'elemento di interruzione multimediale. Quindi, nell'esempio seguente, MediaBreak inizierà a riprodurre a 20 minuti nel contenuto principale. Quando viene riprodotto, l'elemento multimediale inizierà 30 secondi dall'inizio dell'elemento multimediale di interruzione e verrà riprodotto per 15 secondi prima che il contenuto multimediale principale riprende la riproduzione.

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

Ignora interruzioni multimediali

Come accennato in precedenza in questo articolo, è possibile impostare la proprietà CanSkip di un MediaPlaybackItem per impedire all'utente di ignorare il contenuto con i controlli predefiniti. Tuttavia, è possibile chiamare SkipCurrentBreak dal codice in qualsiasi momento per ignorare l'interruzione corrente.

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

Gestire gli eventi MediaBreak

Esistono diversi eventi correlati alle interruzioni multimediali che è possibile registrare per per poter intervenire in base alla modifica dello stato delle interruzioni multimediali.

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

BreakStarted viene generato all'avvio di un'interruzione multimediale. È possibile aggiornare l'interfaccia utente per informare l'utente che il contenuto dell'interruzione multimediale è in riproduzione. In questo esempio vengono usati MediaBreakStartedEventArgs passati al gestore per ottenere un riferimento all'interruzione multimediale avviata. Viene quindi utilizzata la proprietà CurrentItemIndex per determinare quale elemento multimediale nella playlist dell'interruzione multimediale viene riprodotto. L'interfaccia utente viene quindi aggiornata per mostrare all'utente l'indice dell'annuncio corrente e il numero di annunci rimanenti nell'interruzione. Tenere presente che gli aggiornamenti all'interfaccia utente devono essere eseguiti nel thread dell'interfaccia utente, quindi la chiamata deve essere effettuata all'interno di una chiamata a 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 viene generato quando tutti gli elementi multimediali nell'interruzione hanno terminato la riproduzione o sono stati ignorati. È possibile usare il gestore per questo evento per aggiornare l'interfaccia utente per indicare che il contenuto dell'interruzione multimediale non è più in riproduzione.

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;
}

L'evento BreakSkipped viene generato quando l'utente preme il pulsante Avanti nell'interfaccia utente predefinita durante la riproduzione di un elemento per il quale CanSkip è true, o quando si ignora un'interruzione nel codice chiamando SkipCurrentBreak.

Nell'esempio seguente viene utilizzata la proprietà Source di MediaPlayer per ottenere un riferimento all'elemento multimediale per il contenuto principale. L'interruzione multimediale ignorata appartiene alla pianificazione dell'interruzione di questo elemento. Il codice verifica quindi se l'interruzione multimediale ignorata corrisponde all'interruzione multimediale impostata sulla proprietà PrerollBreak della pianificazione. In questo caso, significa che l'interruzione di preroll è stata un'interruzione ignorata e, in questo caso, viene creata una nuova interruzione midroll e pianificata per riprodurre 10 minuti nel contenuto principale.

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 viene generato quando la posizione di riproduzione dell'elemento multimediale principale passa nel tempo pianificato per una o più interruzioni multimediali. Nell'esempio seguente viene verificato se sono stati cercati più di un'interruzione multimediale, se la posizione di riproduzione è stata spostata in avanti e se è stata spostata in avanti meno di 10 minuti. In tal caso, il primo break cercato, ottenuto dall'insieme SeekedOverBreaks esposto dagli argomenti dell'evento, viene riprodotto immediatamente con una chiamata al metodo PlayBreak di 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]);
}

Accedere alla sessione di riproduzione corrente

L'oggetto MediaPlaybackSession usa la classe MediaPlayer per fornire dati ed eventi correlati al contenuto multimediale attualmente in riproduzione. MediaBreakManager dispone anche di una MediaPlaybackSession a cui è possibile accedere per ottenere dati ed eventi correlati in modo specifico al contenuto dell'interruzione multimediale riprodotto. Le informazioni che si possono ottenere dalla sessione di riproduzione includono lo stato di riproduzione corrente, la riproduzione o la sospensione e la posizione di riproduzione corrente all'interno del contenuto. Si possono usare le proprietà NaturalVideoWidth e NaturalVideoHeight e NaturalVideoSizeChanged per regolare l'interfaccia utente video se il contenuto dell'interruzione multimediale ha proporzioni diverse rispetto al contenuto principale. Si possono anche ricevere eventi come BufferingStarted, BufferingEnded e DownloadProgressChanged che possono fornire dati di telemetria utili sulle prestazioni dell'app.

L'esempio seguente registra un gestore per l'evento BufferingProgressChanged; nel gestore eventi aggiorna l'interfaccia utente per mostrare lo stato di avanzamento del buffering corrente.

_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);
}