在 Android 设备上录制和播放 AR 现场录像

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

前提条件

确保您了解 AR 基础概念 以及如何在继续之前配置 ARCore 现场录像

与其他 ARCore API 的兼容性

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

与共享相机的兼容性

系统可能会录制使用共享摄像头的会话。不过,目前无法使用“共享相机”模式播放这些会话。

与云锚点的兼容性

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

正在录制

开始、停止和检查 ARCore 现场录像的状态。

录制 ARCore 现场录像

要录制 ARCore 现场录像,请配置现场录像并提供录制的 MP4 URI。在首次调用 session.resume() 之前调用 session.startRecording()。会话恢复后,系统会自动开始录制。如需在会话暂停时自动停止录制,请调用 RecordingConfig.setAutoStopOnPause()。如需录制部分会话,请在会话运行时调用 session.startRecording()

Java

// Configure the ARCore session.
Session session = new Session(context);
Uri destination = Uri.fromFile(new File(context.getFilesDir(), "recording.mp4"));
RecordingConfig recordingConfig =
        new RecordingConfig(session)
        .setMp4DatasetUri(destination)
        .setAutoStopOnPause(true);
try {
  // Prepare the session for recording, but do not start recording yet.
  session.startRecording(recordingConfig);
} catch (RecordingFailedException e) {
  Log.e(TAG, "Failed to start recording", e);
}

// Resume the ARCore session to start recording.
session.resume();

Kotlin

// Configure the ARCore session.
val session = Session(context)
val destination = Uri.fromFile(File(context.getFilesDir(), "recording.mp4"))
val recordingConfig = RecordingConfig(session)
  .setMp4DatasetUri(destination)
  .setAutoStopOnPause(true)
session.startRecording(recordingConfig)

// Resume the ARCore session to start recording.
session.resume()

停止录制通话内容

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

Java

try {
  session.stopRecording();  // Stop recording.
} catch (RecordingFailedException e) {
  Log.e(TAG, "Failed to stop recording", e);
}

Kotlin

session.stopRecording()

查看录制状态

session.getRecordingStatus() 可随时用于确定当前的 RecordingStatus

Java

// Use any time to determine current RecordingStatus.
if (session.getRecordingStatus() == RecordingStatus.OK) {
  // Update the UI to show that the session is currently being recorded.
}

Kotlin

// Use any time to determine current RecordingStatus.
if (session.recordingStatus == RecordingStatus.OK) {
  // Update the UI to show that the session is currently being recorded.
}

播放

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

播放之前录制的会话

要播放之前录制的会话,请在首次调用 session.resume() 之前调用 session.setPlaybackDatasetUri()

由于首次调用 session.resume() 而开始播放后,通过调用 session.pause() 暂停会话将会暂停处理数据集中的所有相机图像帧和任何其他记录的传感器数据。当通过调用 session.resume() 再次恢复会话时,系统不会重新处理以这种方式舍弃的相机图像帧和传感器帧数据。由于所处理的数据存在缺口,相应会话的 AR 跟踪通常会受到影响。

Java

// Configure the ARCore session.
Session session = new Session(context);

// Specify the previously recorded MP4 file.
Uri recordingUri = Uri.fromFile(new File(context.getFilesDir(), "recording.mp4"));
session.setPlaybackDatasetUri(recordingUri);
…

// Start playback from the beginning of the dataset.
session.resume();
…

// Pause the AR session, but silently continue MP4 playback. Camera frames
// and other recorded sensor data is discarded while the session is paused.
session.pause();
…

// Resume the AR session. Camera frames and other sensor data from the MP4
// that was silently played back while the session was paused is not
// processed by ARCore.
session.resume();

Kotlin

// Configure the ARCore session.
val session = Session(context)

// Specify the previously recorded MP4 file.
val recordingUri = Uri.fromFile(File(context.filesDir, "recording.mp4"))
session.playbackDatasetUri = recordingUri
…

// Start playback from the beginning of the dataset.
session.resume()
…

// Pause the AR session, but silently continue MP4 playback. Camera frames
// and other recorded sensor data is discarded while the session is paused.
session.pause()
…

// Resume the AR session. Camera frames and other sensor data from the MP4
// that was silently played back while the session was paused is not
// processed by ARCore.
session.resume()

从头开始重新播放

如需从数据集开头重新开始播放,请暂停会话并调用 session.setPlaybackDatasetUri(),在恢复会话之前指定相同的 MP4 录制内容。

Java

session.pause();
// Pause and specify the SAME dataset:
session.setPlaybackDatasetUri(previousRecordingUri);
session.resume();  // Playback starts from the BEGINNING of the dataset.

Kotlin

session.pause()
// Pause and specify the SAME dataset:
session.playbackDatasetUri = previousRecordingUri
session.resume()  // Playback starts from the BEGINNING of the dataset.

播放其他会话

如需播放其他数据集,请暂停会话并指定新的数据集,然后再恢复会话。

Java

// Switch to a different dataset.
session.pause();   // Pause the playback of the first dataset.
// Specify a different dataset to use.
session.setPlaybackDatasetUri(newRecordingUri);
session.resume();  // Start playback from the beginning of the new dataset.

Kotlin

// Switch to a different dataset.
session.pause()   // Pause the playback of the first dataset.
// Specify a different dataset to use.
session.playbackDatasetUri = newRecordingUri
session.resume()  // Start playback from the beginning of the new dataset.

查看播放状态

您可以随时使用 session.getPlaybackStatus() 来确定当前的 PlaybackStatus

Java

// Use any time to determine current PlaybackStatus.
if (session.getPlaybackStatus() != PlaybackStatus.OK) {
  // Update the UI to show that the session playback has finished.
}

Kotlin

// Use any time to determine current PlaybackStatus.
if (session.playbackStatus != PlaybackStatus.OK) {
  // Update the UI to show that the session playback has finished.
}

后续步骤