Capturer l’audio, la vidéo, les captures d’écran et les métadonnées d’un jeuCapture game audio, video, screenshots, and metadata

Cet article explique comment capturer des vidéos et des captures d’écran de jeu, et comment envoyer des métadonnées incorporées par le système dans des médias capturés et diffusés, ce qui permet à votre application et à d’autres de créer des expériences dynamiques qui sont synchronisées avec les événements de jeu.This article describes how to capture game video, audio, and screenshots, and how to submit metadata that the system will embed in captured and broadcast media, allowing your app and others to create dynamic experiences that are synchronized to gameplay events.

Il existe deux façons de capturer un jeu de jeu dans une application UWP.There are two different ways that gameplay can be captured in a UWP app. L’utilisateur peut lancer la capture à l’aide de l’interface utilisateur système intégrée.The user can initiate capture using the built-in system UI. Les supports capturés à l’aide de cette technique sont ingérés dans l’écosystème de jeux Microsoft, peuvent être affichés et partagés via des expériences internes telles que l’application Xbox et ne sont pas directement disponibles pour votre application ou pour les utilisateurs.Media that is captured using this technique is ingested into the Microsoft gaming ecosystem, can be viewed and shared through first-party experiences such as the Xbox app, and is not directly availble to your app or to users. Les premières sections de cet article vous expliquent comment activer et désactiver la capture d’application implémentée par le système et comment recevoir des notifications lorsque la capture de l’application démarre ou s’arrête.The first sections of this article will show you how to enable and disable system-implemented app capture and how to receive notifications when app capture starts or stops.

L’autre façon de capturer des médias consiste à utiliser les API de l’espace de noms Windows. Media. AppRecording .The other way to capture media is to use the APIs of the Windows.Media.AppRecording namespace. Si la capture est activée sur l’appareil, votre application peut commencer à capturer le jeu, puis, après un certain temps, vous pouvez arrêter la capture, auquel cas le média est écrit dans un fichier.If capturing is enabled on the device, your app can start capturing gameplay and then, after some time has passed, you can stop the capture, at which point the media is written to a file. Si l’utilisateur a activé la capture d’historique, vous pouvez également enregistrer le jeu qui s’est déjà produit en spécifiant une heure de début dans le passé et une durée à enregistrer.If the user has enabled historical capture, then you can also record gameplay that has already occured by specifying a start time in the past and a duration to record. Ces deux techniques produisent un fichier vidéo accessible par votre application, et selon l’emplacement où vous avez choisi d’enregistrer les fichiers, par l’utilisateur.Both of these techniques produce an video file that can be accessed by your app, and depending on where you choose to save the files, by the user. Les sections du milieu de cet article vous guident tout au long de la implémentation de ces scénarios.The middle sections of this article walk you through the implemenation of these scenarios.

L’espace de noms Windows. Media. capture fournit des API pour créer des métadonnées qui décrivent le jeu qui est capturé ou diffusé.The Windows.Media.Capture namespace provides APIs for creating metadata that describes the gameplay being captured or broadcast. Cela peut inclure du texte ou des valeurs numériques, avec une étiquette de texte qui identifie chaque élément de données.This can include text or numeric values, with a text label identifying each data item. Les métadonnées peuvent représenter un « événement » qui se produit à un moment donné, par exemple lorsque l’utilisateur termine un tour dans un jeu de course, ou qu’il peut représenter un « État » qui persiste sur une période de temps, telle que la carte de jeu actuelle dans laquelle l’utilisateur est joué.Metadata can represent an "event" which occurs at a single moment, such as when the user finishes a lap in a racing game, or it can represent a "state" that persists over a span of time, such as the current game map the user is playing in. Les métadonnées sont écrites dans un cache qui est alloué et géré pour votre application par le système.The metadata is written to a cache that is allocated and managed for your app by the system. Les métadonnées sont incorporées dans des flux de diffusion et des fichiers vidéo capturés, y compris les techniques intégrées de capture de système ou de capture d’application personnalisée.The metadata is embedded into broadcast streams and captured video files, including both the built-in system capture or custom app capture techniques. Les dernières sections de cet article vous montrent comment écrire des métadonnées de jeu.The final sections of this article show you how to write gameplay metadata.

Notes

Étant donné que les métadonnées de jeu peuvent être incorporées dans des fichiers multimédias qui peuvent potentiellement être partagés sur le réseau, en dehors du contrôle de l’utilisateur, vous ne devez pas inclure d’informations d’identification personnelle ou d’autres données potentiellement sensibles dans les métadonnées.Because the gameplay metadata can be embedded in media files that can potentially be shared over the network, out of the user's control, you should not include personally identifiable information or other potentially sensitive data in the metadata.

Activer et désactiver la capture d’applications systèmeEnable and disable system app capture

