Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird beschrieben, wie Sie einer WinUI-App die Wiedergabe adaptiver Streaming-Multimediainhalte hinzufügen. Dieses Feature unterstützt die Wiedergabe von HTTP Live Streaming (HLS) und Dynamisches Streaming über DASH-Inhalte .This feature supports playback of Http Live Streaming (HLS) and Dynamic Streaming over HTTP (DASH) content.
Ab Windows 10, Version 1803, wird Smooth Streaming von AdaptiveMediaSource unterstützt. Beachten Sie, dass für Smooth Streaming nur H264- und WVC1-Codecs unterstützt werden. Andere Manifesttypen haben diese Einschränkung nicht.
Eine Liste der unterstützten HLS-Protokolltags finden Sie unter UNTERSTÜTZUNG von HLS-Tags.
Eine Liste der unterstützten DASH-Profile finden Sie unter DASH-Profilunterstützung.
Hinweis
Der Code in diesem Artikel wurde aus dem Beispiel für adaptives Streaming angepasst.
Einfaches adaptives Streaming mit MediaPlayer und MediaPlayerElement
Um adaptive Streamingmedien in einer WinUI-App wiederzugeben, erstellen Sie ein URI-Objekt , das auf eine DASH- oder HLS-Manifestdatei zeigt. Erstellen Sie eine Instanz der MediaPlayer-Klasse . Rufen Sie "MediaSource.CreateFromUri " auf, um ein neues MediaSource-Objekt zu erstellen, und legen Sie es dann auf die Source-Eigenschaft des MediaPlayers fest. Um die Medienwiedergabe zu starten, rufen Sie Wiedergabe auf.
MediaPlayer mediaPlayer;
System.Uri manifestUri = new Uri("http://amssamples.streaming.mediaservices.windows.net/49b57c87-f5f3-48b3-ba22-c55cfdffa9cb/Sintel.ism/manifest(format=m3u8-aapl)");
mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(manifestUri);
mediaPlayer.Play();
Im obigen Beispiel wird der Audioteil des Medieninhalts abgespielt, der Inhalt wird jedoch nicht automatisch in der Benutzeroberfläche angezeigt. Die meisten Apps, die Videoinhalte wiedergeben, möchten den Inhalt auf einer XAML-Seite rendern. Fügen Sie dazu ihrer XAML-Seite ein MediaPlayerElement-Steuerelement hinzu.
<MediaPlayerElement x:Name="mediaPlayerElement" HorizontalAlignment="Stretch" AreTransportControlsEnabled="True"/>
Rufen Sie MediaSource.CreateFromUri auf, um eine MediaSource aus dem URI einer DASH- oder HLS-Manifestdatei zu erstellen. Legen Sie dann die Source-Eigenschaft des MediaPlayerElements fest. Das MediaPlayerElement erstellt automatisch ein neues MediaPlayer-Objekt für den Inhalt. Sie können Play auf dem MediaPlayer aufrufen, um die Wiedergabe zu starten.
System.Uri manifestUri = new Uri("http://amssamples.streaming.mediaservices.windows.net/49b57c87-f5f3-48b3-ba22-c55cfdffa9cb/Sintel.ism/manifest(format=m3u8-aapl)");
mediaPlayerElement.Source = MediaSource.CreateFromUri(manifestUri);
mediaPlayerElement.MediaPlayer.Play();
Adaptives Streaming mit AdaptiveMediaSource
Wenn Ihre App erweiterte features für adaptives Streaming benötigt, z. B. das Bereitstellen von benutzerdefinierten HTTP-Headern, die Überwachung der aktuellen Download- und Wiedergabebitraten oder das Anpassen der Verhältnisse, die bestimmen, wann das System Bitraten des adaptiven Datenstroms wechselt, verwenden Sie das AdaptiveMediaSource-Objekt .
Initialisieren Sie eine AdaptiveMediaSource aus einem URI.
Initialisieren Sie die AdaptiveMediaSource mit dem URI einer adaptiven Streamingmanifestdatei, indem Sie CreateFromUriAsync aufrufen. Der von dieser Methode zurückgegebene Wert "AdaptiveMediaSourceCreationStatus " informiert Sie, ob die Medienquelle erfolgreich erstellt wurde. Wenn ja, können Sie das Objekt als Streamquelle für Ihren MediaPlayer festlegen, indem Sie ein MediaSource-Objekt erstellen, indem Sie "MediaSource.CreateFromAdaptiveMediaSource" aufrufen und es dann der Source-Eigenschaft des Media Players zuweisen. In diesem Beispiel wird die AvailableBitrates-Eigenschaft abgefragt, um die maximale unterstützte Bitrate für diesen Datenstrom zu ermitteln, und dann wird dieser Wert als anfängliche Bitrate festgelegt. In diesem Beispiel werden auch Handler für die verschiedenen AdaptiveMediaSource-Ereignisse registriert, die weiter unten in diesem Artikel erläutert werden.
async private void InitializeAdaptiveMediaSource(System.Uri uri)
{
AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(uri);
if (result.Status == AdaptiveMediaSourceCreationStatus.Success)
{
ams = result.MediaSource;
mediaPlayerElement.SetMediaPlayer(new MediaPlayer());
mediaPlayerElement.MediaPlayer.Source = MediaSource.CreateFromAdaptiveMediaSource(ams);
mediaPlayerElement.MediaPlayer.Play();
ams.InitialBitrate = ams.AvailableBitrates.Max<uint>();
//Register for download requests
ams.DownloadRequested += DownloadRequested;
//Register for download failure and completion events
ams.DownloadCompleted += DownloadCompleted;
ams.DownloadFailed += DownloadFailed;
//Register for bitrate change events
ams.DownloadBitrateChanged += DownloadBitrateChanged;
ams.PlaybackBitrateChanged += PlaybackBitrateChanged;
//Register for diagnostic event
ams.Diagnostics.DiagnosticAvailable += DiagnosticAvailable;
}
else
{
// Handle failure to create the adaptive media source
MyLogMessageFunction($"Adaptive source creation failed: {uri} - {result.ExtendedError}");
}
}
Initialisieren Sie eine AdaptiveMediaSource mit HttpClient
Wenn Sie benutzerdefinierte HTTP-Header zum Abrufen der Manifestdatei festlegen müssen, können Sie ein HttpClient-Objekt erstellen, die gewünschten Header festlegen und das Objekt dann an die Überladung von CreateFromUriAsync übergeben.
httpClient = new Windows.Web.Http.HttpClient();
httpClient.DefaultRequestHeaders.TryAppendWithoutValidation("X-CustomHeader", "This is a custom header");
AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(manifestUri, httpClient);
Das DownloadRequested-Ereignis wird ausgelöst, wenn das System eine Ressource vom Server abruft. Die an den Ereignishandler übergebene AdaptiveMediaSourceDownloadRequestedEventArgs macht Eigenschaften verfügbar, die Informationen über die angeforderte Ressource bereitstellen, z. B. den Typ und den URI der Ressource.
Ändern von Ressourcenanforderungseigenschaften mithilfe des DownloadRequested-Ereignisses
Sie können den DownloadRequested-Ereignishandler verwenden, um die Ressourcenanforderung zu ändern, indem Sie die Eigenschaften des AdaptiveMediaSourceDownloadResult-Objekts aktualisieren, das von den Ereignisargumenten bereitgestellt wird. Im folgenden Beispiel wird der URI, aus dem die Ressource abgerufen wird, durch Aktualisieren der ResourceUri-Eigenschaften des Ergebnisobjekts geändert. Sie können den Bytebereichsoffset und die Länge auch für Mediensegmente neu schreiben oder den Ressourcen-URI ändern, um die vollständige Ressource herunterzuladen und den Bytebereichsoffset und die Länge auf NULL festzulegen.
Sie können den Inhalt der angeforderten Ressource überschreiben, indem Sie die Eigenschaften Puffer oder InputStream des Ergebnisobjekts festlegen. Im folgenden Beispiel werden die Inhalte der Manifestressource durch Festlegen der Buffer-Eigenschaft ersetzt. Wenn Sie die Ressourcenanforderung mit Daten aktualisieren, die asynchron abgerufen werden, z. B. das Abrufen von Daten von einem Remoteserver oder eine asynchrone Benutzerauthentifizierung, müssen Sie adaptiveMediaSourceDownloadRequestedEventArgs.GetDeferral aufrufen, um eine Verzögerung abzurufen und dann "Abgeschlossen " aufzurufen, wenn der Vorgang abgeschlossen ist, um dem System zu signalisieren, dass der Downloadanforderungsvorgang fortgesetzt werden kann.
private async void DownloadRequested(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadRequestedEventArgs args)
{
// rewrite key URIs to replace http:// with https://
if (args.ResourceType == AdaptiveMediaSourceResourceType.Key)
{
string originalUri = args.ResourceUri.ToString();
string secureUri = originalUri.Replace("http:", "https:");
// override the URI by setting property on the result sub object
args.Result.ResourceUri = new Uri(secureUri);
}
if (args.ResourceType == AdaptiveMediaSourceResourceType.Manifest)
{
AdaptiveMediaSourceDownloadRequestedDeferral deferral = args.GetDeferral();
args.Result.Buffer = await CreateMyCustomManifest(args.ResourceUri);
deferral.Complete();
}
if (args.ResourceType == AdaptiveMediaSourceResourceType.MediaSegment)
{
var resourceUri = args.ResourceUri.ToString() + "?range=" +
args.ResourceByteRangeOffset + "-" + (args.ResourceByteRangeLength - 1);
// override the URI by setting a property on the result sub object
args.Result.ResourceUri = new Uri(resourceUri);
// clear the byte range properties on the result sub object
args.Result.ResourceByteRangeOffset = null;
args.Result.ResourceByteRangeLength = null;
}
}
Verwenden von Bitrate-Ereignissen zum Verwalten und Reagieren auf Bitrate-Änderungen
Das AdaptiveMediaSource-Objekt stellt Ereignisse bereit, mit denen Sie reagieren können, wenn sich die Download- oder Wiedergabebitraten ändern. In diesem Beispiel werden die aktuellen Bitraten einfach in der Benutzeroberfläche aktualisiert. Beachten Sie, dass Sie die Verhältnisse ändern können, die bestimmen, wann das System Bitraten des adaptiven Datenstroms wechselt. Weitere Informationen finden Sie in der AdvancedSettings-Eigenschaft .
private void DownloadBitrateChanged(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadBitrateChangedEventArgs args)
{
DispatcherQueue.TryEnqueue(() =>
{
tbDownloadBitrate.Text = args.NewValue.ToString();
});
}
private void PlaybackBitrateChanged(AdaptiveMediaSource sender, AdaptiveMediaSourcePlaybackBitrateChangedEventArgs args)
{
DispatcherQueue.TryEnqueue(() =>
{
tbPlaybackBitrate.Text = args.NewValue.ToString();
});
}
Behandeln von Downloadabschluss- und Fehlerereignissen
Das AdaptiveMediaSource-Objekt löst das DownloadFailed-Ereignis aus, wenn der Download einer angeforderten Ressource fehlschlägt. Sie können dieses Ereignis verwenden, um die Benutzeroberfläche als Reaktion auf den Fehler zu aktualisieren. Sie können das Ereignis auch verwenden, um statistische Informationen zum Downloadvorgang und zum Fehler zu protokollieren.
Das an den Ereignishandler übergebene AdaptiveMediaSourceDownloadFailedEventArgs-Objekt enthält Metadaten zum fehlgeschlagenen Ressourcendownload, z. B. den Ressourcentyp, den URI der Ressource und die Position innerhalb des Datenstroms, an dem der Fehler aufgetreten ist. Die RequestId ruft einen vom System generierten eindeutigen Bezeichner für die Anforderung ab, mit der Statusinformationen zu einer einzelnen Anforderung über mehrere Ereignisse korreliert werden können.
Die Statistics-Eigenschaft gibt ein AdaptiveMediaSourceDownloadStatistics-Objekt zurück, das detaillierte Informationen zur Anzahl der zum Zeitpunkt des Ereignisses empfangenen Bytes und den Zeitpunkt verschiedener Meilensteine im Downloadvorgang bereitstellt. Sie können diese Informationen protokollieren, um Leistungsprobleme in Ihrer adaptiven Streamingimplementierung zu identifizieren.
private void DownloadFailed(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadFailedEventArgs args)
{
var statistics = args.Statistics;
MyLogMessageFunction("download failed for: " + args.ResourceType +
" - " + args.ResourceUri +
" � Error:" + args.ExtendedError.HResult +
" - RequestId" + args.RequestId +
" � Position:" + args.Position +
" - Duration:" + args.ResourceDuration +
" - ContentType:" + args.ResourceContentType +
" - TimeToHeadersReceived:" + statistics.TimeToHeadersReceived +
" - TimeToFirstByteReceived:" + statistics.TimeToFirstByteReceived +
" - TimeToLastByteReceived:" + statistics.TimeToLastByteReceived +
" - ContentBytesReceivedCount:" + statistics.ContentBytesReceivedCount);
}
Das DownloadCompleted-Ereignis tritt auf, wenn ein Ressourcendownload abgeschlossen ist und ähnliche Daten wie das DownloadFailed-Ereignis bereitstellt. Erneut wird eine RequestId zum Korrelieren von Ereignissen für eine einzelne Anforderung bereitgestellt. Außerdem wird ein AdaptiveMediaSourceDownloadStatistics-Objekt bereitgestellt, um die Protokollierung von Downloadstatistiken zu ermöglichen.
private void DownloadCompleted(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadCompletedEventArgs args)
{
var statistics = args.Statistics;
MyLogMessageFunction("download completed for: " + args.ResourceType + " - " +
args.ResourceUri +
" � RequestId:" + args.RequestId +
" � Position:" + args.Position +
" - Duration:" + args.ResourceDuration +
" - ContentType:" + args.ResourceContentType +
" - TimeToHeadersReceived:" + statistics.TimeToHeadersReceived +
" - TimeToFirstByteReceived:" + statistics.TimeToFirstByteReceived +
" - TimeToLastByteReceived:" + statistics.TimeToLastByteReceived +
" - ContentBytesReceivedCount:" + statistics.ContentBytesReceivedCount);
}
Erfassen von Telemetriedaten für adaptives Streaming mit AdaptiveMediaSourceDiagnostics
Die AdaptiveMediaSource macht eine Diagnostics-Eigenschaft verfügbar, die ein AdaptiveMediaSourceDiagnostics -Objekt zurückgibt. Verwenden Sie dieses Objekt, um sich für das DiagnosticAvailable-Ereignis zu registrieren. Dieses Ereignis soll für die Telemetrienerfassung verwendet werden und nicht dazu, um das Verhalten der App während der Laufzeit zu ändern. Dieses Diagnoseereignis wird aus vielen verschiedenen Gründen ausgelöst. Überprüfen Sie die DiagnosticType-Eigenschaft des an das Ereignis übergebenen AdaptiveMediaSourceDiagnosticAvailableEventArgs-Objekts , um den Grund zu ermitteln, warum das Ereignis ausgelöst wurde. Mögliche Ursachen sind Fehler beim Zugriff auf die angeforderte Ressource und Fehler beim Analysieren der Streamingmanifestdatei. Eine Liste der Situationen, die ein Diagnoseereignis auslösen können, finden Sie unter AdaptiveMediaSourceDiagnosticType. Wie die Argumente für andere adaptive Streamingereignisse stellt das AdaptiveMediaSourceDiagnosticAvailableEventArgs eine RequestId-Eigenschaft zum Korrelieren von Anforderungsinformationen zwischen verschiedenen Ereignissen bereit.
private void DiagnosticAvailable(AdaptiveMediaSourceDiagnostics sender, AdaptiveMediaSourceDiagnosticAvailableEventArgs args)
{
MySendTelemetryFunction(args.RequestId, args.Position,
args.DiagnosticType, args.SegmentId,
args.ResourceType, args.ResourceUri,
args.ResourceDuration, args.ResourceContentType,
args.ResourceByteRangeOffset,
args.ResourceByteRangeLength,
args.Bitrate,
args.ExtendedError);
}
Verzögern Sie die Bindung adaptiver Streaminginhalte für Elemente in einer Wiedergabeliste mithilfe von MediaBinder.
Mit der MediaBinder-Klasse können Sie die Bindung von Medieninhalten in einer MediaPlaybackList zurückstellen. Ab Windows 10, Version 1703, können Sie eine AdaptiveMediaSource als gebundenen Inhalt bereitstellen. Der Prozess für die verzögerte Bindung einer adaptiven Medienquelle entspricht weitgehend der Bindung anderer Medientypen, die in Medienelementen, Wiedergabelisten und Titeln beschrieben werden.
Erstellen Sie eine MediaBinder-Instanz , legen Sie eine appdefinierte Tokenzeichenfolge fest, um den zu bindenden Inhalt zu identifizieren und sich für das Binding-Ereignis zu registrieren. Erstellen Sie eine MediaSource aus dem Binder, indem Sie MediaSource.CreateFromMediaBinder aufrufen. Erstellen Sie dann ein MediaPlaybackItem aus der MediaSource , und fügen Sie es der Wiedergabeliste hinzu.
mediaPlaybackList = new MediaPlaybackList();
var binder = new MediaBinder();
binder.Token = "MyBindingToken1";
binder.Binding += Binder_Binding; ;
mediaPlaybackList.Items.Add(new MediaPlaybackItem(MediaSource.CreateFromMediaBinder(binder)));
binder = new MediaBinder();
binder.Token = "MyBindingToken2";
binder.Binding += Binder_Binding;
mediaPlaybackList.Items.Add(new MediaPlaybackItem(MediaSource.CreateFromMediaBinder(binder)));
mediaPlayer = new MediaPlayer();
mediaPlayer.Source = mediaPlaybackList;
mediaPlayerElement.SetMediaPlayer(mediaPlayer);
Verwenden Sie im Binding-Ereignishandler die Tokenzeichenfolge, um den inhalt zu identifizieren, der gebunden werden soll, und erstellen Sie dann die adaptive Medienquelle, indem Sie eine der Überladungen von CreateFromStreamAsync oder CreateFromUriAsync aufrufen. Da es sich um asynchrone Methoden handelt, sollten Sie zuerst die MediaBindingEventArgs.GetDeferral-Methode aufrufen, um das System anzuweisen, auf den Abschluss des Vorgangs zu warten, bevor Sie fortfahren. Legen Sie die adaptive Medienquelle als gebundenen Inhalt fest, indem Sie SetAdaptiveMediaSource aufrufen. Rufen Sie abschließend Deferral.Complete auf, nachdem der Vorgang abgeschlossen ist, um das System anzuweisen, den Vorgang fortzusetzen.
private async void Binder_Binding_AdaptiveMediaSource(MediaBinder sender, MediaBindingEventArgs args)
{
var deferral = args.GetDeferral();
var contentUri = new Uri($"http://contoso.com/media/{args.MediaBinder.Token}");
AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(contentUri);
if (result.MediaSource != null)
{
args.SetAdaptiveMediaSource(result.MediaSource);
}
args.SetUri(contentUri);
deferral.Complete();
}
Wenn Sie Ereignishandler für die gebundene adaptive Medienquelle registrieren möchten, können Sie dies im Handler für das CurrentItemChanged-Ereignis der MediaPlaybackList tun. Die CurrentMediaPlaybackItemChangedEventArgs.NewItem-Eigenschaft enthält das neue derzeit abgespielte MediaPlaybackItem in der Liste. Rufen Sie eine Instanz der AdaptiveMediaSource ab, die das neue Element darstellt, indem Sie auf die Source-Eigenschaft des MediaPlaybackItem und dann auf die AdaptiveMediaSource-Eigenschaft der Medienquelle zugreifen. Diese Eigenschaft ist NULL, wenn das neue Wiedergabeelement keine AdaptiveMediaSource ist. Daher sollten Sie vor dem Versuch, Handler für ereignisse des Objekts zu registrieren, auf NULL testen.
private void AMSMediaPlaybackList_CurrentItemChanged(MediaPlaybackList sender, CurrentMediaPlaybackItemChangedEventArgs args)
{
if (!(args.NewItem is null))
{
var ams = args.NewItem.Source.AdaptiveMediaSource;
if (!(ams is null))
{
ams.PlaybackBitrateChanged += Ams_PlaybackBitrateChanged;
}
}
}
Zugehörige Themen
Windows developer