Condividi tramite


Acquisire i metadati, gli screenshot, i video e gli audio dei giochi

Questo articolo descrive come acquisire video, audio e screenshot del gioco e come inviare metadati che il sistema incorpora nei supporti acquisiti e trasmessi, consentendo all'app e ad altri di creare esperienze dinamiche sincronizzate con gli eventi del gioco.

Esistono due modi diversi per acquisire il gioco in un'app UWP. L'utente può avviare l'acquisizione usando l'interfaccia utente di sistema predefinita. I contenuti multimediali acquisiti con questa tecnica vengono inseriti nell'ecosistema di giochi Microsoft, possono essere visualizzati e condivisi tramite esperienze di prima parte come il app Xbox e non sono direttamente disponibili per l'app o per gli utenti. Le prime sezioni di questo articolo illustrano come attivare e disattivare l'acquisizione di app implementate dal sistema e come ricevere notifiche all'avvio o all'arresto dell'acquisizione di app.

L'altro modo per acquisire contenuti multimediali consiste nell'usare le API dello spazio dei nomi Windows.Media.AppRecording. Se l'acquisizione è attivata nel dispositivo, l'app può avviarla e, passato del tempo, è possibile arrestarla, dopo di che verrà scritta in un file. Se l'utente ha abilitato l'acquisizione cronologica, è anche possibile registrare il gioco che si è già verificato specificando un'ora di inizio nel passato e una durata da registrare. Entrambe queste tecniche producono un file video accessibile dalla tua app e, a seconda della posizione in cui scegli di salvare i file, dall'utente. Le sezioni centrali di questo articolo illustrano l'implementazione di questi scenari.

Lo spazio dei nomi Windows.Media.Capture fornisce API per la creazione di metadati che descrivono il gameplay acquisito o trasmesso. Può includere valori numerici o di testo, con un'etichetta di testo che identifica ogni elemento di dati. I metadati possono rappresentare un "evento" che si verifica in un singolo momento, ad esempio quando l'utente termina un giro in un gioco di corse o può rappresentare uno "stato" che persiste in un intervallo di tempo, ad esempio la mappa del gioco corrente. I metadati vengono scritti in una cache allocata e gestita per l'app dal sistema. I metadati sono incorporati in flussi di trasmissione e file video acquisiti, incluse le tecniche di acquisizione di sistema predefinite o di acquisizione di app personalizzate. Le sezioni finali di questo articolo illustrano come scrivere metadati di gioco.

Nota

Poiché i metadati di gioco possono essere incorporati in file multimediali che possono essere condivisi in rete al di fuori dal controllo dell'utente, non è consigliabile includere informazioni personali o altre informazioni sensibili nei metadati.

Attivare e disattivare l'acquisizione di app di sistema

L'acquisizione di app di sistema viene avviata dall'utente con l'interfaccia utente di sistema predefinita. I file vengono inseriti dall'ecosistema di giochi di Windows e non sono disponibili all'app o all'utente, a eccezione di esperienze di prima parte come l'app Xbox. L'app può disattivare e attivare l'acquisizione avviata dal sistema, consentendo di impedire all'utente di acquisire determinati contenuti o modalità di gioco.

Per attivare o disattivare l'acquisizione di app di sistema, è sufficiente chiamare il metodo statico AppCapture.SetAllowedAsync e passare false per disattivare l'acquisizione o true per attivarla.

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

Ricevere notifiche all'avvio e all'arresto dell'acquisizione di app di sistema

Per ricevere una notifica all'inizio o alla fine dell'acquisizione di app di sistema, ottenere prima un'istanza della classe AppCapture chiamando il metodo factory GetForCurrentView. Registrare quindi un gestore per l'evento CapturingChanged.

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 l'audio o il video vengono acquisiti, rispettivamente. Potrebbe essere necessario aggiornare l'interfaccia utente dell'app per indicare lo stato di acquisizione corrente.

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 la piattaforma UWP all'app

Le API per la registrazione di audio e video e per l'acquisizione di screenshot direttamente dall'app, disponibili nello spazio dei nomi Windows.Media.AppRecording, non sono incluse nel contratto API universale. Per accedere alle API, devi aggiungere un riferimento alle estensioni desktop di Windows per la piattaforma UWP alla tua app seguendo questa procedura.

  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.
  2. Espandere il nodo Windows Universal e selezionare Estensioni.
  3. Nell'elenco delle estensioni selezionare la casella di controllo accanto alle estensioni desktop di Windows per la voce UWP corrispondente alla build di destinazione per il progetto. Per le funzionalità di trasmissione dell'app, la versione deve essere 1709 o successiva.
  4. Fare clic su OK.

Ottenere un'istanza di AppRecordingManager