La capture d’application système est lancée par l’utilisateur avec l’interface utilisateur système intégrée.System app capture is initiated by the user with the built-in system UI. Les fichiers sont ingérés par l’écosystème de jeux Windows et ne sont pas accessibles à votre application ou à l’utilisateur, à l’exception des premières expériences telles que l’application Xbox.The files are ingested by the Windows gaming ecosystem and is not available to your app or the user, except for through first party experiences like the Xbox app. Votre application peut désactiver et activer la capture d’application initiée par le système, ce qui vous permet d’empêcher l’utilisateur de capturer un contenu ou un jeu de données.Your app can disable and enable system-initiated app capture, allowing you to prevent the user from capturing certain content or gameplay.

Pour activer ou désactiver la capture d’application système, appelez simplement la méthode statique AppCapture. SetAllowedAsync et passez false pour désactiver la capture ou true pour activer la capture.To enable or disable system app capture, simply call the static method AppCapture.SetAllowedAsync and passing false to disable capture or true to enable capture.

Windows::Media::Capture::AppCapture::SetAllowedAsync(allowed);

Recevoir des notifications lorsque la capture de l’application système démarre et s’arrêteReceive notifications when system app capture starts and stops

Pour recevoir une notification lorsque la capture de l’application système commence ou se termine, commencez par obtenir une instance de la classe AppCapture en appelant la méthode de fabrique GetForCurrentView.To receive a notification when system app capture begins or ends, first get an instance of the AppCapture class by calling the factory method GetForCurrentView. Ensuite, inscrivez un gestionnaire pour l’événement CapturingChanged .Next, register a handler for the CapturingChanged event.

Windows::Media::Capture::AppCapture^ appCapture = Windows::Media::Capture::AppCapture::GetForCurrentView();
appCapture->CapturingChanged +=
    ref new TypedEventHandler<Windows::Media::Capture::AppCapture^, Platform::Object^>(this, &App::OnCapturingChanged);

Dans le gestionnaire de l’événement CapturingChanged , vous pouvez vérifier les propriétés IsCapturingAudio et IsCapturingVideo pour déterminer si l’audio ou la vidéo est capturée, respectivement.In the handler for the CapturingChanged event, you can check the IsCapturingAudio and the IsCapturingVideo properties to determine if audio or video are being captured respectively. Vous souhaiterez peut-être mettre à jour l’interface utilisateur de votre application pour indiquer l’état de capture actuel.You may want to update your app's UI to indicate the current capturing status.

void App::OnCapturingChanged(Windows::Media::Capture::AppCapture^ sender, Platform::Object^ args)
{
    Platform::String^ captureStatusText = "";
    if (sender->IsCapturingAudio)
    {
        captureStatusText += "Capturing audio.";
    }
    if (sender->IsCapturingVideo)
    {
        captureStatusText += "Capturing video.";
    }
    UpdateStatusText(captureStatusText);
}

Ajouter les extensions de bureau Windows pour la série UWP à votre applicationAdd the Windows Desktop Extensions for the UWP to your app

Les API d’enregistrement audio et vidéo et de capture de captures d’écran directement à partir de votre application, qui se trouvent dans l’espace de noms Windows. Media. AppRecording , ne sont pas incluses dans le contrat d’API universel.The APIs for recording audio and video and for capturing screenshots directly from your app, found in the Windows.Media.AppRecording namespace, are not included in the Universal API contract. Pour accéder aux API, vous devez ajouter une référence aux extensions de bureau Windows pour la série UWP à votre application en suivant les étapes ci-dessous.To access the APIs, you must add a reference to the Windows Desktop Extensions for the UWP to your app with the following steps.

  1. Dans Visual Studio, dans Explorateur de solutions, développez votre projet UWP et cliquez avec le bouton droit sur références , puis sélectionnez Ajouter une référence....In Visual Studio, in Solution Explorer, expand your UWP project and right-click References and then select Add Reference....
  2. Développez le nœud Windows universel et sélectionnez Extensions.Expand the Universal Windows node and select Extensions.
  3. Dans la liste des extensions, cochez la case en regard des extensions du bureau Windows pour l’entrée UWP correspondant à la build cible de votre projet.In the list of extensions check the checkbox next to the Windows Desktop Extensions for the UWP entry that matches the target build for your project. Pour les fonctionnalités de diffusion d’application, la version doit être supérieure ou égale à 1709.For the app broadcast features, the version must be 1709 or greater.
  4. Cliquez sur OK.Click OK.

Obtient une instance de AppRecordingManagerGet an instance of AppRecordingManager

