Capture à partir de plusieurs sources à l’aide de MediaFrameSourceGroupCapture from multiple sources using MediaFrameSourceGroup

Cet article vous montre comment capturer des vidéos à partir de plusieurs sources simultanément à un seul fichier avec plusieurs pistes vidéo incorporées.This article shows you how to capture video from multiple sources simultaneously to a single file with multiple embedded video tracks. À partir de RS3, vous pouvez spécifier plusieurs objets VideoStreamDescriptor pour un seul MediaEncodingProfile.Starting with RS3, you can specify multiple VideoStreamDescriptor objects for a single MediaEncodingProfile. Cela vous permet d’encoder plusieurs flux simultanément en un seul fichier.This enables you to encode multiple streams simultaneously to a single file. Les flux vidéo qui sont encodés dans cette opération doivent être inclus dans un MediaFrameSourceGroup unique qui spécifie un ensemble de caméras sur l’appareil actuel qui peut être utilisé en même temps.The video streams that are encoded in this operation must be included in a single MediaFrameSourceGroup which specifies a set of cameras on the current device that can be used at the same time.

Pour plus d’informations sur l’utilisation de MediaFrameSourceGroup avec la classe MediaFrameReader pour activer des scénarios de vision d’ordinateur en temps réel qui utilisent plusieurs caméras, consultez traiter des frames multimédias avec MediaFrameReader.For information on using MediaFrameSourceGroup with the MediaFrameReader class to enable real-time computer vision scenarios that use multiple cameras, see Process media frames with MediaFrameReader.

Le reste de cet article vous guide tout au long des étapes d’enregistrement vidéo de deux caméras de couleur dans un fichier unique avec plusieurs pistes vidéo.The rest of this article will walk you through the steps of recording video from two color cameras to a single file with multiple video tracks.

Rechercher les groupes de capteurs disponiblesFind available sensor groups

Un MediaFrameSourceGroup représente une collection de sources de frame, généralement des appareils photo, accessibles à simulataneously.A MediaFrameSourceGroup represents a collection of frame sources, typically cameras, that can be accessed simulataneously. L’ensemble de groupes de sources de frame disponibles est différent pour chaque appareil. la première étape de cet exemple consiste donc à obtenir la liste des groupes de sources de frame disponibles et à en trouver un qui contient les caméras nécessaires pour le scénario, ce qui, dans ce cas, requiert deux caméras couleur.The set of available frame source groups is different for each device, so the first step in this example is to get the list of available frame source groups and finding one that contains the necessary cameras for the scenario, which in this case requires two color cameras.

La méthode MediaFrameSourceGroup. FindAllAsync retourne tous les groupes sources disponibles sur l’appareil actuel.The MediaFrameSourceGroup.FindAllAsync method returns all source groups available on the current device. Chaque MediaFrameSourceGroup retourné contient une liste d’objets MediaFrameSourceInfo qui décrit chaque source de frame dans le groupe.Each returned MediaFrameSourceGroup has a list of MediaFrameSourceInfo objects that describes each frame source in the group. Une requête LINQ est utilisée pour rechercher un groupe source qui contient deux caméras de couleur, l’une sur le panneau avant et l’autre à l’arrière.A Linq query is used to find a source group that contains two color cameras, one on the front panel and one on the back. Un objet anonyme qui contient les MediaFrameSourceGroup sélectionnés et les MediaFrameSourceInfo pour chaque caméra de couleur est retourné.An anonymous object is returned that contains the selected MediaFrameSourceGroup and the MediaFrameSourceInfo for each color camera. Au lieu d’utiliser la syntaxe LINQ, vous pouvez à la place parcourir chaque groupe, puis chaque MediaFrameSourceInfo pour rechercher un groupe qui répond à vos besoins.Instead of using Linq syntax, you could instead loop through each group, and then each MediaFrameSourceInfo to look for a group that meets your requirements.

Notez que tous les appareils ne contiennent pas un groupe source qui contient deux caméras couleur. vous devez donc vérifier qu’un groupe source a été trouvé avant de tenter de capturer la vidéo.Note that not every device will contain a source group that contains two color cameras, so you should check to make sure that a source group was found before trying to capture video.

var sensorGroups = await MediaFrameSourceGroup.FindAllAsync();

