Acquisire i metadati, gli screenshot, i video e gli audio dei giochiCapture game audio, video, screenshots, and metadata

Questo articolo descrive come acquisire video, audio e schermate di gioco e come inviare metadati che verranno incorporati dal sistema in supporti acquisiti e broadcast, consentendo all'app e ad altri utenti di creare esperienze dinamiche sincronizzate con gli eventi di gioco.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.

È possibile acquisire il gameplay in due modi diversi in un'app UWP.There are two different ways that gameplay can be captured in a UWP app. L'utente può avviare l'acquisizione usando l'interfaccia utente predefinita del sistema.The user can initiate capture using the built-in system UI. I supporti acquisiti con questa tecnica vengono inseriti nell'ecosistema di giochi Microsoft, possono essere visualizzati e condivisi attraverso esperienze di prima parte, ad esempio l'app Xbox, e non sono direttamente disponibili per l'app o per gli utenti.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. Nelle prime sezioni di questo articolo viene illustrato come abilitare e disabilitare l'acquisizione di app implementate dal sistema e come ricevere notifiche quando l'acquisizione dell'app viene avviata o arrestata.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'altro modo per acquisire i supporti consiste nell'usare le API dello spazio dei nomi Windows. Media. AppRecording .The other way to capture media is to use the APIs of the Windows.Media.AppRecording namespace. Se l'acquisizione è abilitata nel dispositivo, l'app può avviare l'acquisizione del gameplay e quindi, dopo che è trascorso un certo tempo, è possibile arrestare l'acquisizione, a quel punto il supporto viene scritto in un file.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. Se l'utente ha abilitato l'acquisizione cronologica, è anche possibile registrare la giocabilità già eseguita specificando un'ora di inizio nel passato e una durata da registrare.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. Entrambe queste tecniche producono un file video a cui è possibile accedere dall'app e a seconda di dove si sceglie di salvare i file dall'utente.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. Le sezioni centrali di questo articolo illustrano i implementazione di questi scenari.The middle sections of this article walk you through the implemenation of these scenarios.

Lo spazio dei nomi Windows. Media. Capture fornisce le API per la creazione di metadati che descrivono il gameplay acquisito o trasmesso.The Windows.Media.Capture namespace provides APIs for creating metadata that describes the gameplay being captured or broadcast. Può includere valori di testo o numerici, con un'etichetta di testo che identifica ogni elemento di dati.This can include text or numeric values, with a text label identifying each data item. I metadati possono rappresentare un evento che si verifica in un singolo momento, ad esempio quando l'utente termina un giro in un gioco da corsa oppure può rappresentare uno "stato" che persiste in un intervallo di tempo, ad esempio la mappa del gioco corrente in cui l'utente sta giocando.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. I metadati vengono scritti in una cache allocata e gestita per l'app dal sistema.The metadata is written to a cache that is allocated and managed for your app by the system. I metadati sono incorporati in flussi broadcast e file video acquisiti, incluse le tecniche di acquisizione di sistema predefinite o di acquisizione di app personalizzate.The metadata is embedded into broadcast streams and captured video files, including both the built-in system capture or custom app capture techniques. Le sezioni finali di questo articolo illustrano come scrivere i metadati di gioco.The final sections of this article show you how to write gameplay metadata.

Nota

Poiché i metadati del gameplay possono essere incorporati in file multimediali che possono essere potenzialmente condivisi in rete, dal controllo dell'utente, non è consigliabile includere informazioni personali o altri dati potenzialmente sensibili nei metadati.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.

Abilitare e disabilitare l'acquisizione di app di sistemaEnable and disable system app capture

L'acquisizione di app di sistema viene avviata dall'utente con l'interfaccia utente del sistema incorporata.System app capture is initiated by the user with the built-in system UI. I file vengono inseriti dall'ecosistema di Windows Gaming e non sono disponibili per l'app o per l'utente, tranne che per le esperienze di prima entità come l'app 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. L'app può disabilitare e abilitare l'acquisizione di app avviata dal sistema, consentendo di impedire all'utente di acquisire contenuto o gameplay specifico.Your app can disable and enable system-initiated app capture, allowing you to prevent the user from capturing certain content or gameplay.

