Megosztás a következőn keresztül:


Adaptív streamelés

Ez a cikk bemutatja, hogyan adhat hozzá adaptív streamelési multimédiás tartalmak lejátszását egy WinUI-alkalmazáshoz. Ez a funkció támogatja a HTTP-alapú élő streamelés (HLS) és a dinamikus streamelés HTTP-n (DASH) keresztüli lejátszását.

A Windows 10 1803-es verziójától kezdve a Smooth Streaminget az AdaptiveMediaSource támogatja. Vegye figyelembe, hogy a Smooth Streaming esetében csak a H264 és WVC1 kodekek támogatottak. Más jegyzéktípusokra nem vonatkozik ez a korlátozás.

A támogatott HLS-protokollcímkék listáját a HLS-címkék támogatásával kapcsolatban találja.

A támogatott DASH-profilok listáját a DASH-profilok támogatásával kapcsolatban találja.

Megjegyzés:

A cikkben szereplő kód az Adaptív streamelési mintából lett adaptálva.

Egyszerű adaptív streamelés a MediaPlayer és a MediaPlayerElement használatával

Ha adaptív streamelési adathordozót szeretne lejátszani egy WinUI-alkalmazásban, hozzon létre egy URI-objektumot , amely EGY DASH- vagy HLS-jegyzékfájlra mutat. Hozza létre a MediaPlayer-osztály egy példányát. A MediaSource.CreateFromUri meghívásával hozzon létre egy új MediaSource-objektumot, majd állítsa be a MediaPlayerForrás tulajdonságára. Hívja fel a Lejátszást a médiatartalom lejátszásának elindításához.

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

A fenti példa lejátssza a médiatartalom hangját, de nem jeleníti meg automatikusan a tartalmat a felhasználói felületen. A videótartalmat lejátszó alkalmazások többsége egy XAML-lapon szeretné megjeleníteni a tartalmat. Ehhez vegyen fel egy MediaPlayerElement-vezérlőt az XAML-lapra.

<MediaPlayerElement x:Name="mediaPlayerElement" HorizontalAlignment="Stretch" AreTransportControlsEnabled="True"/>

A MediaSource.CreateFromUri meghívásával hozzon létre egy MediaSource-t egy DASH- vagy HLS-jegyzékfájl URI-jából. Ezután állítsa be a MediaPlayerElement Forrás tulajdonságát. A MediaPlayerElement automatikusan létrehoz egy új MediaPlayer-objektumot a tartalomhoz. A tartalom lejátszását a Play meghívásával kezdheti el a MediaPlayer használatával.

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

Adaptív streamelés az AdaptiveMediaSource-nal

Ha az alkalmazás speciális adaptív streamelési funkciókat igényel, például egyéni HTTP-fejléceket biztosít, figyeli az aktuális letöltési és lejátszási bitrátákat, vagy módosítja azokat az arányokat, amelyek meghatározzák, hogy a rendszer mikor váltja át az adaptív stream bitrátáit, használja az AdaptiveMediaSource objektumot.

Egy URI-ból AdaptiveMediaSource inicializálása.

Inicializálja az AdaptiveMediaSource-t egy adaptív streamelési jegyzékfájl URI-jával a CreateFromUriAsync meghívásával. Az ebből a metódusból visszaadott AdaptiveMediaSourceCreationStatus értékből megtudhatja, hogy a médiaforrás sikeresen létrejött-e. Ha igen, beállíthatja az objektumot a MediaPlayer streamforrásaként, ha létrehoz egy MediaSource objektumot a MediaSource.CreateFromAdaptiveMediaSource meghívásával, majd hozzárendeli azt a médialejátszó Forrás tulajdonságához. Ebben a példában az AvailableBitrates tulajdonság lekérdezve határozza meg a stream maximális támogatott sávszélességét, majd ezt az értéket állítja be a kezdeti bitrátaként. Ez a példa a cikk későbbi részében tárgyalt számos AdaptiveMediaSource-esemény kezelőit is regisztrálja.

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

AdaptiveMediaSource inicializálása a HttpClient használatával