var foundGroup = sensorGroups.Select(g => new
{
    group = g,
    color1 = g.SourceInfos.Where(info => info.SourceKind == MediaFrameSourceKind.Color && info.DeviceInformation.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front).FirstOrDefault(),
    color2 = g.SourceInfos.Where(info => info.SourceKind == MediaFrameSourceKind.Color && info.DeviceInformation.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back).FirstOrDefault()
}).Where(g => g.color1 != null && g.color2 != null).FirstOrDefault();

if (foundGroup == null)
{
    Debug.WriteLine("No groups found.");
    return;
}

Initialiser l’objet MediaCaptureInitialize the MediaCapture object

La classe MediaCapture est la classe principale utilisée pour la plupart des opérations de capture audio, vidéo et photo dans des applications UWP.The MediaCapture class is the primary class that is used for most audio, video, and photo capture operations in UWP apps. Initialisez l’objet en appelant InitializeAsync, en passant un objet MediaCaptureInitializationSettings qui contient des paramètres d’initialisation.Initialize the object by calling InitializeAsync, passing in a MediaCaptureInitializationSettings object that contains initialization parameters. Dans cet exemple, le seul paramètre spécifié est la propriété SourceGroup , qui est définie sur le MediaFrameSourceGroup récupéré dans l’exemple de code précédent.In this example, the only specified setting is the SourceGroup property, which is set to the MediaFrameSourceGroup that was retrieved in the previous code example.

Pour plus d’informations sur les autres opérations que vous pouvez effectuer avec MediaCapture et d’autres fonctionnalités d’application UWP pour la capture de médias, consultez camera.For information on other operations you can perform with MediaCapture and other UWP app features for capturing media, see Camera.

var settings = new MediaCaptureInitializationSettings()
{
    SourceGroup = foundGroup.group
};

mediaCapture = new MediaCapture();
await mediaCapture.InitializeAsync(settings);

Créer un MediaEncodingProfileCreate a MediaEncodingProfile

La classe MediaEncodingProfile indique au pipeline de capture multimédia la manière dont les données audio et vidéo capturées doivent être encodées au fur et à mesure de leur écriture dans un fichier.The MediaEncodingProfile class tells the media capture pipeline how captured audio and video should be encoded as they are written to a file. Pour les scénarios de capture et de transcodage classiques, cette classe fournit un ensemble de méthodes statiques pour créer des profils communs, tels que CreateAvi et CreateMp3.For typical capture and transcoding scenarios, this class provides a set of static methods for creating common profiles, like CreateAvi and CreateMp3. Pour cet exemple, un profil d’encodage est créé manuellement à l’aide d’un conteneur MPEG4 et d’un encodage vidéo H264 –.For this example, an encoding profile is manually created using an Mpeg4 container and H264 video encoding. Les paramètres d’encodage vidéo sont spécifiés à l’aide d’un objet VideoEncodingProperties .Video encoding settings are specified using a VideoEncodingProperties object. Pour chaque caméra de couleur utilisée dans ce scénario, un objet VideoStreamDescriptor est configuré.For each color camera used in this scenario, a VideoStreamDescriptor object is configured. Le descripteur est construit avec l’objet VideoEncodingProperties qui spécifie l’encodage.The descriptor is constructed with the VideoEncodingProperties object specifying the encoding. La propriété label de VideoStreamDescriptor doit être définie sur l’ID de la source de cadre de média qui sera capturée dans le flux.The Label property of the VideoStreamDescriptor must be set to the ID of the media frame source that will be captured to the stream. C’est ainsi que le pipeline de capture sait quel descripteur de flux et quelles propriétés d’encodage doivent être utilisés pour chaque caméra.This is how the capture pipeline knows which stream descriptor and encoding properties should be used for each camera. L’ID de la source du frame est exposé par les objets MediaFrameSourceInfo qui ont été trouvés dans la section précédente, lorsqu’un MediaFrameSourceGroup a été sélectionné.The ID of the frame source is exposed by the MediaFrameSourceInfo objects that were found in the previous section, when a MediaFrameSourceGroup was selected.