Per abilitare o disabilitare l'acquisizione di app di sistema, è sufficiente chiamare il metodo statico AppCapture. SetAllowedAsync e passare false per disabilitare Capture o true per abilitare l'acquisizione.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);

Ricevere notifiche quando l'acquisizione dell'app di sistema viene avviata e arrestataReceive notifications when system app capture starts and stops

Per ricevere una notifica quando l'acquisizione dell'app di sistema inizia o termina, prima di tutto ottenere un'istanza della classe AppCapture chiamando il metodo factory 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. Registrare quindi un gestore per l'evento 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);

Nel gestore per l'evento CapturingChanged è possibile controllare le proprietà IsCapturingAudio e IsCapturingVideo per determinare se vengono acquisiti rispettivamente audio o video.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. Potrebbe essere necessario aggiornare l'interfaccia utente dell'app per indicare lo stato di acquisizione corrente.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);
}

Aggiungere le estensioni desktop di Windows per il UWP all'appAdd the Windows Desktop Extensions for the UWP to your app

Le API per la registrazione di audio e video e per l'acquisizione di schermate direttamente dall'app, disponibili nello spazio dei nomi Windows. Media. AppRecording , non sono incluse nel contratto API universale.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. Per accedere alle API, è necessario aggiungere un riferimento alle estensioni desktop di Windows per il UWP all'app con i passaggi seguenti.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. In Visual Studio, in Esplora soluzioni, espandere il progetto UWP e fare clic con il pulsante destro del mouse su riferimenti , quindi scegliere Aggiungi riferimento.In Visual Studio, in Solution Explorer, expand your UWP project and right-click References and then select Add Reference....
  2. Espandere il nodo Windows universale e selezionare estensioni.Expand the Universal Windows node and select Extensions.
  3. Nell'elenco di estensioni selezionare la casella di controllo accanto alle estensioni desktop di Windows per la voce UWP che corrisponde alla build di destinazione per il progetto.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. Per le funzionalità di broadcast delle app, la versione deve essere 1709 o successiva.For the app broadcast features, the version must be 1709 or greater.
  4. Fare clic su OK.Click OK.

Ottenere un'istanza di AppRecordingManagerGet an instance of AppRecordingManager

La classe AppRecordingManager è l'API centrale che verrà usata per gestire la registrazione delle app.The AppRecordingManager class is the central API you will use to manage app recording. Ottenere un'istanza di questa classe chiamando il metodo factory GetDefault.Get an instance of this class by calling the factory method GetDefault. Prima di usare le API nello spazio dei nomi Windows. Media. AppRecording , è necessario verificare la presenza nel dispositivo corrente.Before using any of the APIs in the Windows.Media.AppRecording namespace, you should check for their presence on the current device. Le API non sono disponibili nei dispositivi che eseguono una versione del sistema operativo precedente a Windows 10, versione 1709.The APIs are not available on devices running an OS version earlier than Windows 10, version 1709. Anziché verificare la presenza di una versione specifica del sistema operativo, usare il metodo ApiInformation. IsApiContractPresent per eseguire una query per Windows. Media. AppBroadcasting. AppRecordingContract versione 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. Se il contratto è presente, le API di registrazione sono disponibili nel dispositivo.If this contract is present, then the recording APIs are available on the device. Il codice di esempio in questo articolo controlla le API una sola volta e quindi controlla se AppRecordingManager è null prima delle operazioni successive.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();
}

Determinare se l'app può attualmente registrareDetermine if your app can currently record

Esistono diversi motivi per cui l'app potrebbe non essere attualmente in grado di acquisire audio o video, incluso se il dispositivo corrente non soddisfa i requisiti hardware per la registrazione o se un'altra app è attualmente in fase di trasmissione.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. Prima di avviare una registrazione, è possibile verificare se l'app è attualmente in grado di registrare.Before initiating a recording, you can check to see if your app is currently able to record. Chiamare il metodo GetStatus dell'oggetto AppRecordingManager , quindi controllare la proprietà CanRecord dell'oggetto AppRecordingStatus restituito.Call the GetStatus method of the AppRecordingManager object and then check the CanRecord property of the returned AppRecordingStatus object. Se CanRecord restituisce false, vale a dire che l'app non può attualmente registrare, è possibile controllare la proprietà Details per determinare il motivo.If CanRecord returns false, meaning that your app can't currently record, you can check the Details property to determine the reason. A seconda del motivo, potrebbe essere necessario visualizzare lo stato all'utente o visualizzare le istruzioni per abilitare la registrazione delle app.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;
}

