Lire du contenu audio et vidéo avec MediaPlayerPlay audio and video with MediaPlayer

Cet article explique comment lire des médias dans votre application Windows universelle à l’aide de la classe MediaPlayer .This article shows you how to play media in your Universal Windows app using the MediaPlayer class. Avec Windows 10, version 1607, des améliorations significatives ont été apportées aux API de lecture multimédia, y compris une conception simplifiée à processus unique pour l’audio en arrière-plan, l’intégration automatique aux contrôles de transport des médias système (SMTC), la possibilité de synchroniser plusieurs lecteurs multimédias, la possibilité de rendre des images vidéo sur une surface Windows.With Windows 10, version 1607, significant improvements were made to the media playback APIs, including a simplified single-process design for background audio, automatic integration with the System Media Transport Controls (SMTC), the ability to synchronize multiple media players, the ability to render video frames to a Windows.UI.Composition surface, and an easy interface for creating and scheduling media breaks in your content. Pour tirer parti de ces améliorations, la meilleure pratique recommandée pour la lecture de contenus multimédias consiste à utiliser la classe MediaPlayer en lieu et place de MediaElement pour la lecture de contenu multimédia.To take advantage of these improvements, the recommended best practice for playing media is to use the MediaPlayer class instead of MediaElement for media playback. Le contrôle XAML léger, MediaPlayerElement, a été introduit pour vous permettre d’afficher le contenu multimédia dans une page XAML.The lightweight XAML control, MediaPlayerElement, has been introduced to allow you render media content in a XAML page. Nombre des API de statut et de contrôle de la lecture fournies par MediaElement sont désormais disponibles via le nouvel objet MediaPlaybackSession.Many of the playback control and status APIs provided by MediaElement are now available through the new MediaPlaybackSession object. MediaElement continue de fonctionner pour prendre en charge la compatibilité descendante, mais aucune fonction supplémentaire ne sera ajoutée à cette classe.MediaElement continues to function to support backwards compatibility, but no additional features will be added to this class.

Cet article vous présente les fonctions MediaPlayer qu’une application standard de lecture de contenu multimédia utilise.This article will walk you through the MediaPlayer features that a typical media playback app will use. Notez que MediaPlayer utilise la classe MediaSource en tant que conteneur pour l’ensemble des éléments multimédias.Note that MediaPlayer uses the MediaSource class as a container for all media items. Cette classe vous permet de charger et de lire le contenu multimédia à partir de multiples sources différentes utilisant une interface unique, notamment les fichiers locaux, les flux de mémoire et les sources réseau.This class allows you to load and play media from many different sources, including local files, memory streams, and network sources, all using the same interface. Il existe également des classes de niveau supérieur compatibles avec MediaSource, comme MediaPlaybackItem et MediaPlaybackList, qui fournissent des fonctions plus avancées comme des playlists et la capacité de gestion de sources multimédias avec plusieurs pistes audio, vidéo et de métadonnées.There are also higher-level classes that work with MediaSource, such as MediaPlaybackItem and MediaPlaybackList, that provide more advanced features like playlists and the ability to manage media sources with multiple audio, video, and metadata tracks. Pour plus d’informations sur MediaSource et les API associées, consultez la page Éléments, playlists et pistes multimédias.For more information on MediaSource and related APIs, see Media items, playlists, and tracks.

Notes

Les éditions Windows 10 N et Windows 10 KN n’incluent pas les fonctionnalités de média nécessaires à l’utilisation de MediaPlayer pour la lecture.Windows 10 N and Windows 10 KN editions do not include the media features required to use MediaPlayer for playback. Ces fonctionnalités peuvent être installées manuellement.These features can be installed manually. Pour plus d’informations, consultez Media Feature Pack for Windows 10 N et Windows 10 kN Editions.For more information, see Media feature pack for Windows 10 N and Windows 10 KN editions.

Lire un fichier multimédia avec MediaPlayerPlay a media file with MediaPlayer

La lecture de contenu multimédia de base avec MediaPlayer est très simple à implémenter.Basic media playback with MediaPlayer is very simple to implement. Tout d’abord, créez une nouvelle instance de la classe MediaPlayer.First, create a new instance of the MediaPlayer class. Votre application peut présenter plusieurs instances MediaPlayer actives simultanément.Your app can have multiple MediaPlayer instances active at once. Ensuite, définissez la propriété source du lecteur sur un objet qui implémente IMediaPlaybackSource, tel qu’un MediaSource, un MediaPlaybackItemou un MediaPlaybackList.Next, set the Source property of the player to an object that implements the IMediaPlaybackSource, such as a MediaSource, a MediaPlaybackItem, or a MediaPlaybackList. Dans cet exemple, un objet MediaSource est créé à partir d’un fichier dans le stockage local de l’application, puis un objet MediaPlaybackItem est créé à partir de la source, puis affecté à la propriété Source du lecteur.In this example, a MediaSource is created from a file in the app's local storage, and then a MediaPlaybackItem is created from the source and then assigned to the player's Source property.

Contrairement à l’objet MediaElement, MediaPlayer ne démarre pas automatiquement la lecture par défaut.Unlike MediaElement, MediaPlayer does not automatically begin playback by default. Vous pouvez démarrer la lecture en appelant Play, en affectant à la propriété AutoPlay la valeur true, ou en attendant que l’utilisateur lance la lecture avec les contrôles multimédia intégrés.You can start playback by calling Play, by setting the AutoPlay property to true, or waiting for the user to initiate playback with the built-in media controls.

mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer.Play();