La classe AppRecordingManager è l'API centrale che si userà per gestire la registrazione delle app. Ottenere un'istanza di questa classe chiamando il metodo factory GetDefault. Prima di usare una delle API nello spazio dei nomi Windows.Media.AppRecording, devi verificare la loro presenza nel dispositivo corrente. Le API non sono disponibili nei dispositivi che eseguono una versione del sistema operativo precedente a Windows 10, versione 1709. Anziché cercare una versione specifica del sistema operativo, usare il metodo ApiInformation.IsApiContractPresent per eseguire una query per Windows.Media.AppBroadcasting.AppRecordingContract versione 1.0. Se questo contratto è presente, le API di registrazione sono disponibili nel dispositivo. Il codice di esempio in questo articolo controlla la presenza delle API una sola volta e quindi controlla se AppRecordingManager è Null prima delle operazioni successive.

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

Determinare se l'app può registrare

Esistono diversi motivi per cui l'app potrebbe non essere in grado di acquisire audio o video, ad esempio se il dispositivo corrente non soddisfa i requisiti hardware per la registrazione o se un'altra app sta trasmettendo. Prima di avviare una registrazione, verificare se l'app è attualmente in grado di registrare. Chiamare il metodo GetStatus dell'oggetto AppRecordingManager e quindi controllare la proprietà CanRecord dell'oggetto AppRecordingStatus restituito. Se CanRecord restituisce false, significa che l'app non è attualmente in grado di registrare ed è possibile controllare la proprietà Details per determinarne il motivo. A seconda del motivo, può essere necessario mostrare lo stato all'utente o mostrare istruzioni per attivare la registrazione dell'app.

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'app in un file

Dopo avere verificato che l'app sia in grado di registrare, è possibile avviare una nuova registrazione chiamando il metodo StartRecordingToFileAsync dell'oggetto AppRecordingManager.

Nell'esempio seguente il primo blocco then viene eseguito quando l'attività asincrona ha esito negativo. Il secondo blocco then tenta di accedere al risultato dell'attività e, se il risultato è Null, l'attività è stata completata. In entrambi i casi, il metodo helper OnRecordingComplete, illustrato di seguito, viene chiamato per gestire il risultato.

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 del record è riuscita. In tal caso, è possibile controllare la proprietà IsFileTruncated per determinare se, per motivi di archiviazione, il sistema è stato forzato a troncare il file acquisito. È possibile controllare la proprietà Duration per individuare la durata effettiva del file registrato; se il file è troncato, tale durata può essere più breve della durata dell'operazione di registrazione.

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

Negli esempi seguenti viene illustrato un codice di base per l'avvio e l'arresto dell'operazione di registrazione illustrata nell'esempio precedente.

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 file

Se l'utente ha attivato la registrazione cronologica per l'app nelle impostazioni di sistema, è possibile registrare un intervallo di tempo di gioco già trascorso. Un esempio precedente di questo articolo ha illustrato come confermare che l'app possa registrare il gameplay. È disponibile un controllo aggiuntivo per determinare se l'acquisizione cronologica è attivata. Ancora una volta, chiama GetStatus e controlla la proprietà CanRecordTimeSpan dell'oggetto AppRecordingStatus restituito. In questo esempio viene restituita anche la proprietà HistoricalBufferDuration di AppRecordingStatus che verrà utilizzata per determinare un'ora di inizio valida per l'operazione di registrazione.

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. L'ora di inizio viene fornita come struct DateTime. L'ora di inizio deve precedere l'ora corrente, entro la durata del buffer di registrazione cronologico. Per questo esempio, la lunghezza del buffer viene recuperata come parte del controllo per verificare se la registrazione cronologica è attivata, come illustrato nell'esempio di codice precedente. La durata della registrazione cronologica viene fornita come struct TimeSpan, che deve essere uguale o inferiore alla durata del buffer cronologico. Dopo avere determinato l'ora di inizio e la durata desiderate, chiamare RecordTimeSpanToFileAsync per avviare l'operazione di registrazione.

Come avviene per la registrazione con avvio e arresto manuali, al termine di una registrazione cronologica è 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, nel caso il file venisse troncato, può risultare più breve della finestra di tempo richiesta.

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 un codice di base per avviare l'operazione di registrazione cronologica illustrata nell'esempio precedente.

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

Salvare immagini screenshot su file

L'app può avviare un'acquisizione di screenshot che salverà il contenuto corrente della finestra dell'app in un file di immagine o in più file di immagine con diverse codifiche di immagini. Per specificare le codifiche delle immagini da usare, creare un elenco di stringhe in cui voce rappresenta un tipo di immagine. Le proprietà di ImageEncodingSubtypes forniscono la stringa corretta per ogni tipo di immagine supportato, ad esempio MediaEncodingSubtypes.Png o MediaEncodingSubtypes.JpegXr.

Avviare l'acquisizione dello schermo chiamando il metodo SaveScreenshotToFilesAsync dell'oggetto AppRecordingManager. Il primo parametro di questo metodo è StorageFolder, nel quale verranno salvati i file di immagine. Il secondo parametro è un prefisso del nome file a cui il sistema aggiungerà l'estensione per ogni tipo di immagine salvata, ad esempio ".png".