Avviare e arrestare manualmente la registrazione dell'applicazione in un fileManually start and stop recording your app to a file

Dopo aver verificato che l'app è in grado di registrare, è possibile avviare una nuova registrazione chiamando il metodo StartRecordingToFileAsync dell'oggetto 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.

Nell'esempio seguente viene eseguito il primo blocco then quando l'attività asincrona ha esito negativo.In the following example, the first then block executes when the asynchronous task fails. Il secondo blocco then tenta di accedere al risultato dell'attività e, se il risultato è null, l'attività è stata completata.The second then block attempts to access the result of the task and, if the result is null, then the task has completed. In entrambi i casi, per gestire il risultato viene chiamato il metodo helper OnRecordingComplete , illustrato di seguito.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();
        }
    });
}

Al termine dell'operazione di registrazione, controllare la proprietà succeeded dell'oggetto AppRecordingResult restituito per determinare se l'operazione di record è stata eseguita correttamente.When the recording operation completes, check the Succeeded property of the returned AppRecordingResult object to determine if the record operation was successful. In tal caso, è possibile controllare la proprietà IsFileTruncated per determinare se, per motivi di archiviazione, il sistema è stato forzato a troncare il file acquisito.If so, you can check the IsFileTruncated property to determine if, for storage reasons, the system was forced to truncate the captured file. È possibile controllare la proprietà Duration per individuare la durata effettiva del file registrato che, se il file è troncato, potrebbe essere più breve della durata dell'operazione di registrazione.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;
    }
}

Gli esempi seguenti illustrano un codice di base per l'avvio e l'arresto dell'operazione di registrazione illustrata nell'esempio precedente.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();
}

Registrare un intervallo di tempo cronologico in un fileRecord a historical time span to a file

Se l'utente ha abilitato la registrazione cronologica per l'app nelle impostazioni di sistema, è possibile registrare un intervallo di tempo del gameplay che è stato precedentemente verificato.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 esempio precedente in questo articolo ha illustrato come verificare che l'app possa attualmente registrare il gioco.A previous example in this article showed how to confirm that your app can currently record gameplay. È presente un controllo aggiuntivo per determinare se l'acquisizione cronologica è abilitata.There is an additional check to determine if historical capture is enabled. Ancora una volta, chiamare GetStatus e controllare la proprietà CanRecordTimeSpan dell'oggetto AppRecordingStatus restituito.Once again, call GetStatus and check the CanRecordTimeSpan property of the returned AppRecordingStatus object. In questo esempio viene inoltre restituita la proprietà HistoricalBufferDuration di AppRecordingStatus che verrà utilizzata per determinare un'ora di inizio valida per l'operazione di registrazione.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;
}

Per acquisire un intervallo di tempo cronologico, è necessario specificare un'ora di inizio per la registrazione e una durata.To capture a historical timespan, you must specify a start time for the recording and a duration. L'ora di inizio viene fornita come struct DateTime .The start time is provided as a DateTime struct. L'ora di inizio deve essere precedente all'ora corrente, entro la lunghezza del buffer di registrazione cronologico.The start time must be a time before the current time, within the length of the historical recording buffer. Per questo esempio, la lunghezza del buffer viene recuperata come parte del controllo per verificare se la registrazione cronologica è abilitata, come illustrato nell'esempio di codice precedente.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 durata della registrazione cronologica viene fornita come struct TimeSpan , che deve essere anche uguale o inferiore alla durata del buffer cronologico.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. Dopo aver determinato l'ora di inizio e la durata desiderate, chiamare RecordTimeSpanToFileAsync per avviare l'operazione di registrazione.Once you have determined your desired start time and duration, call RecordTimeSpanToFileAsync to start the recording operation.

Analogamente alla registrazione con avvio manuale e arresto, quando una registrazione cronologica viene completata, è possibile controllare la proprietà succeeded dell'oggetto AppRecordingResult restituito per determinare se l'operazione di registrazione è stata completata correttamente ed è possibile controllare la proprietà IsFileTruncated e Duration per individuare la durata effettiva del file registrato che, se il file è troncato, potrebbe essere più breve della durata dell'intervallo di tempo richiesto.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);
        }
    });

}