La classe AppRecordingManager est l’API centrale que vous allez utiliser pour gérer l’enregistrement de l’application.The AppRecordingManager class is the central API you will use to manage app recording. Récupérez une instance de cette classe en appelant la méthode de fabrique GetDefault.Get an instance of this class by calling the factory method GetDefault. Avant d’utiliser les API de l’espace de noms Windows. Media. AppRecording , vous devez vérifier leur présence sur l’appareil actuel.Before using any of the APIs in the Windows.Media.AppRecording namespace, you should check for their presence on the current device. Les API ne sont pas disponibles sur les appareils exécutant une version du système d’exploitation antérieure à Windows 10, version 1709.The APIs are not available on devices running an OS version earlier than Windows 10, version 1709. Au lieu de vérifier une version spécifique du système d’exploitation, utilisez la méthode ApiInformation. IsApiContractPresent pour rechercher la version de Windows. Media. AppBroadcasting. AppRecordingContract version 1,0.Rather than check for a specific OS version, use the ApiInformation.IsApiContractPresent method to query for the Windows.Media.AppBroadcasting.AppRecordingContract version 1.0. Si ce contrat est présent, les API d’enregistrement sont disponibles sur l’appareil.If this contract is present, then the recording APIs are available on the device. L’exemple de code de cet article vérifie les API une seule fois, puis vérifie si la valeur de AppRecordingManager est null avant les opérations suivantes.The example code in this article checks for the APIs once and then checks if the AppRecordingManager is null before subsequent operations.

if (Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(
    "Windows.Media.AppRecording.AppRecordingContract", 1, 0))
{
    m_appRecordingManager = AppRecordingManager::GetDefault();
}

Déterminer si votre application peut enregistrer actuellementDetermine if your app can currently record

Il existe plusieurs raisons pour lesquelles votre application peut ne pas être en mesure de capturer des données audio ou vidéo, notamment si l’appareil actuel ne répond pas à la configuration matérielle requise pour l’enregistrement ou si une autre application est en cours de diffusion.There are several reasons that your app may not currently be able to capture audio or video, including if the current device doesn't meet the hardware requirements for recording or if another app is currently broadcasting. Avant de lancer un enregistrement, vous pouvez vérifier si votre application est actuellement en mesure de l’enregistrer.Before initiating a recording, you can check to see if your app is currently able to record. Appelez la méthode GetStatus de l’objet AppRecordingManager , puis vérifiez la propriété CanRecord de l’objet AppRecordingStatus retourné.Call the GetStatus method of the AppRecordingManager object and then check the CanRecord property of the returned AppRecordingStatus object. Si CanRecord retourne false, ce qui signifie que votre application ne peut pas enregistrer actuellement, vous pouvez vérifier la propriété Details pour déterminer la raison.If CanRecord returns false, meaning that your app can't currently record, you can check the Details property to determine the reason. Selon la raison, vous souhaiterez peut-être afficher l’état de l’utilisateur ou afficher les instructions d’activation de l’enregistrement de l’application.Depending on the reason, you may want to display the status to the user or show instructions for enabling app recording.

bool App::CanRecord()
{

    if (m_appRecordingManager == nullptr)
    {
        return false;
    }

    AppRecordingStatus^ recordingStatus = m_appRecordingManager->GetStatus();

    if (!recordingStatus->CanRecord)
    {
        AppRecordingStatusDetails^ details = recordingStatus->Details;
    
        if (details->IsAnyAppBroadcasting)
        {
            UpdateStatusText("Another app is currently broadcasting.");
            return false;
        }

        if (details->IsCaptureResourceUnavailable)
        {
            UpdateStatusText("The capture resource is currently unavailable.");
            return false;
        }

        if (details->IsGameStreamInProgress)
        {
            UpdateStatusText("A game stream is currently in progress.");
            return false;
        }

        if (details->IsGpuConstrained)
        {
            // Typically, this means that the GPU software does not include an H264 encoder
            UpdateStatusText("The GPU does not support app recording.");
            return false;
        }

        
        if (details->IsAppInactive)
        {
            // Broadcasting can only be started when the application's window is the active window.
            UpdateStatusText("The app window to be recorded is not active.");
            return false;
        }

        if (details->IsBlockedForApp)
        {
            UpdateStatusText("Recording is blocked for this app.");
            return false;
        }

        if (details->IsDisabledByUser)
        {
            UpdateStatusText("The user has disabled GameBar in Windows Settings.");
            return false;
        }

        if (details->IsDisabledBySystem)
        {
            UpdateStatusText("Recording is disabled by the system.");
            return false;
        }

        
        return false;
    }


    return true;
}

Démarrer et arrêter manuellement l’enregistrement de votre application dans un fichierManually start and stop recording your app to a file

Après avoir vérifié que votre application est en mesure d’enregistrer, vous pouvez démarrer un nouvel enregistrement en appelant la méthode StartRecordingToFileAsync de l’objet AppRecordingManager .After verifying that your app is able to record, you can start a new recording by calling the StartRecordingToFileAsync method of the AppRecordingManager object.