Il terzo parametro di SaveScreenshotToFilesAsync è necessario affinché il sistema possa eseguire la conversione corretta dello spazio di colore se la finestra corrente da acquisire visualizza contenuti HDR. Se sono presenti contenuti HDR, questo parametro deve essere impostato su AppRecordingSaveScreenshotOption.HdrContentVisible. In caso contrario, usare AppRecordingSaveScreenshotOption.None. Il parametro finale del metodo è l'elenco dei formati di immagine in cui deve essere acquisita la schermata.

Al termine della chiamata asincrona a SaveScreenshotToFilesAsync, restituisce un oggetto AppRecordingSavedScreenshotInfo che fornisce il valore StorageFile e il valore MediaEncodingSubtypes associato che indica il tipo di immagine per ogni immagine salvata.

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 un codice di base per avviare l'operazione di acquisizione illustrata nell'esempio precedente.

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

Aggiungere metadati del gioco per l'acquisizione avviata dal sistema e dall'app

Le sezioni seguenti descrivono come fornire metadati che il sistema potrà incorporare nel flusso MP4 del gioco acquisito o trasmesso. I metadati possono essere incorporati nei supporti acquisiti usando l'interfaccia utente di sistema predefinita e i supporti acquisiti dall'app, tramite AppRecordingManager. Questi metadati possono essere estratti dall'app e da altre app durante la riproduzione multimediale per offrire esperienze contestualmente consapevoli e sincronizzate con il gameplay acquisito o trasmesso.

Ottenere un'istanza di AppCaptureMetadataWriter

La classe primaria per la gestione dei metadati di acquisizione delle app è AppCaptureMetadataWriter. Prima di inizializzare un'istanza di questa classe, usare 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 in uso.

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

Scrivere metadati nella cache di sistema per l'app

Ogni elemento di metadati ha un'etichetta stringa che lo identifica, un valore 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 di dati. Un elemento di metadati può essere considerato un "evento" che si verifica in un singolo punto nel tempo, oppure uno "stato" che mantiene un valore in un intervallo di tempo. I metadati vengono scritti in una cache allocata e gestita per l'app dal sistema. Il sistema applica un limite di dimensioni nella cache di memoria dei metadati e, quando viene raggiunto il limite, elimina i dati in base alla priorità con cui è stato scritto ogni elemento di metadati. La sezione successiva illustra come gestire l'allocazione di memoria dei metadati dell'app.

Una tipica app può scegliere di scrivere alcuni metadati all'inizio della sessione di acquisizione per fornire contesto a dati successivi. Per questo scenario è consigliabile usare dati istantanei di "evento". Questo esempio chiama AddStringEvent, AddDoubleEvent e AddInt32Event per impostare valori istantanei per ogni tipo di dati.

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 di dati di "stato" che persiste nel tempo consiste nel tenere traccia della mappa del gioco in cui si trova attualmente il giocatore. In questo esempio viene chiamato StartStringState per impostare il valore dello stato.

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

Chiamare StopState per registrare che uno stato specifico è terminato.

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

È possibile sovrascrivere uno stato impostando un nuovo valore con un'etichetta di stato esistente.

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

È possibile terminare tutti gli stati attualmente aperti chiamando StopAllStates.

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

Gestire il limite di archiviazione della cache dei metadati

I metadati scritti con AppCaptureMetadataWriter vengono memorizzati nella cache dal sistema fino a quando non vengono scritti nel flusso multimediale associato. Il sistema definisce un limite di dimensioni per la cache dei metadati di ogni app. Una volta raggiunto il limite di dimensioni della cache, il sistema inizierà a eliminare i metadati memorizzati nella cache. Il sistema eliminerà i metadati scritti con il valore di priorità AppCaptureMetadataPriority.Informational prima di eliminare i metadati con la priorità AppCaptureMetadataPriority.Important.

In qualsiasi momento è possibile controllare il numero di byte disponibili nella cache dei metadati dell'app chiamando RemainingStorageBytesAvailable. È possibile scegliere di impostare una soglia definita dall'app personalizzata dopo la quale è possibile scegliere di ridurre la quantità di metadati scritti nella cache. Nell'esempio seguente viene illustrata una semplice implementazione di questo metodo.

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 metadati

È possibile ricevere una notifica quando il sistema inizia a eliminare i metadati per l'app registrando un gestore per l'evento MetadataPurged.

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

}

Nel gestore per l'evento MetadataPurged è possibile cancellare alcune stanze nella cache dei metadati terminando gli stati con priorità inferiore, oppure implementare la logica definita dall'app per ridurre la quantità di metadati scritti nella cache oppure ancora è possibile non eseguire alcuna operazione e lasciare che il sistema continui a ripulire la cache in base alla priorità con cui è stato scritto.

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."));

}