Ha egyéni HTTP-fejléceket kell beállítania a jegyzékfájl lekéréséhez, létrehozhat egy HttpClient-objektumot , beállíthatja a kívánt fejléceket, majd átadhatja az objektumot a CreateFromUriAsync túlterhelésének.

httpClient = new Windows.Web.Http.HttpClient();
httpClient.DefaultRequestHeaders.TryAppendWithoutValidation("X-CustomHeader", "This is a custom header");
AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(manifestUri, httpClient);

A DownloadRequested esemény akkor jön létre, amikor a rendszer le szeretne kérni egy erőforrást a kiszolgálóról. Az eseménykezelőnek átadott AdaptiveMediaSourceDownloadRequestedEventArgs olyan tulajdonságokat tesz elérhetővé, amelyek információt nyújtanak a kért erőforrásról, például az erőforrás típusáról és URI-járól.

Erőforrás-kérelem tulajdonságainak módosítása a DownloadRequested esemény használatával

A DownloadRequested eseménykezelővel módosíthatja az erőforrás-kérést az esemény args által biztosított AdaptiveMediaSourceDownloadResult objektum tulajdonságainak frissítésével. Az alábbi példában az erőforrás lekéréséhez használt URI az eredményobjektum ResourceUri-tulajdonságainak frissítésével módosul. A médiaszegmensek bájttartomány-eltolását és hosszát is átírhatja, vagy az alábbi példában látható módon módosíthatja az erőforrás URI-jának módosítását a teljes erőforrás letöltéséhez, és a bájttartomány eltolását és hosszát null értékre állíthatja.

A kért erőforrás tartalmát felülbírálhatja az eredményobjektum Puffer - vagy InputStream-tulajdonságainak beállításával. Az alábbi példában a jegyzék-erőforrás tartalmát a Puffer tulajdonság beállításával helyettesítjük. Vegye figyelembe, hogy ha az erőforrás-kérést az aszinkron módon beszerzett adatokkal frissíti, például távoli kiszolgálóról vagy aszinkron felhasználói hitelesítésből származó adatokat, az AdaptiveMediaSourceDownloadRequestedEventArgs.GetDeferral meghívásával lekérheti a halasztást, majd ha a művelet befejeződött, a rendszer jelezheti, hogy a letöltési kérelem művelete folytatódhat.

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

A bitrátaesemények használata a változások kezelésére és azokra való reagálásra

Az AdaptiveMediaSource objektum olyan eseményeket biztosít, amelyek lehetővé teszik, hogy reagáljon a letöltési vagy lejátszási bitráták változásakor. Ebben a példában az aktuális bitráták egyszerűen frissülnek a felhasználói felületen. Vegye figyelembe, hogy módosíthatja azokat az arányokat, amelyek meghatározzák, hogy a rendszer mikor váltja át az adaptív stream bitrátáit. További információ: AdvancedSettings tulajdonság.

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

Letöltési befejezési és hibaesemények kezelése

Az AdaptiveMediaSource objektum akkor aktiválja a DownloadFailed eseményt , ha a kért erőforrás letöltése meghiúsul. Az esemény használatával frissítheti a felhasználói felületet a hibára válaszul. Az esemény használatával statisztikai adatokat is naplózhat a letöltési műveletről és a hibáról.

Az eseménykezelőnek átadott AdaptiveMediaSourceDownloadFailedEventArgs objektum metaadatokat tartalmaz a sikertelen erőforrás-letöltésről, például az erőforrás típusáról, az erőforrás URI-járól és a stream azon pozíciójáról, ahol a hiba történt. A RequestId egy rendszer által generált egyedi azonosítót kap a kéréshez, amely felhasználható az egyes kérések állapotadatainak korrelálására több esemény között.

A Statistics tulajdonság egy AdaptiveMediaSourceDownloadStatistics objektumot ad vissza, amely részletes információkat nyújt az esemény időpontjában fogadott bájtok számáról és a letöltési művelet különböző mérföldköveinek időzítéséről. Ezeket az adatokat naplózhatja az adaptív streamelési implementáció teljesítményproblémáinak azonosítása érdekében.

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

}