Lorsque vous avez terminé d’utiliser une instance MediaPlayer sur l’application, vous devez appeler la méthode Close (projetée vers Dispose en C#) afin de nettoyer les ressources utilisées par le lecteur.When your app is done using a MediaPlayer, you should call the Close method (projected to Dispose in C#) to clean up the resources used by the player.

mediaPlayer.Dispose();

Utiliser MediaPlayerElement afin d’afficher du contenu vidéo dans XAMLUse MediaPlayerElement to render video in XAML

Vous pouvez lire du contenu multimédia dans une instance MediaPlayer sans l’afficher au format XAML, mais de nombreuses applications de lecture de contenus multimédias sont définies pour ce type d’affichage.You can play media in a MediaPlayer without displaying it in XAML, but many media playback apps will want to render the media in a XAML page. Pour ce faire, utilisez le contrôle léger MediaPlayerElement.To do this, use the lightweight MediaPlayerElement control. Tout comme MediaElement, MediaPlayerElement vous permet de spécifier si les contrôles intégrés de transport doivent être affichés.Like MediaElement, MediaPlayerElement allows you to specify whether the built-in transport controls should be shown.

<MediaPlayerElement x:Name="_mediaPlayerElement" AreTransportControlsEnabled="False" HorizontalAlignment="Stretch"  Grid.Row="0"/>

Vous pouvez définir l’instance MediaPlayer à laquelle l’élément est lié en appelant SetMediaPlayer.You can set the MediaPlayer instance that the element is bound to by calling SetMediaPlayer.

_mediaPlayerElement.SetMediaPlayer(mediaPlayer);

Vous pouvez également définir la source de lecture sur l’instance MediaPlayerElement. Le cas échéant, l’élément crée automatiquement une nouvelle instance MediaPlayer à laquelle vous pouvez accéder à l’aide de la propriété MediaPlayer.You can also set the playback source on the MediaPlayerElement and the element will automatically create a new MediaPlayer instance that you can access using the MediaPlayer property.

_mediaPlayerElement.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer = _mediaPlayerElement.MediaPlayer;
mediaPlayer.Play();

Notes

Si vous désactivez l’élément MediaPlaybackCommandManager de l’instance MediaPlayer en définissant IsEnabled sur false, le lien entre MediaPlayer et TransportControls fourni par MediaPlayerElement est rompu ; autrement dit, les contrôles de transport intégrés ne contrôleront plus automatiquement la lecture du lecteur.If you disable the MediaPlaybackCommandManager of the MediaPlayer by setting IsEnabled to false, it will break the link between the MediaPlayer the TransportControls provided by the MediaPlayerElement, so the built-in transport controls will no longer automatically control the playback of the player. Vous devrez donc implémenter vos propres contrôles pour pouvoir contrôler le MediaPlayer.Instead, you must implement your own controls to control the MediaPlayer.

Tâches courantes de MediaPlayerCommon MediaPlayer tasks

Cette section vous explique comment utiliser certaines des fonctionnalités de l’instance MediaPlayer.This section shows you how to use some of the features of the MediaPlayer.

Définir la catégorie audioSet the audio category

Définissez la propriété AudioCategory d’une instance MediaPlayer sur l’une des valeurs de l’énumération MediaPlayerAudioCategory afin d’indiquer au système le type de contenu multimédia lu.Set the AudioCategory property of a MediaPlayer to one of the values of the MediaPlayerAudioCategory enumeration to let the system know what kind of media you are playing. Les jeux doivent classer leurs flux musicaux en tant qu’éléments GameMedia, de manière à ce que la musique du jeu soit désactivée automatiquement si de la musique s’active sur une autre application en arrière-plan.Games should categorize their music streams as GameMedia so that game music mutes automatically if another application plays music in the background. Les applications de musique ou de vidéo doivent classer leurs flux en tant qu’éléments Media ou Movie, de manière à les rendre prioritaires par rapport aux flux GameMedia.Music or video applications should categorize their streams as Media or Movie so they will take priority over GameMedia streams.

mediaPlayer.AudioCategory = MediaPlayerAudioCategory.Media;

Sortie vers un point de terminaison audio spécifiqueOutput to a specific audio endpoint

Par défaut, la sortie audio d’une instance MediaPlayer est acheminée vers le point de terminaison audio par défaut du système, mais vous pouvez définir un point de terminaison audio spécifique que l’instance MediaPlayer doit utiliser pour la sortie.By default, the audio output from a MediaPlayer is routed to the default audio endpoint for the system, but you can specify a specific audio endpoint that the MediaPlayer should use for output. Dans l’exemple ci-dessous, MediaDevice. GetAudioRenderSelector retourne une chaîne qui idenfies de manière unique la catégorie de rendu audio des appareils.In the example below, MediaDevice.GetAudioRenderSelector returns a string that uniquely idenfies the audio render category of devices. Ensuite, la DeviceInformation méthode DeviceInformation FindAllAsync est appelée pour obtenir la liste de tous les appareils disponibles du type sélectionné.Next, the DeviceInformation method FindAllAsync is called to get a list of all available devices of the selected type. Vous pouvez déterminer par programmation l’appareil que vous souhaitez utiliser ou ajouter les périphériques retournés à un contrôle ComboBox pour permettre à l’utilisateur de sélectionner un appareil.You may programmatically determine which device you want to use or add the returned devices to a ComboBox to allow the user to select a device.

string audioSelector = MediaDevice.GetAudioRenderSelector();
var outputDevices = await DeviceInformation.FindAllAsync(audioSelector);
foreach (var device in outputDevices)
{
    var deviceItem = new ComboBoxItem();
    deviceItem.Content = device.Name;
    deviceItem.Tag = device;
    _audioDeviceComboBox.Items.Add(deviceItem);
}

Dans l’événement SelectionChanged de la zone déroulante des appareils, la propriété AudioDevice de l’instance MediaPlayer est définie sur l’appareil sélectionné, qui était stocké dans la propriété Tag de l’instance ComboBoxItem.In the SelectionChanged event for the devices combo box, the AudioDevice property of the MediaPlayer is set to the selected device, which was stored in the Tag property of the ComboBoxItem.

private void _audioDeviceComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    DeviceInformation selectedDevice = (DeviceInformation)((ComboBoxItem)_audioDeviceComboBox.SelectedItem).Tag;
    if (selectedDevice != null)
    {
        mediaPlayer.AudioDevice = selectedDevice;
    }
}

Session de lecturePlayback session

Comme décrit précédemment dans cet article, nombre des fonctions exposées par la classe MediaElement ont été déplacées vers la classe MediaPlaybackSession.As described previously in this article, many of the functions that are exposed by the MediaElement class have been moved to the MediaPlaybackSession class. Cela concerne les informations sur l’état de lecture du lecteur, comme la position actuelle de lecture, l’action du lecteur (pause ou lecture) et la vitesse de lecture actuelle.This includes information about the playback state of the player, such as the current playback position, whether the player is paused or playing, and the current playback speed. MediaPlaybackSession fournit également plusieurs événements vous procurant des informations sur les modifications de l’état, notamment sur le statut actuel de mise en mémoire tampon et de téléchargement du contenu lu et sur la taille naturelle et les proportions du contenu vidéo actuellement lu.MediaPlaybackSession also provides several events to notify you when the state changes, including the current buffering and download status of content being played and the natural size and aspect ratio of the currently playing video content.

L’exemple suivant vous illustre l’implémentation d’un gestionnaire de clic du bouton qui permet d’avancer de 10 secondes dans le contenu.The following example shows you how to implement a button click handler that skips 10 seconds forward in the content. Tout d’abord, l’objet MediaPlaybackSession associé au lecteur est récupéré avec la propriété PlaybackSession.First, the MediaPlaybackSession object for the player is retrieved with the PlaybackSession property. Ensuite, la propriété Position est définie sur la position actuelle de lecture plus 10 secondes.Next the Position property is set to the current playback position plus 10 seconds.

private void _skipForwardButton_Click(object sender, RoutedEventArgs e)
{
    var session = mediaPlayer.PlaybackSession;
    session.Position = session.Position + TimeSpan.FromSeconds(10);
}

L’exemple suivant illustre l’utilisation d’un bouton bascule permettant de passer de la vitesse de lecture normale à la vitesse double, en définissant la propriété PlaybackRate de la session.The next example illustrates using a toggle button to toggle between normal playback speed and 2X speed by setting the PlaybackRate property of the session.

private void _speedToggleButton_Checked(object sender, RoutedEventArgs e)
{
    mediaPlayer.PlaybackSession.PlaybackRate = 2.0;
}
private void _speedToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
    mediaPlayer.PlaybackSession.PlaybackRate = 1.0;
}

À compter de Windows 10, version 1803, vous pouvez définir la rotation avec laquelle la vidéo est présentée dans le MediaPlayer par incréments de 90 degrés.Starting with Windows 10, version 1803, you can set the rotation with which video is presented in the MediaPlayer in increments of 90 degrees.

mediaPlayer.PlaybackSession.PlaybackRotation = MediaRotation.Clockwise90Degrees;

Détecter la mise en mémoire tampon attendue et inattendueDetect expected and unexpected buffering

L’objet MediaPlaybackSession décrit dans la section précédente fournit deux événements pour détecter la date de début et la fin de la mise en mémoire tampon des fichiers multimédias, BufferingStarted et BufferingEnded.The MediaPlaybackSession object described in the previous section provides two events for detecting when the currently playing media file begins and ends buffering, BufferingStarted and BufferingEnded. Cela vous permet de mettre à jour votre interface utilisateur pour indiquer à l’utilisateur que la mise en mémoire tampon se produit.This allows you to update your UI to show the user that buffering is occurring. La mise en mémoire tampon initiale est attendue lorsqu’un fichier multimédia est ouvert pour la première fois ou lorsque l’utilisateur bascule vers un nouvel élément dans une sélection.Initial buffering is expected when a media file is first opened or when the user switches to a new item in a playlist. Une mise en mémoire tampon inattendue peut se produire lorsque la vitesse du réseau est dégradée ou si le système de gestion de contenu qui fournit le contenu rencontre des problèmes techniques.Unexpected buffering can occur when the network speed degrades or if the content management system providing the content experiences technical issues. À partir de RS3, vous pouvez utiliser l’événement BufferingStarted pour déterminer si l’événement de mise en mémoire tampon est attendu ou s’il est inattendu et interrompt la lecture.Starting with RS3, you can use the BufferingStarted event to determine if the buffering event is expected or if it is unexpected and interrupting playback. Vous pouvez utiliser ces informations comme données de télémétrie pour votre application ou le service de distribution des médias.You can use this information as telemetry data for your app or media delivery service.

Inscrire des gestionnaires pour les événements BufferingStarted et BufferingEnded pour recevoir des notifications d’état de mise en mémoire tampon.Register handlers for the BufferingStarted and BufferingEnded events to receive buffering state notifications.

