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

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

前提条件

确保您了解基本 AR 概念以及如何配置 ARCore 会话,然后再继续。

与其他 ARCore API 的兼容性

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

与云锚点的兼容性

您可以在录制或播放会话时托管和解析云锚点

录制

开始、停止和检查 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);

后续步骤