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

借助 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.
}

后续步骤