mediaPlayer.PlaybackSession.BufferingStarted += MediaPlaybackSession_BufferingStarted;
mediaPlayer.PlaybackSession.BufferingEnded += MediaPlaybackSession_BufferingEnded;

Dans le gestionnaire d’événements BufferingStarted , effectuez un cast des arguments d’événement passés dans l’événement vers un objet MediaPlaybackSessionBufferingStartedEventArgs et vérifiez la propriété IsPlaybackInterruption .In the BufferingStarted event handler, cast the event args passed into the event to a MediaPlaybackSessionBufferingStartedEventArgs object and check the IsPlaybackInterruption property. Si cette valeur est true, la mise en mémoire tampon qui a déclenché l’événement est inattendue et interrompt la lecture.If this value is true, the buffering that triggered the event is unexpected and interrupting playback. Dans le cas contraire, il s’agit d’une mise en mémoire tampon initiale attendue.Otherwise, it is expected initial buffering.

private void MediaPlaybackSession_BufferingStarted(MediaPlaybackSession sender, object args)
{
    MediaPlaybackSessionBufferingStartedEventArgs bufferingStartedEventArgs = args as MediaPlaybackSessionBufferingStartedEventArgs;
    if (bufferingStartedEventArgs != null && bufferingStartedEventArgs.IsPlaybackInterruption)
    {
        // update the playback quality telemetry report to indicate that
        // playback was interrupted
    }

    // update the UI to indicate that playback is buffering
}
private void MediaPlaybackSession_BufferingEnded(MediaPlaybackSession sender, object args)
{
    // update the UI to indicate that playback is no longer buffering
}

Pincement et zoom sur du contenu vidéoPinch and zoom video

MediaPlayer vous permet de spécifier le rectangle source au sein du contenu vidéo à afficher. Dès lors, vous pouvez effectuer un zoom dans la vidéo.MediaPlayer allows you to specify the source rectangle within video content that should be rendered, effectively allowing you to zoom into video. Le rectangle que vous spécifiez est relatif à un rectangle normalisé (0,0,1,1), où 0,0 correspond au coin supérieur gauche de l’image et 1,1 spécifie la largeur et la hauteur complètes de l’image.The rectangle you specify is relative to a normalized rectangle (0,0,1,1) where 0,0 is the upper left hand of the frame and 1,1 specifies the full width and height of the frame. Ainsi, par exemple, pour définir le rectangle de zoom de manière à afficher le quadrant supérieur droit de la vidéo, vous définiriez le rectangle (0,5 ; 0 ; 0,5 ; 0,5).So, for example, to set the zoom rectangle so that the top-right quadrant of the video is rendered, you would specify the rectangle (.5,0,.5,.5). Il est important que vous vérifiiez vos valeurs afin de vous assurer que votre rectangle source se trouve dans le rectangle normalisé (0,0,1,1).It is important that you check your values to make sure that your source rectangle is within the (0,0,1,1) normalized rectangle. Toute tentative de définition de la valeur en dehors de cette plage provoquera l’envoi d’une exception.Attempting to set a value outside of this range will cause an exception to be thrown.

Pour implémenter les fonctionnalités de pincement et de zoom à l’aide d’entrées tactiles multipoint, vous devez dans un premier temps spécifier les entrées prises en charge.To implement pinch and zoom using multi-touch gestures, you must first specify which gestures you want to support. Dans cet exemple, les entrées de mise à l’échelle et de translation sont demandées.In this example, scale and translate gestures are requested. L’événement ManipulationDelta est déclenché lorsque l’une des entrées enregistrées se produit.The ManipulationDelta event is raised when one of the subscribed gestures occurs. L’événement DoubleTapped sera utilisé pour réinitialiser le zoom sur l’image complète.The DoubleTapped event will be used to reset the zoom to the full frame.

_mediaPlayerElement.ManipulationMode = ManipulationModes.Scale | ManipulationModes.TranslateX | ManipulationModes.TranslateY;
_mediaPlayerElement.ManipulationDelta += _mediaPlayerElement_ManipulationDelta;
_mediaPlayerElement.DoubleTapped += _mediaPlayerElement_DoubleTapped;

Ensuite, déclarez un objet Rect qui stockera le rectangle source actuel de zoom.Next, declare a Rect object that will store the current zoom source rectangle.

Rect _sourceRect = new Rect(0, 0, 1, 1);

Le gestionnaire ManipulationDelta ajuste la mise à l’échelle ou la translation du rectangle de zoom.The ManipulationDelta handler adjusts either the scale or the translation of the zoom rectangle. Si la valeur delta de mise à l’échelle est différente de 1, cela signifie que l’utilisateur à effectuer un pincement.If the delta scale value is not 1, it means that the user performed a pinch gesture. Si la valeur est supérieure à 1, le rectangle source doit être réduit pour la prise en charge du zoom dans le contenu.If the value is greater than 1, the source rectangle should be made smaller to zoom into the content. Si la valeur est inférieure à 1, le rectangle source doit être agrandi pour effectuer un zoom arrière. Avant de définir les nouvelles valeurs de mise à l’échelle, le rectangle résultant est vérifié pour s’assurer qu’il se situe entièrement dans les limites (0, 0, 1, 1).If the value is less than 1, then the source rectangle should be made bigger to zoom out. Before setting the new scale values, the resulting rectangle is checked to make sure it lies entirely within the (0,0,1,1) limits.

Si la valeur de mise à l’échelle est 1, l’entrée de translation est traitée.If the scale value is 1, then the translation gesture is handled. Le rectangle est simplement translaté selon la division du nombre de pixels de l’entrée par la valeur de largeur et de hauteur du contrôle.The rectangle is simply translated by the number of pixels in gesture divided by the width and height of the control. Là encore, le rectangle obtenu est examiné afin de garantir qu’il s’intègre parfaitement dans les limites (0,0,1,1).Again, the resulting rectangle is checked to make sure it lies within the (0,0,1,1) bounds.

Enfin, l’élément NormalizedSourceRect de l’instance MediaPlaybackSession est défini sur le nouveau rectangle ajusté ; il spécifie la zone de la vidéo à afficher.Finally, the NormalizedSourceRect of the MediaPlaybackSession is set to the newly adjusted rectangle, specifying the area within the video frame that should be rendered.

private void _mediaPlayerElement_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{

    if (e.Delta.Scale != 1)
    {
        var halfWidth = _sourceRect.Width / 2;
        var halfHeight = _sourceRect.Height / 2;

        var centerX = _sourceRect.X + halfWidth;
        var centerY = _sourceRect.Y + halfHeight;

        var scale = e.Delta.Scale;
        var newHalfWidth = (_sourceRect.Width * e.Delta.Scale) / 2;
        var newHalfHeight = (_sourceRect.Height * e.Delta.Scale) / 2;

        if (centerX - newHalfWidth > 0 && centerX + newHalfWidth <= 1.0 &&
            centerY - newHalfHeight > 0 && centerY + newHalfHeight <= 1.0)
        {
            _sourceRect.X = centerX - newHalfWidth;
            _sourceRect.Y = centerY - newHalfHeight;
            _sourceRect.Width *= e.Delta.Scale;
            _sourceRect.Height *= e.Delta.Scale;
        }
    }
    else
    {
        var translateX = -1 * e.Delta.Translation.X / _mediaPlayerElement.ActualWidth;
        var translateY = -1 * e.Delta.Translation.Y / _mediaPlayerElement.ActualHeight;

        if (_sourceRect.X + translateX >= 0 && _sourceRect.X + _sourceRect.Width + translateX <= 1.0 &&
            _sourceRect.Y + translateY >= 0 && _sourceRect.Y + _sourceRect.Height + translateY <= 1.0)
        {
            _sourceRect.X += translateX;
            _sourceRect.Y += translateY;
        }
    }

    mediaPlayer.PlaybackSession.NormalizedSourceRect = _sourceRect;
}

Dans le gestionnaire d’événements DoubleTapped , le rectangle source est défini sur (0, 0, 1, 1) pour provoquer le rendu de la totalité de l’image vidéo.In the DoubleTapped event handler, the source rectangle is set back to (0,0,1,1) to cause the entire video frame to be rendered.

private void _mediaPlayerElement_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
    _sourceRect = new Rect(0, 0, 1, 1);
    mediaPlayer.PlaybackSession.NormalizedSourceRect = _sourceRect;
}

