Capture à partir de plusieurs sources à l’aide de MediaFrameSourceGroup

Cet article vous montre comment capturer des vidéos à partir de plusieurs sources simultanément dans un seul fichier avec plusieurs pistes vidéo incorporées. À partir de RS3, vous pouvez spécifier plusieurs objets VideoStreamDescriptor pour un seul MediaEncodingProfile. Cela vous permet d’encoder plusieurs flux simultanément dans un seul fichier. Les flux vidéo qui sont encodés dans cette opération doivent être inclus dans un seul MediaFrameSourceGroup qui spécifie un ensemble de caméras sur l’appareil actuel qui peuvent être utilisées en même temps.

Pour plus d’informations sur l’utilisation de MediaFrameSourceGroup avec la classe MediaFrameReader pour activer des scénarios de vision par ordinateur en temps réel qui utilisent plusieurs caméras, consultez Traiter des images multimédias avec MediaFrameReader.

Le reste de cet article vous guide tout au long des étapes de l’enregistrement vidéo à partir de deux caméras couleur vers un seul fichier avec plusieurs pistes vidéo.

Rechercher les groupes de capteurs disponibles

Un MediaFrameSourceGroup représente une collection de sources d’images, généralement des caméras, qui sont accessibles de manière simulaire. L’ensemble des groupes de sources d’images disponibles étant différent pour chaque appareil, la première étape de cet exemple consiste à obtenir la liste des groupes de sources d’images disponibles et à en trouver un qui contient les caméras nécessaires pour le scénario, ce qui dans ce cas nécessite deux caméras couleur.

La méthode MediaFrameSourceGroup.FindAllAsync retourne tous les groupes sources disponibles sur l’appareil actuel. Chaque MediaFrameSourceGroup retourné a une liste d’objets MediaFrameSourceInfo qui décrit chaque source de frame dans le groupe. Une requête Linq permet de rechercher un groupe source qui contient deux caméras couleur, l’une sur le panneau avant et l’autre à l’arrière. Un objet anonyme est retourné qui contient le MediaFrameSourceGroup sélectionné et le MediaFrameSourceInfo pour chaque caméra couleur. Au lieu d’utiliser la syntaxe Linq, vous pouvez plutôt effectuer une boucle dans chaque groupe, puis chaque MediaFrameSourceInfo pour rechercher un groupe qui répond à vos besoins.

Notez que tous les appareils ne contiennent pas un groupe source contenant deux caméras couleur. Vous devez donc case activée pour vous assurer qu’un groupe source a été trouvé avant d’essayer de capturer une vidéo.

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 MediaCapture

La classe MediaCapture est la classe principale utilisée pour la plupart des opérations de capture audio, vidéo et photo dans les applications UWP. Initialisez l’objet en appelant InitializeAsync, en passant un objet MediaCaptureInitializationSettings qui contient des paramètres d’initialisation. Dans cet exemple, le seul paramètre spécifié est la propriété SourceGroup , qui est définie sur le MediaFrameSourceGroup qui a été récupéré dans l’exemple de code précédent.

Pour plus d’informations sur d’autres opérations que vous pouvez effectuer avec MediaCapture et d’autres fonctionnalités d’application UWP pour capturer des médias, consultez Caméra.

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

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

Créer un MediaEncodingProfile

La classe MediaEncodingProfile indique au pipeline de capture multimédia comment l’audio et la vidéo capturés doivent être encodés à mesure qu’ils sont écrits dans un fichier. Pour les scénarios de capture et de transcodage classiques, cette classe fournit un ensemble de méthodes statiques pour créer des profils courants, comme CreateAvi et CreateMp3. Pour cet exemple, un profil d’encodage est créé manuellement à l’aide d’un conteneur Mpeg4 et d’un encodage vidéo H264. Les paramètres d’encodage vidéo sont spécifiés à l’aide d’un objet VideoEncodingProperties . Pour chaque caméra couleur utilisée dans ce scénario, un objet VideoStreamDescriptor est configuré. Le descripteur est construit avec l’objet VideoEncodingProperties spécifiant l’encodage. La propriété Label du VideoStreamDescriptor doit être définie sur l’ID de la source de trame multimédia qui sera capturée dans le flux. C’est ainsi que le pipeline de capture sait quel descripteur de flux et quelles propriétés d’encodage doivent être utilisées pour chaque caméra. L’ID de la source de 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é.

À compter de Windows 10 version 1709, vous pouvez définir plusieurs propriétés d’encodage sur un MediaEncodingProfile en appelant SetVideoTracks. Vous pouvez récupérer la liste des descripteurs de flux vidéo en appelant GetVideoTracks. Notez que si vous définissez la propriété Video , qui stocke un descripteur de flux unique, la liste de descripteurs que vous définissez en appelant SetVideoTracks sera remplacée par une liste contenant le descripteur unique que vous avez spécifié.

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 chrono timed dans les fichiers multimédias

À compter de Windows 10, version 1803, vous pouvez encoder les métadonnées chronologiques dans un fichier multimédia pour lequel le format de données est pris en charge, en plus de l’audio et de la vidéo. 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.

Les métadonnées d’encodage utilisent un modèle parallèle à l’encodage audio ou vidéo. La classe TimedMetadataEncodingProperties décrit le type, le sous-type et les propriétés d’encodage des métadonnées, comme videoEncodingProperties pour la vidéo. Le TimedMetadataStreamDescriptor identifie un flux de métadonnées, tout comme le VideoStreamDescriptor pour les flux vidéo.

L’exemple suivant montre comment intialiser un objet TimedMetadataStreamDescriptor . 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 seront incluses dans le flux. Cet exemple utilise le GUID pour les métadonnées GoPro (gpmd). La méthode SetFormatUserData est appelée pour définir des données spécifiques au format. Pour les fichiers MP4, les données spécifiques au format sont stockées dans la zone SampleDescription (stsd). Ensuite, un nouveau TimedMetadataStreamDescriptor est créé à partir des propriétés d’encodage. Les propriétés Label et Name sont définies pour identifier le flux à encoder.

           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. 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 chronomètres, et retourne un MediaEncodingProfile qui peut être utilisé pour encoder les flux.

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

Enregistrer à l’aide du mediaEncodingProfile multi-flux

La dernière étape de cet exemple consiste à lancer la capture vidéo en appelant StartRecordToStorageFileAsync, en passant le StorageFile dans lequel le média capturé est écrit, et le MediaEncodingProfile créé dans l’exemple de code précédent. Après avoir attendu quelques secondes, l’enregistrement est arrêté avec un appel à 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 a été créé qui contient la vidéo capturée à partir de chaque caméra encodée sous la forme d’un flux distinct dans le fichier. Pour plus d’informations sur la lecture de fichiers multimédias contenant plusieurs pistes vidéo, consultez Éléments multimédias, playlists et pistes.