Nell'esempio seguente viene illustrato il codice di base per l'avvio dell'operazione di record cronologico illustrata nell'esempio precedente.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);
});

Salva immagini screenshot in fileSave screenshot images to files

L'app può avviare un'acquisizione di screenshot che consente di salvare il contenuto corrente della finestra dell'app in un file di immagine o in più file di immagine con codifiche di immagini diverse.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. Per specificare le codifiche delle immagini che si vuole usare, creare un elenco di stringhe in cui ogni rappresenta un tipo di immagine.To specify the image encodings you would like to use, create a list of strings where each represents an image type. Le proprietà di ImageEncodingSubtypes forniscono la stringa corretta per ogni tipo di immagine supportato, ad esempio MediaEncodingSubtypes.Png o MediaEncodingSubtypes. JpegXr.The properties of the ImageEncodingSubtypes provide the correct string for each supported image type, such as MediaEncodingSubtypes.Png or MediaEncodingSubtypes.JpegXr.

Avviare l'acquisizione schermo chiamando il metodo SaveScreenshotToFilesAsync dell'oggetto AppRecordingManager .Initiate screen capture by calling the SaveScreenshotToFilesAsync method of the AppRecordingManager object. Il primo parametro di questo metodo è StorageFolder in cui verranno salvati i file di immagine.The first parameter to this method is a StorageFolder where the image files will be saved. Il secondo parametro è un prefisso filename a cui il sistema aggiungerà l'estensione per ogni tipo di immagine salvato, ad esempio ". png".The second parameter is a filename prefix to which the system will append the extension for each image type saved, such as ".png".

Il terzo parametro di SaveScreenshotToFilesAsync è necessario affinché il sistema sia in grado di eseguire la conversione dello spazio dei colore corretta se la finestra corrente da acquisire sta visualizzando il contenuto 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. Se è presente contenuto HDR, questo parametro deve essere impostato su AppRecordingSaveScreenshotOption. HdrContentVisible.If HDR content is present, this parameter should be set to AppRecordingSaveScreenshotOption.HdrContentVisible. In caso contrario, utilizzare AppRecordingSaveScreenshotOption. None.Otherwise, use AppRecordingSaveScreenshotOption.None. Il parametro finale per il metodo è l'elenco dei formati di immagine in cui deve essere acquisita la schermata.The final parameter to the method is the list of image formats to which the screen should be captured.

Quando la chiamata asincrona a SaveScreenshotToFilesAsync viene completata, restituisce un oggetto AppRecordingSavedScreenshotInfo che fornisce StorageFile e il valore MediaEncodingSubtypes associato che indica il tipo di immagine per ogni immagine salvata.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);
        }
    });
}

Nell'esempio seguente viene illustrato il codice di base per l'avvio dell'operazione screenshot illustrata nell'esempio precedente.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");

Aggiungere i metadati del gioco per l'acquisizione avviata dal sistema e dall'appAdd game metadata for system and app-initiated capture

Le sezioni seguenti di questo articolo descrivono come fornire i metadati che verranno incorporati dal sistema nel flusso MP4 del gameplay acquisito o trasmesso.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. I metadati possono essere incorporati nei supporti acquisiti usando l'interfaccia utente e i supporti di sistema incorporati acquisiti dall'app con 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. Questi metadati possono essere estratti dall'app e da altre app durante la riproduzione multimediale per fornire esperienze compatibili con il contesto sincronizzate con il gameplay acquisito o trasmesso.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.

Ottenere un'istanza di AppCaptureMetadataWriterGet an instance of AppCaptureMetadataWriter

La classe primaria per la gestione dei metadati di acquisizione delle app è AppCaptureMetadataWriter.The primary class for managing app capture metadata is AppCaptureMetadataWriter. Prima di inizializzare un'istanza di questa classe, utilizzare il metodo ApiInformation. IsApiContractPresent per eseguire una query per Windows. Media. Capture. AppCaptureMetadataContract versione 1,0 per verificare che l'API sia disponibile nel dispositivo corrente.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();
}

Scrivere i metadati nella cache di sistema per l'appWrite metadata to the system cache for your app