Remarque Cette section décrit les entrées tactiles.NOTE This section describes touch input. Le pavé tactile envoie des événements de pointeur et n’envoie pas d’événements de manipulation.Touchpad sends pointer events and will not send Manipulation events.

Gestion de la dégradation de la lecture basée sur des stratégiesHandling policy-based playback degradation

Dans certains cas, le système peut dégrader la lecture d’un élément multimédia, par exemple réduire la résolution (la restriction), en fonction d’une stratégie plutôt que d’un problème de performances.In some circumstances the system may degrade the playback of a media item, such as reducing the resolution (constriction), based on a policy rather than a performance issue. Par exemple, la vidéo peut être détériorée par le système si elle est lue à l’aide d’un pilote vidéo non signé.For example, video may be degraded by the system if it is being played using an unsigned video driver. Vous pouvez appeler MediaPlaybackSession. GetOutputDegradationPolicyState pour déterminer si et pourquoi cette dégradation basée sur une stratégie est en cours et avertir l’utilisateur ou enregistrer la raison de la télémétrie.You can call MediaPlaybackSession.GetOutputDegradationPolicyState to determine if and why this policy-based degredation is occurring and alert the user or record the reason for telemetry purposes.

L’exemple suivant montre une implémentation d’un gestionnaire pour l’événement MediaPlayer. MediaOpened qui est déclenché lorsque le joueur ouvre un nouvel élément multimédia.The following example shows an implementation of a handler for the MediaPlayer.MediaOpened event that is raised when the player opens a new media item. GetOutputDegradationPolicyState est appelé sur le MediaPlayer passé dans le gestionnaire.GetOutputDegradationPolicyState is called on the MediaPlayer passed into the handler. La valeur de VideoConstrictionReason indique la raison de la stratégie pour laquelle la vidéo est restreinte.The value of VideoConstrictionReason indicates the policy reason that the video is constricted. Si la valeur n’est pas None, cet exemple journalise la raison de la dégradation à des fins de télémétrie.If the value isn't None, this example logs the degradation reason for telemetry purposes. Cet exemple montre également comment définir le débit binaire de la AdaptiveMediaSource actuellement jouée sur la bande passante la plus basse pour enregistrer l’utilisation des données, car la vidéo est restreinte et ne s’affiche pas quand même à la haute résolution.This example also shows setting the bitrate of the AdaptiveMediaSource currently being played to the lowest bandwidth to save data usage, since the video is constricted and won't be displayed at high resolution anyway. Pour plus d’informations sur l’utilisation de AdaptiveMediaSource, consultez streaming adaptative.For more information on using AdaptiveMediaSource, see Adaptive streaming.

private void MediaPlayer_MediaOpened(MediaPlayer sender, object args)
{
    MediaPlaybackSessionOutputDegradationPolicyState info = sender.PlaybackSession.GetOutputDegradationPolicyState();

    if (info.VideoConstrictionReason != MediaPlaybackSessionVideoConstrictionReason.None)
    {
        // Switch to lowest bitrate to save bandwidth
        adaptiveMediaSource.DesiredMaxBitrate = adaptiveMediaSource.AvailableBitrates[0];

        // Log the degradation reason or show a message to the user
        System.Diagnostics.Debug.WriteLine("Logging constriction reason: " + info.VideoConstrictionReason);
    }
}

Utilisez MediaPlayerSurface afin d’afficher la vidéo sur une surface Windows.UI.CompositionUse MediaPlayerSurface to render video to a Windows.UI.Composition surface

À partir de Windows 10, version 1607, vous pouvez utiliser l’instance MediaPlayer afin d’afficher le contenu vidéo sur une interface ICompositionSurface, ce qui permet au lecteur d’intergir avec les API dans l’espace de noms Windows.UI.Composition.Starting with Windows 10, version 1607, you can use MediaPlayer to render video to an to render video to an ICompositionSurface, which allows the player to interoperate with the APIs in the Windows.UI.Composition namespace. L’infrastructure de composition peut être mise à profit pour travailler avec des graphiques dans la couche visuelle située entre les API XAML et les API graphiques DirectX de niveau inférieur.The composition framework allows you to work with graphics in the visual layer between XAML and the low-level DirectX graphics APIs. Cela permet la prise en charge de scénarios tels que le rendu de contenus vidéo dans tout contrôle XAML.This enables scenarios like rendering video into any XAML control. Pour plus d’informations sur l’utilisation des API de composition, consultez la page Couche visuelle.For more information on using the composition APIs, see Visual Layer.

L’exemple suivant illustre l’affichage d’un contenu de lecteur vidéo sur un contrôle Canvas.The following example illustrates how to render video player content onto a Canvas control. Les appels spécifiques au lecteur multimédias de cet exemple sont SetSurfaceSize et GetSurface.The media player-specific calls in this example are SetSurfaceSize and GetSurface. SetSurfaceSize indique au système la talle de la mémoire tampon à allouer pour l’affichage du contenu.SetSurfaceSize tells the system the size of the buffer that should be allocated for rendering content. GetSurface prend un élément Compositor en tant qu’argument et récupère une instance de la classe MediaPlayerSurface.GetSurface takes a Compositor as an arguemnt and retreives an instance of the MediaPlayerSurface class. Cette classe procure un accès aux éléments MediaPlayer et Compositor utilisés pour créer la surface et l’expose via la propriété CompositionSurface.This class provides access to the MediaPlayer and Compositor used to create the surface and exposes the surface itself through the CompositionSurface property.

Le reste du code de cet exemple crée un SpriteVisual dans lequel la vidéo est rendue et définit la taille de l’élément Canvas qui affichera l’élément visuel.The rest of the code in this example creates a SpriteVisual to which the video is rendered and sets the size to the size of the canvas element that will display the visual. Ensuite, un élément CompositionBrush est créé à partir de la classe MediaPlayerSurface et affecté à la propriété Brush des éléments visuels.Next a CompositionBrush is created from the MediaPlayerSurface and assigned to the Brush property of the visual. À ce stade, un élément ContainerVisual est créé et l’instance SpriteVisual est insérée dans la partie supérieure de son arborescence visuelle.Next a ContainerVisual is created and the SpriteVisual is inserted at the top of its visual tree. Enfin, SetElementChildVisual est appelé afin d’affecter les éléments visuels du conteneur au contrôle Canvas.Finally, SetElementChildVisual is called to assign the container visual to the Canvas.

mediaPlayer.SetSurfaceSize(new Size(_compositionCanvas.ActualWidth, _compositionCanvas.ActualHeight));

var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
MediaPlayerSurface surface = mediaPlayer.GetSurface(compositor);

SpriteVisual spriteVisual = compositor.CreateSpriteVisual();
spriteVisual.Size =
    new System.Numerics.Vector2((float)_compositionCanvas.ActualWidth, (float)_compositionCanvas.ActualHeight);

CompositionBrush brush = compositor.CreateSurfaceBrush(surface.CompositionSurface);
spriteVisual.Brush = brush;

ContainerVisual container = compositor.CreateContainerVisual();
container.Children.InsertAtTop(spriteVisual);

ElementCompositionPreview.SetElementChildVisual(_compositionCanvas, container);

Utilisez MediaTimelineController afin de synchroniser du contenu entre plusieurs couches.Use MediaTimelineController to synchronize content across multiple players.

Comme indiqué précédemment dans cet article, vous application peut disposer de plusieurs objets MediaPlayer actifs simultanément.As discussed previously in this article, your app can have several MediaPlayer objects active at a time. Par défaut, chaque instance MediaPlayer créée fonctionne indépendamment.By default, each MediaPlayer you create operates independently. Pour certains scénarios, tels que la synchronisation d’une piste de commentaires sur une vidéo, vous voudrez synchroniser l’état du lecteur, la position de lecture et la vitesse de lecture de plusieurs couches.For some scenarios, such as synchronizing a commentary track to a video, you may want to synchronize the player state, playback position, and playback speed of multiple players. À partir de Windows 10, version 1607, vous pouvez implémenter ce comportement à l’aide de la classe MediaTimelineController.Starting with Windows 10, version 1607, you can implement this behavior by using the MediaTimelineController class.

Implémenter des contrôles de lectureImplement playback controls