À compter de Windows 10, version 1709, vous pouvez définir plusieurs propriétés d’encodage sur un MediaEncodingProfile en appelant SetVideoTracks.Starting with Windows 10, version 1709, you can set multiple encoding properties on a MediaEncodingProfile by calling SetVideoTracks. Vous pouvez récupérer la liste des descripteurs de flux vidéo en appelant GetVideoTracks.You can retrieve the list of video stream descriptors by calling GetVideoTracks. Notez que si vous définissez la propriété Video , qui stocke un descripteur de flux unique, la liste de descripteurs que vous avez définie en appelant SetVideoTracks sera remplacée par une liste contenant le seul descripteur que vous avez spécifié.Note that if you set the Video property, which stores a single stream descriptor, the descriptor list you set by calling SetVideoTracks will be replaced with a list containing the single descriptor you specified.

var profile = new MediaEncodingProfile();
profile.Container = new ContainerEncodingProperties();
profile.Container.Subtype = MediaEncodingSubtypes.Mpeg4;

List<VideoStreamDescriptor> streams = new List<VideoStreamDescriptor>();

var encodeProps = VideoEncodingProperties.CreateH264();
encodeProps.Subtype = MediaEncodingSubtypes.H264;
var stream1Desc = new VideoStreamDescriptor(encodeProps);
stream1Desc.Label = foundGroup.color1.Id;
streams.Add(stream1Desc);

var encodeProps2 = VideoEncodingProperties.CreateH264();
encodeProps2.Subtype = MediaEncodingSubtypes.H264;
var stream2Desc = new VideoStreamDescriptor(encodeProps2);
stream2Desc.Label = foundGroup.color2.Id;
streams.Add(stream2Desc);

profile.SetVideoTracks(streams);
profile.Audio = null;

Encoder les métadonnées chronométrées dans les fichiers multimédiasEncode timed metadata in media files

À compter de Windows 10, version 1803, en plus de l’audio et de la vidéo, vous pouvez encoder les métadonnées chronométrées dans un fichier multimédia pour lequel le format de données est pris en charge.Starting with Windows 10, version 1803, in addition to audio and video you can encode timed metadata into a media file for which the data format is supported. Par exemple, les métadonnées GoPro (GPMD) peuvent être stockées dans des fichiers MP4 pour transmettre l’emplacement géographique corrélé à un flux vidéo.For example, GoPro metadata (gpmd) can be stored in MP4 files to convey the geographic location correlated with a video stream.

Les métadonnées d’encodage utilisent un modèle qui est parallèle à l’encodage audio ou vidéo.Encoding metadata uses a pattern that is parallel to encoding audio or video. La classe TimedMetadataEncodingProperties décrit les propriétés de type, de sous-type et d’encodage des métadonnées, comme VideoEncodingProperties pour la vidéo.The TimedMetadataEncodingProperties class describes the type, subtype and encoding properties of the metadata, like VideoEncodingProperties does for video. Le TimedMetadataStreamDescriptor identifie un flux de métadonnées, tout comme le VideoStreamDescriptor pour les flux vidéo.The TimedMetadataStreamDescriptor identifies a metadata stream, just as the VideoStreamDescriptor does for video streams.

L’exemple suivant montre comment initialiser un objet TimedMetadataStreamDescriptor .The following example shows how to intialize a TimedMetadataStreamDescriptor object. Tout d’abord, un objet TimedMetadataEncodingProperties est créé et le sous- type est défini sur un GUID qui identifie le type de métadonnées qui sera inclus dans le flux.First, a TimedMetadataEncodingProperties object is created and the Subtype is set to a GUID that identifies the type of metadata that will be included in the stream. Cet exemple utilise le GUID pour les métadonnées GoPro (GPMD).This example uses the GUID for GoPro metadata (gpmd). La méthode SetFormatUserData est appelée pour définir des données spécifiques au format.The SetFormatUserData method is called to set format-specific data. Pour les fichiers MP4, les données spécifiques au format sont stockées dans la zone SampleDescription (STSD).For MP4 files, the format-specific data is stored in the SampleDescription box (stsd). Ensuite, une nouvelle TimedMetadataStreamDescriptor est créée à partir des propriétés d’encodage.Next, a new TimedMetadataStreamDescriptor is created from the encoding properties. Les propriétés d' étiquette et de nom sont définies pour identifier le flux à encoder.The Label and Name properties are set to identify the stream to be encoded.

           TimedMetadataEncodingProperties encodingProperties = new TimedMetadataEncodingProperties
           {
               Subtype = "{67706D64-BF10-48B4-BC18-593DC1DB950F}"
           };

           byte[] streamDescriptionData = GetStreamDescriptionDataForGpmdEncodingSubtype();
           encodingProperties.SetFormatUserData(streamDescriptionData);

           TimedMetadataStreamDescriptor descriptor = new TimedMetadataStreamDescriptor(encodingProperties)
           {
               Name = "GPS Info",
               Label = "GPS Info"
           };