Ogni elemento di metadati ha un'etichetta stringa che identifica l'elemento dei metadati, un valore di dati associato che può essere una stringa, un numero intero o un valore Double e un valore dell'enumerazione AppCaptureMetadataPriority che indica la priorità relativa dell'elemento dati.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 elemento dei metadati può essere considerato un "evento", che si verifica in un singolo momento, o "stato", che mantiene un valore in un intervallo di tempo.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. I metadati vengono scritti in una cache in memoria che viene allocata e gestita per l'app dal sistema.Metadata is written to a memory cache that is allocated and managed for your app by the system. Il sistema impone un limite di dimensioni per la cache della memoria dei metadati e, quando viene raggiunto il limite, eliminerà i dati in base alla priorità con cui è stato scritto ogni elemento di metadati.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 sezione successiva di questo articolo illustra come gestire l'allocazione di memoria dei metadati dell'app.The next section of this article shows how to manage your app's metadata memory allocation.

Una tipica app può scegliere di scrivere alcuni metadati all'inizio della sessione di acquisizione per fornire un contesto per i dati successivi.A typical app may choose to write some metadata at the beginning of the capture session to provide some context for the subsequent data. Per questo scenario è consigliabile usare dati "evento" istantanei.For this scenario it is recommended that you use instantaneous "event" data. In questo esempio vengono chiamati AddStringEvent, AddDoubleEvent e AddInt32Event per impostare i valori istantanei per ogni tipo di dati.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);
    }
}

Uno scenario comune per l'uso dei dati di "stato" che viene mantenuto nel tempo è quello di tenere traccia della mappa del gioco in cui si trova attualmente il lettore.A common scenario for using "state" data that persists over time is to track the game map that the player is currently within. Questo esempio chiama StartStringState per impostare il valore di stato.This example calls StartStringState to set the state value.

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

Chiamare StopState per registrare il termine di un determinato stato.Call StopState to record that a particular state has ended.

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

È possibile sovrascrivere uno stato impostando un nuovo valore con un'etichetta di stato esistente.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);
}

È possibile terminare tutti gli Stati attualmente aperti chiamando StopAllStates.You can end all currently open states by calling StopAllStates.

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

Gestire il limite di archiviazione della cache dei metadatiManage metadata cache storage limit

I metadati scritti con AppCaptureMetadataWriter vengono memorizzati nella cache dal sistema fino a quando non vengono scritti nel flusso multimediale associato.The metadata that you write with AppCaptureMetadataWriter is cached by the system until it is written to the associated media stream. Il sistema definisce un limite di dimensioni per la cache dei metadati di ogni app.The system defines a size limit for each app's metadata cache. Una volta raggiunto il limite delle dimensioni della cache, il sistema inizierà a eliminare i metadati memorizzati nella cache.Once the cache size limit has been reached, the system will begin purging cached metadata. Il sistema eliminerà i metadati scritti con il valore di priorità AppCaptureMetadataPriority. Informational prima di eliminare i metadati con AppCaptureMetadataPriority. priorità importante .The system will delete metadata that was written with AppCaptureMetadataPriority.Informational priority value before deleting metadata with the AppCaptureMetadataPriority.Important priority.

In qualsiasi momento, è possibile controllare per visualizzare il numero di byte disponibili nella cache dei metadati dell'app chiamando RemainingStorageBytesAvailable.At any point, you can check to see the number of bytes available in your app's metadata cache by calling RemainingStorageBytesAvailable. È possibile scegliere di impostare una soglia definita dall'app dopo la quale è possibile scegliere di ridurre la quantità di metadati scritti nella 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. Nell'esempio seguente viene illustrata una semplice implementazione di questo modello.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);
    }
}

Ricevere notifiche quando il sistema elimina i metadatiReceive notifications when the system purges metadata

È possibile eseguire la registrazione per ricevere una notifica quando il sistema inizia a eliminare i metadati per l'app registrando un gestore per l'evento 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);

}

Nel gestore per l'evento MetadataPurged , è possibile eliminare alcuni spazio nella cache dei metadati terminando gli Stati di priorità inferiore, è possibile implementare la logica definita dall'app per ridurre la quantità di metadati scritti nella cache oppure non è possibile eseguire alcuna operazione e consentire al sistema di continuare a ripulire la cache in base alla priorità con cui è stata scritta.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."));

}