Dans l’exemple suivant, le premier bloc Then s’exécute lorsque la tâche asynchrone échoue.In the following example, the first then block executes when the asynchronous task fails. Le deuxième bloc tente ensuite d’accéder au résultat de la tâche et, si le résultat est null, la tâche est terminée.The second then block attempts to access the result of the task and, if the result is null, then the task has completed. Dans les deux cas, la méthode d’assistance OnRecordingComplete , illustrée ci-dessous, est appelée pour gérer le résultat.In both cases, the OnRecordingComplete helper method, shown below, is called to handle the result.

void App::StartRecordToFile(Windows::Storage::StorageFile^ file)
{

    if (m_appRecordingManager == nullptr)
    {
        return;
    }

    if (!CanRecord())
    {
        return;
    }


    // Start a recording operation to record starting from 
    // now until the operation fails or is cancelled. 
    m_recordOperation = m_appRecordingManager->StartRecordingToFileAsync(file);

    create_task(m_recordOperation).then(
        [this](AppRecordingResult^ result)
    {
        OnRecordingComplete();
    }).then([this](task<void> t)
    {
        try
        {
            t.get();
        }
        catch (const task_canceled&)
        {
            OnRecordingComplete();
        }
    });
}

Une fois l’opération d’enregistrement terminée, vérifiez la propriété Succeeded de l’objet AppRecordingResult retourné pour déterminer si l’opération d’enregistrement a réussi.When the recording operation completes, check the Succeeded property of the returned AppRecordingResult object to determine if the record operation was successful. Si c’est le cas, vous pouvez vérifier la propriété IsFileTruncated pour déterminer si, pour des raisons de stockage, le système a été contraint de tronquer le fichier capturé.If so, you can check the IsFileTruncated property to determine if, for storage reasons, the system was forced to truncate the captured file. Vous pouvez vérifier la propriété Duration pour découvrir la durée réelle du fichier enregistré qui, si le fichier est tronqué, peut être plus petite que la durée de l’opération d’enregistrement.You can check the Duration property to discover the actual duration of the recorded file which, if the file is truncated, may be shorter than the duration of the recording operation.

void App::OnRecordingComplete()
{
    if (m_recordOperation)
    {
        auto result = m_recordOperation->GetResults();

        if (result->Succeeded)
        {
            Windows::Foundation::TimeSpan duration = result->Duration;
            boolean isTruncated = result->IsFileTruncated;

            UpdateStatusText("Recording completed.");
        }
        else
        {
            // If the recording failed, ExtendedError 
            // can be retrieved and used for diagnostic purposes 
            HResult extendedError = result->ExtendedError;
            LogTelemetryMessage("Error during recording: " + extendedError);
        }

        m_recordOperation = nullptr;
    }
}

Les exemples suivants illustrent un code de base pour démarrer et arrêter l’opération d’enregistrement indiquée dans l’exemple précédent.The following examples show some basic code for starting and stopping the recording operation shown in the previous example.

StorageFolder^ storageFolder = ApplicationData::Current->LocalFolder;
concurrency::create_task(storageFolder->CreateFileAsync("recordtofile_example.mp4", CreationCollisionOption::ReplaceExisting)).then(
    [this](StorageFile^ file)
{
    StartRecordToFile(file);
});
void App::FinishRecordToFile()
{
    m_recordOperation->Cancel();
}

Enregistrer un intervalle de temps historique dans un fichierRecord a historical time span to a file

Si l’utilisateur a activé l’enregistrement de l’historique de votre application dans les paramètres système, vous pouvez enregistrer un laps de temps de jeu qui s’est déjà écoulé.If the user has enabled historical recording for your app in the system settings, you can record a time span of gameplay that has previously transpired. Un exemple précédent de cet article A montré comment confirmer que votre application peut enregistrer actuellement des procédures de jeu.A previous example in this article showed how to confirm that your app can currently record gameplay. Il existe une vérification supplémentaire pour déterminer si l’historique de capture est activé.There is an additional check to determine if historical capture is enabled. Une fois encore, appelez GetStatus et vérifiez la propriété CanRecordTimeSpan de l’objet AppRecordingStatus retourné.Once again, call GetStatus and check the CanRecordTimeSpan property of the returned AppRecordingStatus object. Cet exemple retourne également la propriété HistoricalBufferDuration de l' AppRecordingStatus qui sera utilisée pour déterminer une heure de début valide pour l’opération d’enregistrement.This example also returns the HistoricalBufferDuration property of the AppRecordingStatus which will be used to determine a valid start time for the recording operation.

bool App::CanRecordTimeSpan(TimeSpan &historicalDurationBuffer)
{

    if (m_appRecordingManager == nullptr)
    {
        return false;
    }

    AppRecordingStatus^ recordingStatus = m_appRecordingManager->GetStatus();
    if (recordingStatus->Details->IsTimeSpanRecordingDisabled)
    {
        UpdateStatusText("Historical time span recording is disabled by the system.");
        return false;
    }

    historicalDurationBuffer = recordingStatus->HistoricalBufferDuration;

    return true;
}