Appelez MediaEncodingProfile. SetTimedMetadataTracks pour ajouter le descripteur de flux de métadonnées au profil d’encodage.Call MediaEncodingProfile.SetTimedMetadataTracks to add the metadata stream descriptor to the encoding profile. L’exemple suivant montre une méthode d’assistance qui prend deux descripteurs de flux vidéo, un descripteur de flux audio et un descripteur de flux de métadonnées minutaux et retourne un MediaEncodingProfile qui peut être utilisé pour encoder les flux.The following example shows a helper method that takes two video stream descriptors, one audio stream descriptor, and one timed metadata stream descriptor and returns a MediaEncodingProfile that can be used to encode the streams.

public MediaEncodingProfile CreateProfileForTranscoder(VideoStreamDescriptor videoStream1, VideoStreamDescriptor videoStream2, AudioStreamDescriptor audioStream, TimedMetadataStreamDescriptor timedMetadataStream)
{
    ContainerEncodingProperties container = new ContainerEncodingProperties()
    {
        Subtype = MediaEncodingSubtypes.Mpeg4
    };

    MediaEncodingProfile profile = new MediaEncodingProfile()
    {
        Container = container
    };


    VideoStreamDescriptor encodingVideoStream1 = videoStream1.Copy();
    encodingVideoStream1.EncodingProperties.Subtype = MediaEncodingSubtypes.H264;
    encodingVideoStream1.Label = videoStream1.Name;

    VideoStreamDescriptor encodingVideoStream2 = videoStream2.Copy();
    encodingVideoStream2.EncodingProperties.Subtype = MediaEncodingSubtypes.H264;
    encodingVideoStream2.Label = videoStream2.Name;

    AudioStreamDescriptor encodingAudioStream = audioStream.Copy();
    encodingAudioStream.EncodingProperties.Subtype = MediaEncodingSubtypes.Ac3;
    encodingAudioStream.Label = audioStream.Name;

    TimedMetadataStreamDescriptor encodingTimedMetadataStream = timedMetadataStream.Copy();

    profile.SetTimedMetadataTracks(new TimedMetadataStreamDescriptor[] { encodingTimedMetadataStream });
    profile.SetVideoTracks(new VideoStreamDescriptor[] { encodingVideoStream1, encodingVideoStream2 });
    profile.SetAudioTracks(new AudioStreamDescriptor[] { encodingAudioStream });
    return profile;
}

Enregistrement à l’aide du MediaEncodingProfile à plusieurs fluxRecord using the multi-stream MediaEncodingProfile

La dernière étape de cet exemple consiste à lancer la capture vidéo en appelant StartRecordToStorageFileAsync, en transmettant le StorageFile sur lequel le média capturé est écrit et le MediaEncodingProfile créé dans l’exemple de code précédent.The final step in this example is to initiate video capture by calling StartRecordToStorageFileAsync, passing in the StorageFile to which the captured media is written, and the MediaEncodingProfile created in the previous code example. Après avoir attendu quelques secondes, l’enregistrement est arrêté avec un appel à StopRecordAsync.After waiting a few seconds, the recording is stopped with a call to StopRecordAsync.

var recordFile = await Windows.Storage.KnownFolders.CameraRoll.CreateFileAsync("record.mp4", Windows.Storage.CreationCollisionOption.GenerateUniqueName);
await mediaCapture.StartRecordToStorageFileAsync(profile, recordFile);
await Task.Delay(8000);
await mediaCapture.StopRecordAsync();

Une fois l’opération terminée, un fichier vidéo contenant la vidéo capturée à partir de chaque caméra encodée en tant que flux distinct dans le fichier est créé.When the operation is complete, a video file will have been created that contains the video captured from each camera encoded as a separate stream within the file. Pour plus d’informations sur la lecture de fichiers multimédias contenant plusieurs pistes vidéo, consultez éléments multimédias, sélections et pistes.For information on playing media files containing multiple video tracks, see Media items, playlists, and tracks.