A DownloadCompleted esemény akkor következik be, amikor egy erőforrás letöltése befejeződik, és hasonló adatokat szolgáltat a DownloadFailed eseményhez. Ismét meg van adva egy RequestId , amely egyetlen kérelem eseményeinek korrelációját biztosítja. Emellett egy AdaptiveMediaSourceDownloadStatistics objektum is rendelkezésre áll a letöltési statisztikák naplózásának engedélyezéséhez.

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

}

Adaptív streamelési telemetriai adatok gyűjtése az AdaptiveMediaSourceDiagnostics használatával

Az AdaptiveMediaSource egy Diagnosztikai tulajdonságot tesz elérhetővé, amely egy AdaptiveMediaSourceDiagnostics objektumot ad vissza. Ezzel az objektummal regisztrálhat a DiagnosticAvailable eseményre. Ez az esemény telemetriagyűjtésre szolgál, és nem használható az alkalmazások futásidőben történő viselkedésének módosítására. Ez a diagnosztikai esemény számos különböző okból merül fel. Ellenőrizze az eseménybe átadott DiagnosticType tulajdonságát az AdaptiveMediaSourceDiagnosticAvailableEventArgs objektumnak az esemény létrehozásának okának megállapításához. A lehetséges okok közé tartoznak a kért erőforráshoz való hozzáféréssel kapcsolatos hibák, valamint a streamelési jegyzékfájl elemzésével kapcsolatos hibák. A diagnosztikai eseményeket kiváltó helyzetek listáját az AdaptiveMediaSourceDiagnosticType című témakörben találja. A többi adaptív streamelési esemény argumentumaihoz hasonlóan az AdaptiveMediaSourceDiagnosticAvailableEventArgs egy RequestId tulajdonságot is biztosít a különböző események közötti kérésadatok korrelálására.

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

}

Adaptív streamelési tartalom kötésének elhalasztása egy lejátszási lista elemeihez a MediaBinder használatával

A MediaBinder osztály lehetővé teszi a médiatartalmak kötésének elhalasztását a MediaPlaybackListben. A Windows 10 1703-as verziójától kezdve egy AdaptiveMediaSource-t is megadhat kötött tartalomként. Az adaptív médiaforrás késleltetett kötésének folyamata nagyrészt megegyezik a médiaelemekben , lejátszási listákban és zeneszámokban leírt más típusú médiatartalmak kötésével.

Hozzon létre egy MediaBinder-példányt, állítson be egy alkalmazás által definiált jogkivonat-sztringet a kötendő tartalom azonosításához, és regisztráljon a kötési eseményre. Hozzon létre egy MediaSource-t a Binderből a MediaSource.CreateFromMediaBinder meghívásával. Ezután hozzon létre egy MediaPlaybackItemet a MediaSource-ból , és adja hozzá a lejátszási listához.

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

A Kötés eseménykezelőben használja a token sztringet a kötendő tartalom azonosítására, majd hozza létre a médiaforrást adaptív módon a CreateFromStreamAsync vagy a CreateFromUriAsync egyik túlterhelésének a meghívásával. Mivel ezek aszinkron metódusok, először hívja meg a MediaBindingEventArgs.GetDeferral metódust, hogy utasítsa a rendszert, hogy várja meg a művelet befejezését a folytatás előtt. Állítsa be az adaptív médiaforrást kötött tartalomként a SetAdaptiveMediaSource meghívásával. Végül hívja meg a Deferral.Complete parancsot a művelet befejezése után, hogy utasítsa a rendszert a folytatásra.

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

Ha eseménykezelőket szeretne regisztrálni a kötött adaptív médiaforráshoz, ezt a MediaPlaybackListCurrentItemChanged eseményének kezelőjében teheti meg. A CurrentMediaPlaybackItemChangedEventArgs.NewItem tulajdonság tartalmazza az új jelenleg lejátszott MediaPlaybackItemet a listában. Szerezze be az új elemet képviselő AdaptiveMediaSource példányt úgy, hogy először hozzáfér a Forrás tulajdonságához a MediaPlaybackItem-nél, majd a médiaforrás AdaptiveMediaSource tulajdonságához. Ez a tulajdonság null értékű lesz, ha az új lejátszási elem nem AdaptiveMediaSource, ezért az objektum eseményeinek kezelőinek regisztrálása előtt tesztelje a null értéket.

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