Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird beschrieben, wie Sie Spielvideos, Audio- und Screenshots aufzeichnen und Metadaten übermitteln, die das System in aufgenommene und übertragene Medien einbettet, sodass Ihre App und andere Personen dynamische Erfahrungen erstellen können, die mit Spielereignissen synchronisiert werden.
Es gibt zwei verschiedene Möglichkeiten, wie das Spiel in einer UWP-App erfasst werden kann. Der Benutzer kann die Erfassung mithilfe der integrierten Systembenutzeroberfläche initiieren. Medien, die mit dieser Technik erfasst werden, werden in das Microsoft-Spielökosystem aufgenommen, können über Erstanbietererfahrungen wie die Xbox-App angezeigt und freigegeben werden und stehen Ihrer App oder Benutzern nicht direkt zur Verfügung. In den ersten Abschnitten dieses Artikels erfahren Sie, wie Sie die vom System implementierte App-Erfassung aktivieren und deaktivieren und wie Sie Benachrichtigungen empfangen, wenn die App-Aufnahme gestartet oder beendet wird.
Die andere Möglichkeit zum Erfassen von Medien besteht darin, die APIs des Windows.Media.AppRecording-Namespaces zu verwenden. Wenn die Aufnahme auf dem Gerät aktiviert ist, kann Ihre App mit der Erfassung des Gameplays beginnen und dann nach einiger Zeit die Aufnahme beenden, an dem die Medien in eine Datei geschrieben werden. Wenn der Benutzer die verlaufsgeschichtliche Erfassung aktiviert hat, können Sie auch Das Spiel aufzeichnen, das bereits aufgetreten ist, indem Sie eine Startzeit in der Vergangenheit und eine Dauer angeben, die aufgezeichnet werden soll. Beide Techniken erzeugen eine Videodatei, auf die von Ihrer App zugegriffen werden kann, und je nachdem, wo Sie die Dateien speichern möchten, vom Benutzer. In den mittleren Abschnitten dieses Artikels werden Sie durch die Implementierung dieser Szenarien geführt.
Der Windows.Media.Capture-Namespace stellt APIs zum Erstellen von Metadaten bereit, die das aufgezeichnete oder übertragene Spiel beschreiben. Dies kann Text- oder numerische Werte umfassen, wobei eine Textbezeichnung jedes Datenelements identifiziert. Metadaten können ein "Ereignis" darstellen, das zu einem einzelnen Zeitpunkt auftritt, z. B. wenn der Benutzer eine Runde in einem Rennspiel beendet hat, oder es kann einen "Zustand" darstellen, der über einen Zeitraum beibehalten wird, z. B. die aktuelle Spielkarte, in der der Benutzer spielt. Die Metadaten werden in einen Cache geschrieben, der für Ihre App vom System zugewiesen und verwaltet wird. Die Metadaten werden in Übertragungsstreams und aufgenommene Videodateien eingebettet, einschließlich der integrierten Systemerfassung oder der benutzerdefinierten App-Aufnahmetechniken. In den letzten Abschnitten dieses Artikels erfahren Sie, wie Sie Spielmetadaten schreiben.
Hinweis
Da die Spielmetadaten in Mediendateien eingebettet werden können, die potenziell über das Netzwerk freigegeben werden können, sollten Sie keine personenbezogenen Informationen oder andere potenziell vertrauliche Daten in die Metadaten einschließen.
Aktivieren und Deaktivieren der System-App-Erfassung
Die System-App-Erfassung wird vom Benutzer mit der integrierten Systembenutzeroberfläche initiiert. Die Dateien werden vom Windows-Spieleökosystem aufgenommen und sind nicht für Ihre App oder den Benutzer verfügbar, mit Ausnahme der Erfahrungen von Erstanbietern wie der Xbox-App. Ihre App kann die vom System initiierte App-Erfassung deaktivieren und aktivieren, sodass Sie verhindern können, dass der Benutzer bestimmte Inhalte oder Spielvorgänge erfasst.
Rufen Sie zum Aktivieren oder Deaktivieren der System-App-Erfassung einfach die statische Methode "AppCapture.SetAllowedAsync " auf, und übergeben Sie "false ", um die Erfassung zu deaktivieren oder "true " zu übergeben, um die Erfassung zu aktivieren.
Windows::Media::Capture::AppCapture::SetAllowedAsync(allowed);
Empfangen von Benachrichtigungen beim Starten und Beenden der System-App-Erfassung
Um eine Benachrichtigung zu erhalten, wenn die System-App-Erfassung beginnt oder endet, rufen Sie zuerst eine Instanz der AppCapture-Klasse ab, indem Sie die Factorymethode GetForCurrentView aufrufen. Registrieren Sie als Nächstes einen Handler für das CaptureChanged-Ereignis.
Windows::Media::Capture::AppCapture^ appCapture = Windows::Media::Capture::AppCapture::GetForCurrentView();
appCapture->CapturingChanged +=
ref new TypedEventHandler<Windows::Media::Capture::AppCapture^, Platform::Object^>(this, &App::OnCapturingChanged);
Im Handler für das CaptureChanged-Ereignis können Sie die IsCapturingAudio- und die IsCapturingVideo-Eigenschaften überprüfen, um festzustellen, ob Audio oder Video aufgenommen werden. Möglicherweise möchten Sie die Benutzeroberfläche Ihrer App aktualisieren, um den aktuellen Aufnahmestatus anzugeben.
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);
}
Hinzufügen der Windows-Desktoperweiterungen für die UWP zu Ihrer App
Die APIs zum Aufzeichnen von Audio und Video und zum Aufnehmen von Screenshots direkt aus Ihrer App, die im Windows.Media.AppRecording-Namespace enthalten sind, sind nicht im Vertrag für die universelle API enthalten. Um auf die APIs zuzugreifen, müssen Sie Ihrer App mit den folgenden Schritten einen Verweis auf die Windows-Desktoperweiterungen für die UWP hinzufügen.
- Erweitern Sie in Visual Studio in Projektmappen-Explorer Ihr UWP-Projekt, klicken Sie mit der rechten Maustaste auf "Verweise", und wählen Sie dann "Verweis hinzufügen" aus.
- Erweitern Sie den Universellen Windows-Knoten, und wählen Sie "Erweiterungen" aus.
- Aktivieren Sie in der Liste der Erweiterungen das Kontrollkästchen neben den Windows-Desktoperweiterungen für den UWP-Eintrag , der dem Zielbuild für Ihr Projekt entspricht. Für die App-Übertragungsfeatures muss die Version 1709 oder höher sein.
- Klicken Sie auf OK.
Abrufen einer Instanz von AppRecordingManager
Die AppRecordingManager-Klasse ist die zentrale API, die Sie zum Verwalten der App-Aufzeichnung verwenden. Rufen Sie eine Instanz dieser Klasse ab, indem Sie die Factorymethode GetDefault aufrufen. Bevor Sie eine der APIs im Windows.Media.AppRecording-Namespace verwenden, sollten Sie auf dem aktuellen Gerät überprüfen, ob sie vorhanden sind. Die APIs sind auf Geräten mit einer Betriebssystemversion vor Windows 10, Version 1709, nicht verfügbar. Anstatt nach einer bestimmten Betriebssystemversion zu suchen, verwenden Sie die ApiInformation.IsApiContractPresent-Methode, um die Windows.Media.AppBroadcasting.AppRecordingContract Version 1.0 abzufragen. Wenn dieser Vertrag vorhanden ist, sind die Aufzeichnungs-APIs auf dem Gerät verfügbar. Der Beispielcode in diesem Artikel sucht einmal nach den APIs und überprüft dann, ob der AppRecordingManager null ist, bevor nachfolgende Vorgänge ausgeführt werden.
if (Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(
"Windows.Media.AppRecording.AppRecordingContract", 1, 0))
{
m_appRecordingManager = AppRecordingManager::GetDefault();
}
Ermitteln, ob Ihre App derzeit aufzeichnen kann
Es gibt mehrere Gründe, warum Ihre App derzeit nicht in der Lage ist, Audio oder Video aufzunehmen, einschließlich, wenn das aktuelle Gerät die Hardwareanforderungen für die Aufzeichnung nicht erfüllt oder eine andere App derzeit übertragen wird. Bevor Sie eine Aufzeichnung initiieren, können Sie überprüfen, ob Ihre App derzeit aufzeichnen kann. Rufen Sie die GetStatus-Methode des AppRecordingManager-Objekts auf, und überprüfen Sie dann die CanRecord-Eigenschaft des zurückgegebenen AppRecordingStatus-Objekts. Wenn CanRecord "false" zurückgibt, was bedeutet, dass Ihre App zurzeit keine Aufzeichnung durchführen kann, können Sie die Details-Eigenschaft überprüfen, um den Grund zu ermitteln. Je nach Grund sollten Sie dem Benutzer den Status anzeigen oder Anweisungen zum Aktivieren der App-Aufzeichnung anzeigen.
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;
}
Manuelles Starten und Beenden der Aufzeichnung Ihrer App in einer Datei
Nachdem Sie überprüft haben, ob Ihre App aufzeichnen kann, können Sie eine neue Aufzeichnung starten, indem Sie die StartRecordingToFileAsync-Methode des AppRecordingManager-Objekts aufrufen.
Im folgenden Beispiel wird der erste Dann-Block ausgeführt, wenn die asynchrone Aufgabe fehlschlägt. Der zweite Block dann versucht, auf das Ergebnis der Aufgabe zuzugreifen. Wenn das Ergebnis null ist, dann ist die Aufgabe abgeschlossen. In beiden Fällen wird die unten gezeigte OnRecordingComplete-Hilfsmethode aufgerufen, um das Ergebnis zu behandeln.
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();
}
});
}
Überprüfen Sie nach Abschluss des Aufzeichnungsvorgangs die Succeeded-Eigenschaft des zurückgegebenen AppRecordingResult-Objekts, um zu ermitteln, ob der Datensatzvorgang erfolgreich war. Wenn ja, können Sie die IsFileTruncated-Eigenschaft überprüfen, um festzustellen, ob das System aus Speichergründen gezwungen wurde, die erfasste Datei abgeschnitten zu haben. Sie können die Duration-Eigenschaft überprüfen, um die tatsächliche Dauer der aufgezeichneten Datei zu ermitteln, die, wenn die Datei abgeschnitten wird, kürzer sein kann als die Dauer des Aufzeichnungsvorgangs.
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;
}
}
Die folgenden Beispiele zeigen einige grundlegende Code zum Starten und Beenden des Aufzeichnungsvorgangs im vorherigen Beispiel.
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();
}
Aufzeichnen einer historischen Zeitspanne in einer Datei
Wenn der Benutzer die verlaufsgeschichtliche Aufzeichnung für Ihre App in den Systemeinstellungen aktiviert hat, können Sie eine Zeitspanne aufzeichnen, die zuvor transpiriert wurde. Ein vorheriges Beispiel in diesem Artikel zeigt, wie Sie bestätigen können, dass Ihre App das Spiel derzeit aufzeichnen kann. Es gibt eine zusätzliche Überprüfung, um festzustellen, ob die historische Erfassung aktiviert ist. Rufen Sie erneut GetStatus auf, und überprüfen Sie die CanRecordTimeSpan-Eigenschaft des zurückgegebenen AppRecordingStatus-Objekts. In diesem Beispiel wird auch die HistoricalBufferDuration-Eigenschaft der AppRecordingStatus zurückgegeben, die verwendet wird, um eine gültige Startzeit für den Aufzeichnungsvorgang zu bestimmen.
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;
}
Um einen historischen Zeitbereich zu erfassen, müssen Sie eine Startzeit für die Aufzeichnung und eine Dauer angeben. Die Startzeit wird als DateTime-Struktur bereitgestellt. Die Startzeit muss eine Zeit vor der aktuellen Uhrzeit innerhalb der Länge des Historischen Aufzeichnungspuffers sein. In diesem Beispiel wird die Pufferlänge als Teil der Überprüfung abgerufen, um festzustellen, ob die verlaufsgeschichtliche Aufzeichnung aktiviert ist, die im vorherigen Codebeispiel gezeigt wird. Die Dauer der historischen Aufzeichnung wird als TimeSpan-Struktur bereitgestellt, die auch gleich oder kleiner als die Dauer des historischen Puffers sein sollte. Nachdem Sie die gewünschte Startzeit und Dauer ermittelt haben, rufen Sie RecordTimeSpanToFileAsync auf, um den Aufzeichnungsvorgang zu starten.
Wie die Aufzeichnung mit manuellem Start und Beenden, wenn eine historische Aufzeichnung abgeschlossen ist, können Sie die Succeeded-Eigenschaft des zurückgegebenen AppRecordingResult-Objekts überprüfen, um festzustellen, ob der Datensatzvorgang erfolgreich war, und Sie können die IsFileTruncated- und Duration-Eigenschaft überprüfen, um die tatsächliche Dauer der aufgezeichneten Datei zu ermitteln, die, wenn die Datei abgeschnitten wird, möglicherweise kürzer als die Dauer der angeforderten Zeit ist. Fenster.
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);
}
});
}
Das folgende Beispiel zeigt einen grundlegenden Code zum Initiieren des historischen Datensatzvorgangs im vorherigen Beispiel.
StorageFolder^ storageFolder = ApplicationData::Current->LocalFolder;
concurrency::create_task(storageFolder->CreateFileAsync("recordtimespantofile_example.mp4", CreationCollisionOption::ReplaceExisting)).then(
[this](StorageFile^ file)
{
RecordTimeSpanToFile(file);
});
Speichern von Screenshotbildern in Dateien
Ihre App kann eine Screenshotaufnahme initiieren, die den aktuellen Inhalt des App-Fensters in einer Bilddatei oder in mehreren Bilddateien mit unterschiedlichen Bildcodierungen speichert. Um die bildcodierungen anzugeben, die Sie verwenden möchten, erstellen Sie eine Liste mit Zeichenfolgen, in denen jedes einen Bildtyp darstellt. Die Eigenschaften der ImageEncodingSubtypes stellen die richtige Zeichenfolge für jeden unterstützten Bildtyp bereit, z. B. MediaEncodingSubtypes.Png oder MediaEncodingSubtypes.JpegXr.
Initiieren Sie die Bildschirmaufnahme, indem Sie die SaveScreenshotToFilesAsync-Methode des AppRecordingManager-Objekts aufrufen. Der erste Parameter für diese Methode ist ein StorageFolder , in dem die Bilddateien gespeichert werden. Der zweite Parameter ist ein Dateinamenpräfix, an das das System die Erweiterung für jeden gespeicherten Bildtyp anfügen wird, z. B. ".png".
Der dritte Parameter für SaveScreenshotToFilesAsync ist erforderlich, damit das System die richtige Farbraumkonvertierung ausführen kann, wenn das zu erfassende aktuelle Fenster HDR-Inhalte anzeigt. Wenn HDR-Inhalte vorhanden sind, sollte dieser Parameter auf "AppRecordingSaveScreenshotOption.HdrContentVisible" festgelegt werden. Verwenden Sie andernfalls "AppRecordingSaveScreenshotOption.None". Der letzte Parameter für die Methode ist die Liste der Bildformate, mit denen der Bildschirm erfasst werden soll.
Wenn der asynchrone Aufruf von SaveScreenshotToFilesAsync abgeschlossen ist, wird ein AppRecordingSavedScreenshotInfo-Objekt zurückgegeben, das den StorageFile- und zugeordneten MediaEncodingSubtypes-Wert bereitstellt, der den Bildtyp für jedes gespeicherte Bild angibt.
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);
}
});
}
Das folgende Beispiel zeigt einen grundlegenden Code zum Initiieren des Screenshotvorgangs, der im vorherigen Beispiel gezeigt wird.
StorageFolder^ storageFolder = ApplicationData::Current->LocalFolder;
SaveScreenShotToFiles(storageFolder, "screen_capture");
Hinzufügen von Spielmetadaten für system- und app-initiierte Erfassung
In den folgenden Abschnitten dieses Artikels wird beschrieben, wie Metadaten bereitgestellt werden, die das System in den MP4-Stream des aufgezeichneten oder übertragenen Spiels einbettet. Metadaten können in Medien eingebettet werden, die mithilfe der integrierten Systembenutzeroberfläche und medien erfasst werden, die von der App mit AppRecordingManager erfasst werden. Diese Metadaten können von Ihrer App und anderen Apps während der Medienwiedergabe extrahiert werden, um kontextbezogene Erfahrungen bereitzustellen, die mit dem aufgezeichneten oder übertragenen Spiel synchronisiert werden.
Abrufen einer Instanz von AppCaptureMetadataWriter
Die primäre Klasse zum Verwalten von App-Erfassungsmetadaten ist "AppCaptureMetadataWriter". Bevor Sie eine Instanz dieser Klasse initialisieren, verwenden Sie die ApiInformation.IsApiContractPresent-Methode, um die Windows.Media.Capture.AppCaptureMetadataContract Version 1.0 abzufragen, um zu überprüfen, ob die API auf dem aktuellen Gerät verfügbar ist.
if (Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent("Windows.Media.Capture.AppCaptureMetadataContract", 1, 0))
{
m_appCaptureMetadataWriter = ref new AppCaptureMetadataWriter();
}
Schreiben von Metadaten in den Systemcache für Ihre App
Jedes Metadatenelement weist eine Zeichenfolgenbeschriftung auf, identifiziert das Metadatenelement, einen zugeordneten Datenwert, der eine Zeichenfolge, eine ganze Zahl oder einen Doppelwert sein kann, und einen Wert aus der AppCaptureMetadataPriority-Aufzählung , die die relative Priorität des Datenelements angibt. Ein Metadatenelement kann entweder als "Ereignis" betrachtet werden, das zu einem einzelnen Zeitpunkt auftritt, oder als "Zustand", der einen Wert über ein Zeitfenster verwaltet. Metadaten werden in einen Speichercache geschrieben, der für Ihre App vom System zugewiesen und verwaltet wird. Das System erzwingt eine Größenbeschränkung für den Metadatenspeichercache und löscht beim Erreichen des Grenzwerts Daten basierend auf der Priorität, mit der jedes Metadatenelement geschrieben wurde. Im nächsten Abschnitt dieses Artikels wird gezeigt, wie Sie die Metadatenspeicherzuweisung Ihrer App verwalten.
Eine typische App kann sich entscheiden, einige Metadaten am Anfang der Aufnahmesitzung zu schreiben, um einen Kontext für die nachfolgenden Daten bereitzustellen. Für dieses Szenario wird empfohlen, sofortige "Ereignis"-Daten zu verwenden. In diesem Beispiel wird AddStringEvent, AddDoubleEvent und AddInt32Event aufgerufen, um sofortige Werte für jeden Datentyp festzulegen.
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);
}
}
Ein häufiges Szenario für die Verwendung von Zustandsdaten, die im Laufe der Zeit beibehalten werden, besteht darin, die Spielkarte nachzuverfolgen, in der sich der Spieler derzeit befindet. In diesem Beispiel wird StartStringState aufgerufen, um den Statuswert festzulegen.
void App::StartMap(Platform::String^ mapName)
{
m_appCaptureMetadataWriter->StartStringState("map", mapName, AppCaptureMetadataPriority::Important);
}
Rufen Sie StopState auf, um aufzuzeichnen, dass ein bestimmter Zustand beendet wurde.
void App::EndMap(Platform::String^ mapName)
{
m_appCaptureMetadataWriter->StopState("map");
}
Sie können einen Zustand überschreiben, indem Sie einen neuen Wert mit einer vorhandenen Statusbezeichnung festlegen.
void App::LevelUp(int newLevel)
{
m_appCaptureMetadataWriter->StartInt32State("currentLevel", newLevel, AppCaptureMetadataPriority::Important);
}
Sie können alle aktuell geöffneten Zustände beenden, indem Sie StopAllStates aufrufen.
void App::RaceComplete()
{
m_appCaptureMetadataWriter->StopAllStates();
}
Verwalten des Speicherlimits für den Metadatencache
Die Metadaten, die Sie mit AppCaptureMetadataWriter schreiben, werden vom System zwischengespeichert, bis sie in den zugeordneten Mediendatenstrom geschrieben wird. Das System definiert eine Größenbeschränkung für den Metadatencache jeder App. Sobald der Grenzwert für die Cachegröße erreicht wurde, beginnt das System, zwischengespeicherte Metadaten zu löschen. Das System löscht Metadaten, die mit dem Wert "AppCaptureMetadataPriority.Informational" geschrieben wurden, bevor Metadaten mit der Priorität "AppCaptureMetadataPriority.Important" gelöscht werden.
Sie können jederzeit überprüfen, wie viele Bytes im Metadatencache Ihrer App verfügbar sind, indem Sie RemainingStorageBytesAvailable aufrufen. Sie können ihren eigenen app-definierten Schwellenwert festlegen, nach dem Sie die Menge der Metadaten verringern können, die Sie in den Cache schreiben. Das folgende Beispiel zeigt eine einfache Implementierung dieses Musters.
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);
}
}
Empfangen von Benachrichtigungen, wenn das System Metadaten löscht
Sie können sich registrieren, um eine Benachrichtigung zu erhalten, wenn das System mit dem Löschen von Metadaten für Ihre App beginnt, indem Sie einen Handler für das MetadataPurged-Ereignis registrieren.
if (m_appCaptureMetadataWriter != nullptr)
{
m_appCaptureMetadataWriter->MetadataPurged +=
ref new TypedEventHandler<AppCaptureMetadataWriter^, Platform::Object^>(this, &App::OnMetadataPurged);
}
Im Handler für das MetadataPurged-Ereignis können Sie einen Raum im Metadatencache löschen, indem Sie die Status mit niedrigerer Priorität beenden. Sie können appdefinierte Logik implementieren, um die Menge der Metadaten zu verringern, die Sie in den Cache schreiben, oder Sie können nichts tun und das System den Cache weiterhin löschen lassen, basierend auf der Priorität, mit der sie geschrieben wurde.
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."));
}
Zugehörige Themen