以 Android 为目标平台在 AR Foundation 上录制和播放 AR 现场录像

借助 Recording & Playback API,您可以在给定环境中录制一次视频和 AR 数据,并使用该内容替换实时相机会话。

前提条件

在继续操作之前,请确保您了解基本 AR 概念以及如何配置 ARCore 会话

与其他 ARCore API 的兼容性

由于会话数据的处理方式不同,ARCore API 在播放期间产生的结果可能与记录期间观察到的结果不同。它们在后续播放会话期间也可能会产生不同的结果。例如,在播放期间,检测到的可跟踪对象的数量、检测的确切时间以及它们随时间推移的姿势可能会有所不同。

与 Cloud Anchors 的兼容性

您可以在录制或播放会话时托管和解析 Cloud Anchor

正在录制

开始、停止和检查 ARCore 会话录制的状态。

录制 ARCore 会话

如需录制 ARCore 会话,请配置会话并为录制提供 MP4 URI。请先调用 ARRecordingManager.StartRecording(),然后再恢复会话。会话恢复后,系统会自动开始录制。如需在会话暂停时自动停止录制,请调用 ARRecordingConfig.AutoStopOnPause。如需录制部分会话,请在会话运行时调用 ARRecordingManager.StartRecording()

ARCoreRecordingConfig recordingConfig = ScriptableObject.CreateInstance<ARCoreRecordingConfig>();
Uri datasetUri = new System.Uri("file:///uri/for/dataset.mp4");
recordingConfig.Mp4DatasetUri = datasetUri.AbsoluteUri;

recordingManager.StartRecording(recordingConfig);

停止会话录制

如需停止录制但不暂停当前正在运行的 AR 会话,请调用 ARRecordingManager.StopRecording()

recordingManager.StopRecording();

查看录制状态

您可以随时使用 ARRecordingManager.RecordingStatus 确定当前的录制状态。

Debug.Log("Current Recording Status: " + recordingManager.RecordingStatus);

播放

播放之前录制的 AR 会话。会话会实时播放,且无法调整会话播放或速度。

播放之前录制的会话

如需回放之前录制的会话,请调用 ARPlaybackManager.SetPlaybackDatasetUri() 并提供要回放的数据集的 URI。您必须暂停会话才能使用此方法。继续会话以使更改生效。

由于恢复会话而开始播放后,通过停用 ARSession 暂停会话将会暂停处理数据集中的所有相机图像帧和任何其他记录的传感器数据。通过这种方式丢弃的相机图像帧和传感器帧数据在会话通过恢复会话再次恢复时不会重新处理。由于处理数据存在间隔,会话的 AR 跟踪通常会受到影响。

// Disable the ARSession to pause the current AR session.
session.enabled = false;

// In the next frame, provide a URI for the dataset you wish to play back.
Uri datasetUri = new System.Uri("file:///uri/for/dataset.mp4");
playbackManager.SetPlaybackDatasetUri(datasetUri);

// In the frame after that, re-enable the ARSession to resume the session from
// the beginning of the dataset.
session.enabled = true;

已知问题和解决方法

有一个已知问题,即对 ARPlaybackManager.SetPlaybackDatasetUri() 的调用会返回 ErrorPlaybackFailed。之所以会出现这种情况,是因为会话可能需要几帧才能暂停。如果在会话暂停之前调用 ARPlaybackManager.SetPlaybackDatasetUri(),则无法访问会话,因此会返回错误。

以下代码可作为权宜解决方法。

// Workaround for known issue where `playbackManager.SetPlaybackDatasetUri()`
// returns `ErrorPlaybackFailed` because it can take several frames for a
// session to be paused.

// Reference to the ARSession component in the scene.
ARSession session;

void PlaybackDataset()
{
    setPlaybackDataset = true;

    // Pause the current AR session.
    session.enabled = false;

    // Set a timeout for retrying playback retrieval.
    timeout = 10f;
}

// Next frame
void Update()
{
    ...

    if (setPlaybackDataset)
    {
        PlaybackResult result = playbackManager.SetPlaybackDatasetUri(datasetUri);
        if (result == PlaybackResult.ErrorPlaybackFailed || result == PlaybackResult.SessionNotReady)
        {
            // Try to set the dataset again in the next frame.
            timeout -= Time.deltaTime;
        }
        else
        {
            // Do not set the timeout if the result is something other than ErrorPlaybackFailed.
            timeout = -1f;
        }

        if (timeout < 0.0f)
        {
            setPlaybackDataset = false;
            // If playback is successful, proceed as usual.
            // If playback is not successful, handle the error appropriately.
        }
    }

    ...
}

停止播放

如需停止播放,请调用 ARPlaybackManager.SetPlaybackDatasetUri() 并将数据集 URI 设置为 null

// Disable the ARSession to pause the current AR session.
session.enabled = false;

// In the next frame, unset the playback dataset URI.
playbackManager.SetPlaybackDatasetUri(null);

// In the frame after that, re-enable the ARSession to resume the session using
// the device camera and other sensors.
session.enabled = true;

从头开始重新播放

如需从数据集开头重新开始播放,请调用 ARPlaybackManager.SetPlaybackDatasetUri() 并指定相同的 MP4 录制内容,然后再恢复会话。

// Disable the ARSession to pause the current AR session.
session.enabled = false;

// In the next frame, specify the same dataset URI.
playbackManager.SetPlaybackDatasetUri(datasetUri); // Same URI that was previously set.

// In the frame after that, re-enable the ARSession to resume the session from
// the beginning of the dataset.
session.enabled = true;

播放其他会话

如需回放其他数据集,请暂停会话并指定新数据集,然后再继续会话。

// Disable the ARSession to pause the current AR session.
session.enabled = false;

// In the next frame, specify a new dataset URI.
Uri newDatasetUri = new System.Uri("file:///uri/for/different/dataset.mp4");
playbackManager.SetPlaybackDatasetUri(newDatasetUri); // Different URI than was previously set.

// In the frame after that, re-enable the ARSession to resume the session from
// the beginning of the new dataset.
session.enabled = true;

查看播放状态

ARPlaybackManager.PlaybackStatus 可随时用于确定当前的播放状态。

Debug.Log("Current Playback Status: " + playbackManager.PlaybackStatus);

后续步骤