Pour capturer un intervalle de temps historique, vous devez spécifier une heure de début pour l’enregistrement et une durée.To capture a historical timespan, you must specify a start time for the recording and a duration. L’heure de début est fournie en tant que struct DateTime .The start time is provided as a DateTime struct. L’heure de début doit être une heure antérieure à l’heure actuelle, dans la longueur de la mémoire tampon d’enregistrement historique.The start time must be a time before the current time, within the length of the historical recording buffer. Pour cet exemple, la longueur de la mémoire tampon est récupérée dans le cadre du contrôle pour voir si l’enregistrement historique est activé, ce qui est indiqué dans l’exemple de code précédent.For this example, the buffer length is retrieved as part of the check to see if historical recording is enabled, which is shown in the previous code example. La durée de l’enregistrement historique est fournie sous forme de struct TimeSpan , qui doit également être inférieure ou égale à la durée de la mémoire tampon d’historique.The duration of the historical recording is provided as TimeSpan struct, which should also be equal to or smaller than the duration of the historical buffer. Une fois que vous avez déterminé l’heure de début et la durée de votre choix, appelez RecordTimeSpanToFileAsync pour démarrer l’opération d’enregistrement.Once you have determined your desired start time and duration, call RecordTimeSpanToFileAsync to start the recording operation.

Comme pour l’enregistrement avec un démarrage et un arrêt manuels, quand un enregistrement historique est terminé, vous pouvez vérifier la propriété Succeeded de l’objet AppRecordingResult retourné pour déterminer si l’opération d’enregistrement a réussi, et vous pouvez vérifier la propriété IsFileTruncated et Duration pour découvrir la durée réelle du fichier enregistré qui, si le fichier est tronqué, peut être plus petite que la durée de la fenêtre de temps demandée.Like recording with manual start and stop, when a historical recording completes, you can check the Succeeded property of the returned AppRecordingResult object to determine if the record operation was successful, and you can check the IsFileTruncated and Duration property to discover the actual duration of the recorded file which, if the file is truncated, may be shorter than the duration of the requested time window.

void App::RecordTimeSpanToFile(Windows::Storage::StorageFile^ file)
{


    if (m_appRecordingManager == nullptr)
    {
        return;
    }

    if (!CanRecord())
    {
        return;
    }

    Windows::Foundation::TimeSpan historicalBufferDuration;
    if (!CanRecordTimeSpan(historicalBufferDuration))
    {
        return;
    }
    

    AppRecordingStatus^ recordingStatus = m_appRecordingManager->GetStatus();
    
    Windows::Globalization::Calendar^ calendar = ref new Windows::Globalization::Calendar();
    calendar->SetToNow();

    Windows::Foundation::DateTime nowTime = calendar->GetDateTime();

    int secondsToRecord = min(30, historicalBufferDuration.Duration / 10000000);
    calendar->AddSeconds(-1 * secondsToRecord);

    Windows::Foundation::DateTime  startTime = calendar->GetDateTime();

    Windows::Foundation::TimeSpan duration;

    duration.Duration = nowTime.UniversalTime - startTime.UniversalTime;

    create_task(m_appRecordingManager->RecordTimeSpanToFileAsync(startTime, duration, file)).then(
        [this](AppRecordingResult^ result)
    {
        if (result->Succeeded)
        {
            Windows::Foundation::TimeSpan duration = result->Duration;
            boolean isTruncated = result->IsFileTruncated;
            UpdateStatusText("Recording completed.");
        }
        else
        {
            // If the recording failed, ExtendedError
            // can be retrieved and used for diagnostic purposes
            HResult extendedError = result->ExtendedError;
            LogTelemetryMessage("Error during recording: " + extendedError);
        }
    });

}

L’exemple suivant montre un code de base pour initialiser l’opération d’enregistrement d’historique indiquée dans l’exemple précédent.The following example shows some basic code for initiating the historical record operation shown in the previous example.

StorageFolder^ storageFolder = ApplicationData::Current->LocalFolder;
concurrency::create_task(storageFolder->CreateFileAsync("recordtimespantofile_example.mp4", CreationCollisionOption::ReplaceExisting)).then(
    [this](StorageFile^ file)
{
    RecordTimeSpanToFile(file);
});

Enregistrer les images de capture d’écran dans des fichiersSave screenshot images to files

Votre application peut lancer une capture de capture d’écran qui permet d’enregistrer le contenu actuel de la fenêtre de l’application dans un fichier image ou dans plusieurs fichiers image avec des encodages d’image différents.Your app can initiate a screenshot capture that will save the current contents of the app's window to one image file or to multiple image files with different image encodings. Pour spécifier les encodages d’image que vous souhaitez utiliser, créez une liste de chaînes où chacune représente un type d’image.To specify the image encodings you would like to use, create a list of strings where each represents an image type. Les propriétés du ImageEncodingSubtypes fournissent la chaîne correcte pour chaque type d’image pris en charge, par exemple MediaEncodingSubtypes.Png ou MediaEncodingSubtypes. JpegXr.The properties of the ImageEncodingSubtypes provide the correct string for each supported image type, such as MediaEncodingSubtypes.Png or MediaEncodingSubtypes.JpegXr.