L’exemple suivant vous explique l’utilisation d’une classe MediaTimelineController pour contrôler deux instances de MediaPlayer.The following example shows how to use a MediaTimelineController to control two instances of MediaPlayer. Tout d’abord, chaque instance de MediaPlayer est instanciée et l’objet Source est défini sur un fichier multimédia.First, each instance of the MediaPlayer is instantiated and the Source is set to a media file. Ensuite, une nouvelle classe MediaTimelineController est créée.Next, a new MediaTimelineController is created. Pour chaque instance MediaPlayer, la classe MediaPlaybackCommandManager associée à chaque lecteur est désactivée par la définition de la propriété IsEnabled sur False.For each MediaPlayer, the MediaPlaybackCommandManager associated with each player is disabled by setting the IsEnabled property to false. La propriété TimelineController est ensuite définie sur l’objet contrôleur de chronologie.And then the TimelineController property is set to the timeline controller object.

MediaTimelineController _mediaTimelineController;
mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
_mediaPlayerElement.SetMediaPlayer(mediaPlayer);


_mediaPlayer2 = new MediaPlayer();
_mediaPlayer2.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video_2.mkv"));
_mediaPlayerElement2.SetMediaPlayer(_mediaPlayer2);

_mediaTimelineController = new MediaTimelineController();

mediaPlayer.CommandManager.IsEnabled = false;
mediaPlayer.TimelineController = _mediaTimelineController;

_mediaPlayer2.CommandManager.IsEnabled = false;
_mediaPlayer2.TimelineController = _mediaTimelineController;

Attention La classe MediaPlaybackCommandManager procure une intégration automatique entre MediaPlayer et les contrôles de transport de média système, mais cette intégration automatique ne peut pas être utilisée avec des lecteurs multimédias contrôlés avec une classe MediaTimelineController.Caution The MediaPlaybackCommandManager provides automatic integration between MediaPlayer and the System Media Transport Controls (SMTC), but this automatic integration can't be used with media players that are controlled with a MediaTimelineController. Par conséquent, vous devez désactiver le gestionnaire de commande du lecteur multimédia avant de définir son contrôleur de chronologie.Therefore you must disable the command manager for the media player before setting the player's timeline controller. À défaut, une exception sera transmise avec un message vous informant du blocage de l’association du contrôleur de chronologie de médias en raison de l’état actuel de l’objet.Failure to do so will result in an exception being thrown with the following message: "Attaching Media Timeline Controller is blocked because of the current state of the object." Pour plus d’informations sur l’intégration des lecteurs multimédias avec les contrôles de transport de média système, consultez la page Intégrer avec les contrôles de transport de média système.For more information on media player integration with the SMTC, see Integrate with the System Media Transport Controls. Si vous utilisez une classe MediaTimelineController, vous pouvez toujours contrôler manuellement les contrôles de transport de média système.If you are using a MediaTimelineController you can still control the SMTC manually. Pour plus d’informations, consultez la page Contrôles de transport de média système.For more information, see Manual control of the System Media Transport Controls.

Une fois que vous avez associé une classe MediaTimelineController à un ou plusieurs lecteurs multimédias, vous pouvez contrôler l’état de lecture à l’aide des méthodes exposées par le contrôleur.Once you have attached a MediaTimelineController to one or more media players, you can control the playback state by using the methods exposed by the controller. L’exemple suivant appelle Start pour commencer à lire tous les lecteurs multimédias associés au début du support.The following example calls Start to begin playback of all associated media players at the beginning of the media.

private void PlayButton_Click(object sender, RoutedEventArgs e)
{
    _mediaTimelineController.Start();
}

Cet exemple illustre l’interruption et la reprise de la lecture sur l’ensemble des lecteurs multimédias associés.This example illustrates pausing and resuming all of the attached media players.

private void PauseButton_Click(object sender, RoutedEventArgs e)
{
    if(_mediaTimelineController.State == MediaTimelineControllerState.Running)
    {
        _mediaTimelineController.Pause();
        _pauseButton.Content = "Resume";
    }
    else
    {
        _mediaTimelineController.Resume();
        _pauseButton.Content = "Pause";
    }
}

Pour définir l’avance rapide sur l’ensemble des lecteurs multimédias connectés, définissez la vitesse de lecture sur une valeur supérieure à 1.To fast-forward all connected media players, set the playback speed to a value greater that 1.

private void FastForwardButton_Click(object sender, RoutedEventArgs e)
{
    _mediaTimelineController.ClockRate = 2.0;
}

L’exemple suivant illustre l’utilisation d’un contrôle Slider afin d’afficher la position de lecture actuelle du contrôleur de chronologie par rapport à la durée du contenu sur l’un des lecteurs multimédias associés.The next example shows how to use a Slider control to show the current playback position of the timeline controller relative to the duration of the content of one of the connected media players. Tout d’abord, un nouvel élément MediaSource est créé et un gestionnaire est enregistré pour l’événement OpenOperationCompleted de la source multimédia.First, a new MediaSource is created and a handler for the OpenOperationCompleted of the media source is registered.

var mediaSource = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaSource.OpenOperationCompleted += MediaSource_OpenOperationCompleted;
mediaPlayer.Source = mediaSource;
_mediaPlayerElement.SetMediaPlayer(mediaPlayer);

Le gestionnaire OpenOperationCompleted est utilisé en tant qu’opportunité de découverte de la durée du contenu de la source multimédia.The OpenOperationCompleted handler is used as an opportunity to discover the duration of the media source content. Une fois que la durée est déterminée, la valeur maximale du contrôle Slider est définie sur le nombre total de secondes de l’élément multimédia.Once the duration is determined, the maximum value of the Slider control is set to the total number of seconds of the media item. La valeur est définie au sein d’un appel à RunAsync, afin de garantir l’exécution sur le thread d’interface utilisateur.The value is set inside a call to RunAsync to make sure it is run on the UI thread.

TimeSpan _duration;
private async void MediaSource_OpenOperationCompleted(MediaSource sender, MediaSourceOpenOperationCompletedEventArgs args)
{
    _duration = sender.Duration.GetValueOrDefault();

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        _positionSlider.Minimum = 0;
        _positionSlider.Maximum = _duration.TotalSeconds;
        _positionSlider.StepFrequency = 1;
    }); 
}

Ensuite, un gestionnaire pour l’événement PositionChanged du contrôleur de chronologie est enregistré.Next, a handler for the timeline controller's PositionChanged event is registered. L’appel est effectué régulièrement par le système, environ 4 fois par seconde.This is called periodically by the system, approximately 4 times per second.

_mediaTimelineController.PositionChanged += _mediaTimelineController_PositionChanged;

Dans le gestionnaire de PositionChanged, la valeur Slider est mise à jour en fonction de la position actuelle du contrôleur de chronologie.In the handler for PositionChanged, the slider value is updated to reflect the current position of the timeline controller.

private async void _mediaTimelineController_PositionChanged(MediaTimelineController sender, object args)
{
    if (_duration != TimeSpan.Zero)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            _positionSlider.Value = sender.Position.TotalSeconds / (float)_duration.TotalSeconds;
        });
    }
}

Décaler la position de lecture de la position de la chronologieOffset the playback position from the timeline position

Dans certains cas, il est possible que vous vouliez décaler la position de lecture d’un ou de plusieurs lecteurs multimédias des autres lecteurs.In some cases you may want the playback position of one or more media players associated with a timeline controller to be offset from the other players. Pour ce faire, définissez la propriété TimelineControllerPositionOffset de l’objet MediaPlayer que vous voulez décaler.You can do this by setting the TimelineControllerPositionOffset property of the MediaPlayer object you want to be offset. L’exemple suivant utilise les durées du contenu de deux lecteurs multimédias pour définir les valeurs minimum et maximum du contrôle à deux curseurs sur « plus » ou « moins » la longueur de l’élément.The following example uses the durations of the content of two media players to set the minimum and maximum values of two slider control to plus and minus the length of the item.

_timelineOffsetSlider1.Minimum = -1 * _duration.TotalSeconds;
_timelineOffsetSlider1.Maximum = _duration.TotalSeconds;
_timelineOffsetSlider1.StepFrequency = 1;