Lancez la capture d’écran en appelant la méthode SaveScreenshotToFilesAsync de l’objet AppRecordingManager .Initiate screen capture by calling the SaveScreenshotToFilesAsync method of the AppRecordingManager object. Le premier paramètre de cette méthode est un StorageFolder dans lequel les fichiers image seront enregistrés.The first parameter to this method is a StorageFolder where the image files will be saved. Le deuxième paramètre est un préfixe de nom de fichier auquel le système ajoute l’extension pour chaque type d’image enregistré, par exemple « . png ».The second parameter is a filename prefix to which the system will append the extension for each image type saved, such as ".png".

Le troisième paramètre de SaveScreenshotToFilesAsync est nécessaire pour que le système puisse effectuer la conversion colorspace appropriée si la fenêtre en cours à capturer affiche le contenu HDR.The third parameter to SaveScreenshotToFilesAsync is necessary for the system to be able to do the proper colorspace conversion if the current window to be captured is displaying HDR content. Si le contenu HDR est présent, ce paramètre doit être défini sur AppRecordingSaveScreenshotOption. HdrContentVisible.If HDR content is present, this parameter should be set to AppRecordingSaveScreenshotOption.HdrContentVisible. Sinon, utilisez AppRecordingSaveScreenshotOption. None.Otherwise, use AppRecordingSaveScreenshotOption.None. Le dernier paramètre de la méthode est la liste des formats d’image sur lesquels l’écran doit être capturé.The final parameter to the method is the list of image formats to which the screen should be captured.

Lorsque l’appel asynchrone à SaveScreenshotToFilesAsync se termine, il retourne un objet AppRecordingSavedScreenshotInfo qui fournit le StorageFile et la valeur MediaEncodingSubtypes associée indiquant le type d’image pour chaque image enregistrée.When the asynchronous call to SaveScreenshotToFilesAsync completes, it returns a AppRecordingSavedScreenshotInfo object that provides the StorageFile and associated MediaEncodingSubtypes value indicating the image type for each saved image.

void App::SaveScreenShotToFiles(Windows::Storage::StorageFolder^ folder, Platform::String^ filenamePrefix)
{

    if (m_appRecordingManager == nullptr)
    {
        return;
    }


    Windows::Foundation::Collections::IVectorView<Platform::String^>^ supportedFormats = 
        m_appRecordingManager->SupportedScreenshotMediaEncodingSubtypes;

    
    Platform::Collections::Vector<Platform::String^>^ requestedFormats = 
        ref new Platform::Collections::Vector<Platform::String^>();

    for (Platform::String^ format : requestedFormats)
    {
        if (format == Windows::Media::MediaProperties::MediaEncodingSubtypes::Png)
        {
            requestedFormats->Append(format);
        }
        else if (format == Windows::Media::MediaProperties::MediaEncodingSubtypes::JpegXr)
        {
            requestedFormats->Append(format);
        }
    }


    create_task(m_appRecordingManager->SaveScreenshotToFilesAsync(folder, filenamePrefix, AppRecordingSaveScreenshotOption::None,
        requestedFormats->GetView())).then(
            [this](AppRecordingSaveScreenshotResult^ result)
    {
        if (result->Succeeded)
        {
            Windows::Foundation::Collections::IVectorView<AppRecordingSavedScreenshotInfo^>^ returnedScreenshots = result->SavedScreenshotInfos;

            for (AppRecordingSavedScreenshotInfo^ screenshotInfo : returnedScreenshots)
            {
                Windows::Storage::StorageFile^ file = screenshotInfo->File;
                Platform::String^ type = screenshotInfo->MediaEncodingSubtype;
            }
        }
        else
        {
            // If the recording failed, ExtendedError 
            // can be retrieved and used for diagnostic purposes 
            HResult extendedError = result->ExtendedError;
            LogTelemetryMessage("Error during screenshot: " + extendedError);
        }
    });
}

L’exemple suivant montre un code de base pour initialiser l’opération de capture d’écran illustrée dans l’exemple précédent.The following example shows some basic code for initiating the screenshot operation shown in the previous example.

StorageFolder^ storageFolder = ApplicationData::Current->LocalFolder;
SaveScreenShotToFiles(storageFolder, "screen_capture");

Ajouter des métadonnées de jeu pour la capture initiée par le système et l’applicationAdd game metadata for system and app-initiated capture