_timelineOffsetSlider2.Minimum = -1 * _duration2.TotalSeconds;
_timelineOffsetSlider2.Maximum = _duration2.TotalSeconds;
_timelineOffsetSlider2.StepFrequency = 1;

Dans l’événement ValueChanged associé à chaque curseur, la propriété TimelineControllerPositionOffset de chaque lecteur est définie sur la valeur correspondante.In the ValueChanged event for each slider, the TimelineControllerPositionOffset for each player is set to the corresponding value.

private void _timelineOffsetSlider1_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
    mediaPlayer.TimelineControllerPositionOffset = TimeSpan.FromSeconds(_timelineOffsetSlider1.Value);
}

private void _timelineOffsetSlider2_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
    _mediaPlayer2.TimelineControllerPositionOffset = TimeSpan.FromSeconds(_timelineOffsetSlider2.Value);
}

Notez que si la valeur de décalage d’un lecteur correspond à une position de lecture négative, le contenu demeure interrompu jusqu’à ce que le décalage atteigne la valeur de 0, puis la lecture redémarre.Note that if the offset value of a player maps to a negative playback position, the clip will remain paused until the offset reaches zero and then playback will begin. De la même manière, si la valeur de décalage correspond à une position de lecture supérieure à la durée de l’élément multimédia, l’image finale s’affiche, comme cela se produit à la fin de la lecture du contenu d’un lecteur multimédia.Likewise, if the offset value maps to a playback position greater than the duration of the media item, the final frame will be shown, just as it does when a single media player reached the end of its content.

Lire une vidéo sphérique avec MediaPlayerPlay spherical video with MediaPlayer

À compter de Windows 10, la version 1703, MediaPlayer prend en charge la projection équirectangulaire pour la lecture de vidéos sphériques.Starting with Windows 10, version 1703, MediaPlayer supports equirectangular projection for spherical video playback. Le contenu vidéo sphérique n’est pas différent de la vidéo ordinaire et plate dans la mesure où le MediaPlayer affiche la vidéo tant que l’encodage vidéo est pris en charge.Spherical video content is no different from regular, flat video in that MediaPlayer will render the video as long as the video encoding is supported. Pour une vidéo sphérique qui contient une balise de métadonnées qui spécifie que la vidéo utilise la projection équirectangulaire, MediaPlayer peut afficher la vidéo à l’aide d’une orientation de champ et d’affichage spécifiée.For spherical video that contains a metadata tag that specifies that the video uses equirectangular projection, MediaPlayer can render the video using a specified field-of-view and view orientation. Cela permet des scénarios tels que la lecture vidéo de la réalité virtuelle avec un affichage monté en tête ou simplement la possibilité pour l’utilisateur de se déplacer dans le contenu vidéo sphérique à l’aide de la souris ou du clavier.This enables scenarios such as virtual reality video playback with a head-mounted display or simply allowing the user to pan around within spherical video content using the mouse or keyboard input.

Pour lire une vidéo sphérique, suivez les étapes de lecture du contenu vidéo décrit précédemment dans cet article.To play back spherical video, use the steps for playing back video content described previously in this article. La première étape consiste à inscrire un gestionnaire pour l’événement MediaPlayer. MediaOpened .The one additional step is to register a handler for the MediaPlayer.MediaOpened event. Cet événement vous donne la possibilité d’activer et de contrôler les paramètres de lecture de la vidéo sphérique.This event gives you an opportunity to enable and control the spherical video playback parameters.

mediaPlayer = new MediaPlayer();
mediaPlayer.MediaOpened += _mediaPlayer_MediaOpened;
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video_spherical.mp4"));
_mediaPlayerElement.SetMediaPlayer(mediaPlayer);
mediaPlayer.Play();

Dans le gestionnaire MediaOpened , vérifiez tout d’abord le format de cadre de l’élément multimédia qui vient d’être ouvert en vérifiant la propriété PlaybackSession. SphericalVideoProjection. FrameFormat .In the MediaOpened handler, first check the frame format of the newly opened media item by checking the PlaybackSession.SphericalVideoProjection.FrameFormat property. Si cette valeur est SphericaVideoFrameFormat. équirectangulaire, le système peut automatiquement projeter le contenu vidéo.If this value is SphericaVideoFrameFormat.Equirectangular, then the system can automatically project the video content. Tout d’abord, définissez la propriété PlaybackSession. SphericalVideoProjection. IsEnabled sur true.First, set the PlaybackSession.SphericalVideoProjection.IsEnabled property to true. Vous pouvez également ajuster des propriétés telles que l’orientation de l’affichage et le champ de vue que le lecteur multimédia utilisera pour projeter le contenu vidéo.You can also adjust properties such as the view orientation and field of view that the media player will use to project the video content. Dans cet exemple, le champ de la vue est défini sur une valeur étendue de 120 degrés en définissant la propriété HorizontalFieldOfViewInDegrees .In this example, the field of view is set to a wide value of 120 degrees by setting the HorizontalFieldOfViewInDegrees property.

Si le contenu de la vidéo est sphérique, mais est dans un format autre que équirectangulaire, vous pouvez implémenter votre propre algorithme de projection à l’aide du mode serveur de frames du lecteur multimédia pour recevoir et traiter des frames individuels.If the video content is spherical, but is in a format other than equirectangular, you can implement your own projection algorithm using the media player's frame server mode to receive and process individual frames.

private void _mediaPlayer_MediaOpened(MediaPlayer sender, object args)
{
    if (sender.PlaybackSession.SphericalVideoProjection.FrameFormat == SphericalVideoFrameFormat.Equirectangular)
    {
        sender.PlaybackSession.SphericalVideoProjection.IsEnabled = true;
        sender.PlaybackSession.SphericalVideoProjection.HorizontalFieldOfViewInDegrees = 120;

    }
    else if (sender.PlaybackSession.SphericalVideoProjection.FrameFormat == SphericalVideoFrameFormat.Unsupported)
    {
        // If the spherical format is unsupported, you can use frame server mode to implement a custom projection
    }
}

L’exemple de code suivant montre comment ajuster l’orientation de l’affichage vidéo sphérique à l’aide des touches de direction gauche et droite.The following example code illustrates how to adjust the spherical video view orientation using the left and right arrow keys.

protected override void OnKeyDown(KeyRoutedEventArgs e)
{
    if (mediaPlayer.PlaybackSession.SphericalVideoProjection.FrameFormat != SphericalVideoFrameFormat.Equirectangular)
    {
        return;
    }

    switch (e.Key)
    {
        case Windows.System.VirtualKey.Right:
            mediaPlayer.PlaybackSession.SphericalVideoProjection.ViewOrientation *= Quaternion.CreateFromYawPitchRoll(.1f, 0, 0);
            break;
        case Windows.System.VirtualKey.Left:
            mediaPlayer.PlaybackSession.SphericalVideoProjection.ViewOrientation *= Quaternion.CreateFromYawPitchRoll(-.1f, 0, 0);
            break;
    }
}

Si votre application prend en charge les sélections de vidéos, vous souhaiterez peut-être identifier les éléments de lecture qui contiennent une vidéo sphérique dans votre interface utilisateur.If your app supports playlists of video, you may want to identify playback items that contain spherical video in your UI. Les sélections multimédias sont décrites en détail dans l’article, les éléments multimédias, les sélections et les pistes.Media playlists are discussed in detail in the article, Media items, playlists, and tracks. L’exemple suivant illustre la création d’une nouvelle sélection, l’ajout d’un élément et l’inscription d’un gestionnaire pour l’événement MediaPlaybackItem. VideoTracksChanged , qui se produit lorsque les pistes vidéo d’un élément multimédia sont résolues.The following example shows creating a new playlist, adding an item, and registering a handler for the MediaPlaybackItem.VideoTracksChanged event, which occurs when the video tracks for a media item are resolved.

var playbackList = new MediaPlaybackList();
var item = new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/RIFTCOASTER HD_injected.mp4")));
item.VideoTracksChanged += Item_VideoTracksChanged;
playbackList.Items.Add(item);
mediaPlayer.Source = playbackList;