Les sections suivantes de cet article décrivent comment fournir des métadonnées incorporées par le système dans le flux MP4 de la capture ou du jeu de diffusion.The following sections of this article describe how to provide metadata that the system will embed into the MP4 stream of captured or broadcast gameplay. Les métadonnées peuvent être incorporées dans un média capturé à l’aide de l’interface utilisateur et du média intégrés capturés par l’application avec AppRecordingManager.Metadata can be embedded in media that is captured using the built-in system UI and media that is captured by the app with AppRecordingManager. Ces métadonnées peuvent être extraites par votre application et d’autres applications pendant la lecture du média afin de fournir des expériences contextuelles qui sont synchronisées avec le jeu capturé ou diffusé.This metadata can be extracted by your app and other apps during media playback in order to provide contextually-aware experiences that are synchronized with the captured or broadcast gameplay.

Obtient une instance de AppCaptureMetadataWriterGet an instance of AppCaptureMetadataWriter

La classe principale pour la gestion des métadonnées de capture d’application est AppCaptureMetadataWriter.The primary class for managing app capture metadata is AppCaptureMetadataWriter. Avant d’initialiser une instance de cette classe, utilisez la méthode ApiInformation. IsApiContractPresent pour rechercher la version 1,0 de Windows. Media. capture. AppCaptureMetadataContract afin de vérifier que l’API est disponible sur l’appareil actuel.Before initializing an instance of this class, use the ApiInformation.IsApiContractPresent method to query for the Windows.Media.Capture.AppCaptureMetadataContract version 1.0 to verify that the API is available on the current device.

if (Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent("Windows.Media.Capture.AppCaptureMetadataContract", 1, 0))
{
    m_appCaptureMetadataWriter = ref new AppCaptureMetadataWriter();
}

Écrire des métadonnées dans le cache système de votre applicationWrite metadata to the system cache for your app

Chaque élément de métadonnées a une étiquette de chaîne, identifiant l’élément de métadonnées, une valeur de données associée qui peut être une chaîne, un entier ou une valeur double, et une valeur de l’énumération AppCaptureMetadataPriority indiquant la priorité relative de l’élément de données.Each metadata item has a string label, identifying the metadata item, an associated data value which can be a string, an integer, or a double value, and a value from the AppCaptureMetadataPriority enumeration indicating the relative priority of the data item. Un élément de métadonnées peut être considéré comme un « événement », qui se produit à un point unique dans le temps, ou un « État » qui maintient une valeur sur une fenêtre de temps.A metadata item can either be considered an "event", which occurs at a single point in time, or a "state" which maintains a value over a time window. Les métadonnées sont écrites dans un cache mémoire qui est alloué et géré pour votre application par le système.Metadata is written to a memory cache that is allocated and managed for your app by the system. Le système applique une limite de taille sur le cache mémoire des métadonnées et, lorsque la limite est atteinte, purge les données en fonction de la priorité avec laquelle chaque élément de métadonnées a été écrit.The system enforces a size limit on the metadata memory cache and, when the limit is reached, will purge data based on the priority with which each metadata item was written. La section suivante de cet article explique comment gérer l’allocation de mémoire de métadonnées de votre application.The next section of this article shows how to manage your app's metadata memory allocation.

Une application classique peut choisir d’écrire des métadonnées au début de la session de capture pour fournir un contexte pour les données suivantes.A typical app may choose to write some metadata at the beginning of the capture session to provide some context for the subsequent data. Pour ce scénario, il est recommandé d’utiliser les données instantanées « événement ».For this scenario it is recommended that you use instantaneous "event" data. Cet exemple appelle AddStringEvent, AddDoubleEvent et AddInt32Event pour définir des valeurs instantanées pour chaque type de données.This example calls AddStringEvent, AddDoubleEvent, and AddInt32Event to set instantaneous values for each data type.

void App::StartSession(Platform::String^ sessionId, double averageFps, int resolutionWidth, int resolutionHeight)
{
    if (m_appCaptureMetadataWriter != nullptr)
    {
        m_appCaptureMetadataWriter->AddStringEvent("sessionId", sessionId, AppCaptureMetadataPriority::Informational);
        m_appCaptureMetadataWriter->AddDoubleEvent("averageFps", averageFps, AppCaptureMetadataPriority::Informational);
        m_appCaptureMetadataWriter->AddInt32Event("resolutionWidth", resolutionWidth, AppCaptureMetadataPriority::Informational);
        m_appCaptureMetadataWriter->AddInt32Event("resolutionHeight", resolutionHeight, AppCaptureMetadataPriority::Informational);
    }
}

Un scénario courant pour l’utilisation de données d’État qui persistent au fil du temps consiste à effectuer le suivi de la carte de jeu dans laquelle se trouve actuellement le joueur.A common scenario for using "state" data that persists over time is to track the game map that the player is currently within. Cet exemple appelle StartStringState pour définir la valeur d’État.This example calls StartStringState to set the state value.

void App::StartMap(Platform::String^ mapName)
{
    m_appCaptureMetadataWriter->StartStringState("map", mapName, AppCaptureMetadataPriority::Important);
}