Dans le gestionnaire d’événements VideoTracksChanged , récupérez les propriétés d’encodage des pistes vidéo ajoutées en appelant VideoTrack. GetEncodingProperties.In the VideoTracksChanged event handler, get the encoding properties for any added video tracks by calling VideoTrack.GetEncodingProperties. Si la valeur de la propriété SphericalVideoFrameFormat des propriétés d’encodage est différente de SphericaVideoFrameFormat. None, la piste vidéo contient une vidéo sphérique et vous pouvez mettre à jour votre interface utilisateur en conséquence si vous le souhaitez.If the SphericalVideoFrameFormat property of the encoding properties is a value other than SphericaVideoFrameFormat.None, then the video track contains spherical video and you can update your UI accordingly if you choose.

private void Item_VideoTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    if (args.CollectionChange != CollectionChange.ItemInserted)
    {
        return;
    }
    foreach (var videoTrack in sender.VideoTracks)
    {
        if (videoTrack.GetEncodingProperties().SphericalVideoFrameFormat != SphericalVideoFrameFormat.None)
        {
            // Optionally indicate in the UI that this item contains spherical video
        }
    }
}

Utiliser MediaPlayer en mode de serveur de framesUse MediaPlayer in frame server mode

À compter de Windows 10, version 1703, vous pouvez utiliser MediaPlayer en mode de serveur de trame.Starting with Windows 10, version 1703, you can use MediaPlayer in frame server mode. Dans ce mode, le MediaPlayer ne rend pas automatiquement les frames à un MediaPlayerElementassocié.In this mode, the MediaPlayer does not automatically render frames to an associated MediaPlayerElement. Au lieu de cela, votre application copie le frame actuel du MediaPlayer vers un objet qui implémente IDirect3DSurface.Instead, your app copies the current frame from the MediaPlayer to an object that implements IDirect3DSurface. Le scénario principal que cette fonctionnalité permet d’utiliser utilise des nuanceurs de pixels pour traiter les trames vidéo fournies par le MediaPlayer.The primary scenario this feature enables is using pixel shaders to process video frames provided by the MediaPlayer. Votre application est chargée d’afficher chaque frame après son traitement, par exemple en affichant le frame dans un contrôle d' image XAML.Your app is responsible for displaying each frame after processing, such as by showing the frame in a XAML Image control.

Dans l’exemple suivant, un nouveau MediaPlayer est initialisé et le contenu vidéo est chargé.In the following example, a new MediaPlayer is initialized and video content is loaded. Ensuite, un gestionnaire pour VideoFrameAvailable est inscrit.Next, a handler for VideoFrameAvailable is registered. Le mode de serveur de frames est activé en affectant à la propriété IsVideoFrameServerEnabled de l’objet MediaPlayer la valeur true.Frame server mode is enabled by setting the MediaPlayer object's IsVideoFrameServerEnabled property to true. Enfin, la lecture du média démarre avec un appel à Play.Finally, media playback is started with a call to Play.

mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer.VideoFrameAvailable += mediaPlayer_VideoFrameAvailable;
mediaPlayer.IsVideoFrameServerEnabled = true;
mediaPlayer.Play();

L’exemple suivant montre un gestionnaire pour VideoFrameAvailable qui utilise Win2D pour ajouter un effet de flou simple à chaque image d’une vidéo, puis affiche les frames traités dans un contrôle image XAML.The next example shows a handler for VideoFrameAvailable that uses Win2D to add a simple blur effect to each frame of a video and then displays the processed frames in a XAML Image control.

Chaque fois que le gestionnaire VideoFrameAvailable est appelé, la méthode CopyFrameToVideoSurface est utilisée pour copier le contenu du frame dans un IDirect3DSurface.Whenever the VideoFrameAvailable handler is called, the CopyFrameToVideoSurface method is used to copy the contents of the frame to an IDirect3DSurface. Vous pouvez également utiliser CopyFrameToStereoscopicVideoSurfaces pour copier le contenu 3D dans deux surfaces, pour traiter le contenu de l’œil gauche et du bon œil séparément.You can also use CopyFrameToStereoscopicVideoSurfaces to copy 3D content into two surfaces, for processing the left eye and right eye content separately. Pour obtenir un objet qui implémente IDirect3DSurface , cet exemple crée un SoftwareBitmap , puis utilise cet objet pour créer un CanvasBitmapWin2D, qui implémente l’interface nécessaire.To get an object that implements IDirect3DSurface this example creates a SoftwareBitmap and then uses that object to create a Win2D CanvasBitmap, which implements the necessary interface. Un CanvasImageSource est un objet Win2D qui peut être utilisé comme source pour un contrôle image . un nouveau est créé et défini en tant que source de l' image dans laquelle le contenu doit être affiché.A CanvasImageSource is a Win2D object that can be used as the source for an Image control, so a new one is created and set as the source for the Image in which the content will be displayed. Ensuite, un CanvasDrawingSession est créé.Next, a CanvasDrawingSession is created. Utilisé par Win2D pour restituer l’effet de flou.This is used by Win2D to render the blur effect.

Une fois que tous les objets nécessaires ont été instanciés, CopyFrameToVideoSurface est appelé, ce qui copie le frame actuel à partir du MediaPlayer dans le CanvasBitmap.Once all of the necessary objects have been instantiated, CopyFrameToVideoSurface is called, which copies the current frame from the MediaPlayer into the CanvasBitmap. Ensuite, un GaussianBlurEffect Win2D est créé, avec le CanvasBitmap défini comme source de l’opération.Next, a Win2D GaussianBlurEffect is created, with the CanvasBitmap set as the source of the operation. Enfin, CanvasDrawingSession. DrawImage est appelé pour dessiner l’image source, avec l’effet de flou appliqué, dans le CanvasImageSource qui a été associé au contrôle image , provoquant son dessin dans l’interface utilisateur.Finally, CanvasDrawingSession.DrawImage is called to draw the source image, with the blur effect applied, into the CanvasImageSource that has been associated with Image control, causing it to be drawn in the UI.

private async void mediaPlayer_VideoFrameAvailable(MediaPlayer sender, object args)
{
    CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        if(frameServerDest == null)
        {
            // FrameServerImage in this example is a XAML image control
            frameServerDest = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)FrameServerImage.Width, (int)FrameServerImage.Height, BitmapAlphaMode.Ignore);
        }
        if(canvasImageSource == null)
        {
            canvasImageSource = new CanvasImageSource(canvasDevice, (int)FrameServerImage.Width, (int)FrameServerImage.Height, DisplayInformation.GetForCurrentView().LogicalDpi);//96); 
            FrameServerImage.Source = canvasImageSource;
        }

        using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, frameServerDest))
        using (CanvasDrawingSession ds = canvasImageSource.CreateDrawingSession(Windows.UI.Colors.Black))
        {

            mediaPlayer.CopyFrameToVideoSurface(inputBitmap);

            var gaussianBlurEffect = new GaussianBlurEffect
            {
                Source = inputBitmap,
                BlurAmount = 5f,
                Optimization = EffectOptimization.Speed
            };

            ds.DrawImage(gaussianBlurEffect);

        }
    });
}

private void FrameServerSubtitlesButton_Click(object sender, RoutedEventArgs e)
{

    mediaPlayer = new MediaPlayer();
    var source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
    var item = new MediaPlaybackItem(source);

    item.TimedMetadataTracksChanged += Item_TimedMetadataTracksChanged;


    mediaPlayer.Source = item;
    mediaPlayer.VideoFrameAvailable += mediaPlayer_VideoFrameAvailable_Subtitle;
    mediaPlayer.IsVideoFrameServerEnabled = true;
    mediaPlayer.Play();

    mediaPlayer.IsMuted = true;

}

private void Item_TimedMetadataTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    if(sender.TimedMetadataTracks.Count > 0)
    {
        sender.TimedMetadataTracks.SetPresentationMode(0, TimedMetadataTrackPresentationMode.PlatformPresented);
    }
}

private async void mediaPlayer_VideoFrameAvailable_Subtitle(MediaPlayer sender, object args)
{
    CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        if (frameServerDest == null)
        {
            // FrameServerImage in this example is a XAML image control
            frameServerDest = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)FrameServerImage.Width, (int)FrameServerImage.Height, BitmapAlphaMode.Ignore);
        }
        if (canvasImageSource == null)
        {
            canvasImageSource = new CanvasImageSource(canvasDevice, (int)FrameServerImage.Width, (int)FrameServerImage.Height, DisplayInformation.GetForCurrentView().LogicalDpi);//96); 
            FrameServerImage.Source = canvasImageSource;
        }

        using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, frameServerDest))
        {
            using (CanvasDrawingSession ds = canvasImageSource.CreateDrawingSession(Windows.UI.Colors.Black))
            {

                mediaPlayer.CopyFrameToVideoSurface(inputBitmap);

                //Rect subtitleTargetRect = new Rect(0, 0, inputBitmap.Bounds.Width, inputBitmap.Bounds.Bottom * .1);
                Rect subtitleTargetRect = new Rect(0, 0, 100, 100);

                mediaPlayer.RenderSubtitlesToSurface(inputBitmap);//, subtitleTargetRect);

                //var gaussianBlurEffect = new GaussianBlurEffect
                //{
                //    Source = inputBitmap,
                //    BlurAmount = 5f,
                //    Optimization = EffectOptimization.Speed
                //};

                //ds.DrawImage(gaussianBlurEffect);

                ds.DrawImage(inputBitmap);
            }
        }
    });
}

Pour plus d’informations sur Win2D, consultez le référentiel GitHub Win2D.For more information on Win2D, see the Win2D GitHub repository. Pour tester l’exemple de code indiqué ci-dessus, vous devez ajouter le package NuGet Win2D à votre projet en suivant les instructions ci-dessous.To try out the sample code shown above, you will need to add the Win2D NuGet package to your project with the following instructions.

Pour ajouter le package NuGet Win2D à votre projet d’effetTo add the Win2D NuGet package to your effect project

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Gérer les packages NuGet.In Solution Explorer, right-click your project and select Manage NuGet Packages.
  2. En haut de la fenêtre, sélectionnez l’onglet Explorer.At the top of the window, select the Browse tab.
  3. Dans la zone de recherche, entrez Win2D.In the search box, enter Win2D.
  4. Sélectionnez Win2D.uwp, puis Installer dans le volet droit.Select Win2D.uwp, and then select Install in the right pane.
  5. La boîte de dialogue Examiner les modifications vous indique le package à installer.The Review Changes dialog shows you the package to be installed. Cliquez sur OK.Click OK.
  6. Acceptez la licence de package.Accept the package license.

Détecter les modifications de niveau audio et y répondre par le systèmeDetect and respond to audio level changes by the system

À compter de Windows 10, version 1803, votre application peut détecter si le système diminue ou diminue le niveau audio d’un MediaPlayeren cours de lecture.Starting with Windows 10, version 1803, your app can detect when the system lowers or mutes the audio level of a currently playing MediaPlayer. Par exemple, le système peut réduire, ou « canard », le niveau de lecture audio lors de la sonnerie d’une alarme.For example, the system may lower, or "duck", the audio playback level when an alarm is ringing. Le système désactive votre application lorsqu’elle passe en arrière-plan si votre application n’a pas déclaré la fonctionnalité backgroundMediaPlayback dans le manifeste de l’application.The system will mute your app when it goes into the background if your app has not declared the backgroundMediaPlayback capability in the app manifest. La classe AudioStateMonitor vous permet de vous inscrire pour recevoir un événement lorsque le système modifie le volume d’un flux audio.The AudioStateMonitor class allows you to register to receive an event when the system modifies the volume of an audio stream. Accédez à la propriété AudioStateMonitor d’un MediaPlayer et enregistrez un gestionnaire pour l’événement SoundLevelChanged à notifier lorsque le niveau audio de ce MediaPlayer est modifié par le système.Access the AudioStateMonitor property of a MediaPlayer and register a handler for the SoundLevelChanged event to be notified when the audio level for that MediaPlayer is changed by the system.

mediaPlayer.AudioStateMonitor.SoundLevelChanged += AudioStateMonitor_SoundLevelChanged;

Lors du traitement de l’événement SoundLevelChanged , vous pouvez effectuer différentes actions en fonction du type de contenu en cours de lecture.When handling the SoundLevelChanged event, you may take different actions depending on the type of content being played. Si vous jouez actuellement de la musique, vous souhaiterez peut-être laisser la musique continuer à jouer pendant que le volume est présent.If you are currently playing music, then you may want to let the music continue to play while the volume is ducked. Toutefois, si vous jouez à un podcast, vous souhaiterez probablement suspendre la lecture pendant que l’audio est mis en place, de sorte que l’utilisateur n’a pas de contenu.If you are playing a podcast, however, you likely want to pause playback while the audio is ducked so the user doesn't miss any of the content.

Cet exemple déclare une variable pour suivre si le contenu en cours de création est un podcast, il est supposé que vous définissez cette valeur sur la valeur appropriée lors de la sélection du contenu pour le MediaPlayer.This example declares a variable to track whether the currently playing content is a podcast, it is assumed that you set this to the appropriate value when selecting the content for the MediaPlayer. Nous créons également une variable de classe pour effectuer le suivi lorsque la lecture est suspendue par programmation lorsque le niveau audio change.We also create a class variable to track when we pause playback programmatically when the audio level changes.

bool isPodcast;
bool isPausedDueToAudioStateMonitor;

Dans le gestionnaire d’événements SoundLevelChanged , vérifiez la propriété SoundLevel de l’expéditeur AudioStateMonitor pour déterminer le nouveau niveau sonore.In the SoundLevelChanged event handler, check the SoundLevel property of the AudioStateMonitor sender to determine the new sound level. Cet exemple vérifie si le nouveau niveau de son est Full Volume, ce qui signifie que le système a cessé de fonctionner en sourdine ou qu’il est en train de le faire, ou si le niveau sonore a été abaissé mais qu’il s’agit d’un contenu qui n’est pas un podcast.This example checks to see if the new sound level is full volume, meaning the system has stopped muting or ducking the volume, or if the sound level has been lowered but is playing non-podcast content. Si l’une ou l’autre est vraie et que le contenu a été mis en pause par programme, la lecture est reprise.If either of these are true and the content was previously paused programmatically, playback is resumed. Si le nouveau niveau audio est muet ou si le contenu actuel est un podcast et que le niveau sonore est faible, la lecture est suspendue et la variable est définie pour assurer le suivi de l’initialisation de la pause par programmation.If the new sound level is muted or if the current content is a podcast and the sound level is low, playback is paused, and the variable is set to track that the pause was initiated programatically.

private void AudioStateMonitor_SoundLevelChanged(Windows.Media.Audio.AudioStateMonitor sender, object args)
{
    if ((sender.SoundLevel == SoundLevel.Full) || (sender.SoundLevel == SoundLevel.Low && !isPodcast))
    {
        if (isPausedDueToAudioStateMonitor)
        {
            mediaPlayer.Play();
            isPausedDueToAudioStateMonitor = false;
        }
    }
    else if ((sender.SoundLevel == SoundLevel.Muted) ||
         (sender.SoundLevel == SoundLevel.Low && isPodcast))
    {
        if (mediaPlayer.PlaybackSession.PlaybackState == MediaPlaybackState.Playing)
        {
            mediaPlayer.Pause();
            isPausedDueToAudioStateMonitor = true;
        }
    }

}

L’utilisateur peut décider qu’il souhaite suspendre ou continuer la lecture, même si l’audio est mis en place par le système.The user may decide that they want to pause or continue playback, even if the audio is ducked by the system. Cet exemple montre les gestionnaires d’événements pour un bouton de lecture et d’interruption.This example shows event handlers for a play and a pause button. Dans le bouton suspendre, le gestionnaire de clic est suspendu, si la lecture avait déjà été suspendue par programme, nous mettons à jour la variable pour indiquer que l’utilisateur a suspendu le contenu.In the pause button click handler is paused, if playback had already been paused programmatically, then we update the variable to indicate that the user has paused the content. Dans le gestionnaire de clic de clic sur le bouton de lecture, nous reprenons la lecture et effacons notre variable de suivi.In the play button click handler, we resume playback and clear our tracking variable.

private void PauseButton_User_Click(object sender, RoutedEventArgs e)
{
    if (isPausedDueToAudioStateMonitor)
    {
        isPausedDueToAudioStateMonitor = false;
    }
    else
    {
        mediaPlayer.Pause();
    }
}

public void PlayButton_User_Click()
{
    isPausedDueToAudioStateMonitor = false;
    mediaPlayer.Play();
}