Appelez StopState pour enregistrer qu’un état particulier s’est terminé.Call StopState to record that a particular state has ended.

void App::EndMap(Platform::String^ mapName)
{
    m_appCaptureMetadataWriter->StopState("map");
}

Vous pouvez remplacer un État en définissant une nouvelle valeur avec une étiquette d’État existante.You can overwrite a state by setting a new value with an existing state label.

void App::LevelUp(int newLevel)
{
    m_appCaptureMetadataWriter->StartInt32State("currentLevel", newLevel, AppCaptureMetadataPriority::Important);
}

Vous pouvez terminer tous les États actuellement ouverts en appelant StopAllStates.You can end all currently open states by calling StopAllStates.

void App::RaceComplete()
{
    m_appCaptureMetadataWriter->StopAllStates();
}

Gérer la limite de stockage du cache des métadonnéesManage metadata cache storage limit

Les métadonnées que vous écrivez avec AppCaptureMetadataWriter sont mises en cache par le système jusqu’à ce qu’elles soient écrites dans le flux multimédia associé.The metadata that you write with AppCaptureMetadataWriter is cached by the system until it is written to the associated media stream. Le système définit une limite de taille pour le cache des métadonnées de chaque application.The system defines a size limit for each app's metadata cache. Une fois la limite de taille du cache atteinte, le système commence à purger les métadonnées mises en cache.Once the cache size limit has been reached, the system will begin purging cached metadata. Le système supprimera les métadonnées écrites avec la valeur de priorité AppCaptureMetadataPriority. informatif avant de supprimer les métadonnées avec la priorité AppCaptureMetadataPriority. important .The system will delete metadata that was written with AppCaptureMetadataPriority.Informational priority value before deleting metadata with the AppCaptureMetadataPriority.Important priority.

À tout moment, vous pouvez vérifier le nombre d’octets disponibles dans le cache de métadonnées de votre application en appelant RemainingStorageBytesAvailable.At any point, you can check to see the number of bytes available in your app's metadata cache by calling RemainingStorageBytesAvailable. Vous pouvez choisir de définir votre propre seuil défini par l’application après lequel vous pouvez choisir de réduire la quantité de métadonnées que vous écrivez dans le cache.You can choose to set your own app-defined threshold after which you can choose to reduce the amount of metadata that you write to the cache. L’exemple suivant illustre une implémentation simple de ce modèle.The following example shows a simple implementation of this pattern.

void App::CheckMetadataStorage()
{
    INT64 storageRemaining = m_appCaptureMetadataWriter->RemainingStorageBytesAvailable;

    if (storageRemaining < m_myLowStorageLevelInBytes)
    {
        m_writeLowPriorityMetadata = false;
    }
}
void App::ComboExecuted(Platform::String^ comboName)
{
    if (m_writeLowPriorityMetadata)
    {
        m_appCaptureMetadataWriter->AddStringEvent("combo", comboName, AppCaptureMetadataPriority::Informational);
    }
}

Recevoir des notifications lorsque le système purge les métadonnéesReceive notifications when the system purges metadata

Vous pouvez vous inscrire pour recevoir une notification lorsque le système commence à purger les métadonnées de votre application en inscrivant un gestionnaire pour l’événement MetadataPurged .You can register to receive a notification when the system begins purging metadata for your app by registering a handler for the MetadataPurged event.

if (m_appCaptureMetadataWriter != nullptr)
{
    m_appCaptureMetadataWriter->MetadataPurged += 
        ref new TypedEventHandler<AppCaptureMetadataWriter^, Platform::Object^>(this, &App::OnMetadataPurged);

}

Dans le gestionnaire de l’événement MetadataPurged , vous pouvez libérer de la place dans le cache des métadonnées en terminant les États de priorité inférieure, vous pouvez implémenter une logique définie par l’application pour réduire la quantité de métadonnées que vous écrivez dans le cache, ou vous pouvez faire en sorte que le système continue de vider le cache en fonction de la priorité avec laquelle il a été écrit.In the handler for the MetadataPurged event, you can clear up some room in the metadata cache by ending lower-priority states, you can implement app-defined logic for reducing the amount of metadata you write to the cache, or you can do nothing and let the system continue to purge the cache based on the priority with which it was written.

void App::OnMetadataPurged(Windows::Media::Capture::AppCaptureMetadataWriter^ sender, Platform::Object^ args)
{
    // Reduce metadata by stopping a low-priority state.
    //m_appCaptureMetadataWriter->StopState("map");

    // Reduce metadata by stopping all states.
    //m_appCaptureMetadataWriter->StopAllStates();

    // Change app-specific behavior to write less metadata.
    //m_writeLowPriorityMetadata = false;

    // Take no action. Let the system purge data as needed. Record event for telemetry.
    OutputDebugString(TEXT("Low-priority metadata purged."));

}