Google I/O 2021にて、ARCoreの新機能 Recording and Playback API が発表・リリースされました。
AR Foundationの最新バージョンが即座に対応しており、簡単に使えてARのテストに便利な機能なので、サクサクサクっと試します。
サンプルを動かす
Recording and Playback APIは、周囲の環境を映した動画を録画しておき、再生することでARのテストができる機能です。
ARCore 1.24で追加されており、対応するAR Foundationのバージョンは4.2 preview7 以降となります。
AR Foundation Samplesにすぐに動かせるサンプルシーンがあるので、mainブランチから最新バージョンを取得します。
README.mdを読むと、AR Foundation 4.2を使うにはUnity 2021.2が必要となっていますので、Unity Hubで2021.2.0a17をインストールしました。
AR Foundation SamplesをUnityで開いてみると、"Assets" > "Scenes" > "ARCore" に "ARCoreSessionRecoding"というシーンがあります。
こちらのシーンを開きます。
シーンの構成を見てみると、AR Foundationの基本構成となる"AR Session"、"AR Session Origin"が配置されています。
ポイントになるのは、"AR Session"にアタッチされている"ARCoreSessionRecorder"で、こちらにRecordingとPlaybackの処理が書かれています。中身の処理は後で確認することにして、まずは動かしてみましょう。
ビルドの際に、プラットフォームをAndroidに切り替えるのと、ビルド対象のシーンが "ARCoreSessionRecoding"になっているか注意してください。
Androidの実機で動かします。私はPixel 3aを使っています。
画面上部にボタンのUIが表示されており、[Start recording]で録画が開始されます。そのまま周囲の環境を映して、[Stop recording]を行うと動画が保存されます。
保存した動画は[Start playback]で再生されます。
ARCoreのRecording and Playback APIをAR Foundationで。
— jyuko🐼@技術書典11 (@jyuko49) 2021年5月26日
夜の室内で昼の屋外のテストできる。 pic.twitter.com/s0nItUpT8f
再生した動画でも、録画時と同じように平面や点群(Point Cloud)が検出できています。
また、Playbackの動作を確認するため、サンプルシーンを一部修正して、画面タップで平面にキューブを置く処理を追加しています。赤いキューブはRecording時ではなく、Playback時に画面タップした位置に移動しました。
Recodingされた動画を確認する
Playbackの結果は一見すると、平面や点群も映像として録画されているように見えます。
そこで、Android Transferで保存されている動画をPCに転送して、確認してみます。
保存された動画は、arcore-session.mp4
というファイル名で保存されています。
こちらを再生してみると、カメラアプリで普通に録画したのと同じような風景だけの動画になっています。
ARCoreのドキュメントからDepthの情報は動画に含まれているようですが、平面や点群はPlayback時に検知・表示されていることになります。
Playbackの動作を確認する
平面や点群が動画には保存されていないことがわかったので、"AR Plane Manager"と"AR Point Cloud Manager"のPrefabに適用されているマテリアルを変更して、色などを変えてみます。
平面や点群は録画されたものではなくPlaybackで表示されているもの。
— jyuko🐼@技術書典11 (@jyuko49) 2021年5月26日
なので、色変えたりとかできます。 pic.twitter.com/VIcTwgGBdO
変更がPlaybackに反映されていますね。
続いて、AR Camera Backgroundに、カラーをネガティブ反転するマテリアルを適用してみます。
Camera Backgroundも反映されますね。 pic.twitter.com/dzuu5E7mcn
— jyuko🐼@技術書典11 (@jyuko49) 2021年5月26日
こちらもしっかり適用されています。
AR Sessionからのフィードバックを受けて行う処理(平面検知、点群取得、Hittest、カメラ画像やデプスの取得など)は、すべてPlaybackで再現できており、Playbackで実行するために既存の処理を変更する必要はありません。Playbackボタンを押すだけです。
APIの使い方を確認する
最後に、ARCoreSessionRecorderのスクリプトからAPIの使い方を見てみます。
Recording and Playbackは、"AR Session"で使用する情報を録画して再生する機能なので、"ARSession"が必須になります。
[RequireComponent(typeof(ARSession))]
保存するmp4ファイルのパスはAwake()
で定義されており、固定のファイル名になっています。 そのため、サンプルではRecordingを複数回行うと、動画が上書きされてしまいます。
m_Mp4Path = Path.Combine(Application.persistentDataPath, "arcore-session.mp4");
PCに転送できるにしても、実用性を考えると複数の動画を保存しておきたいので、保存時ファイル名にタイムスタンプを付与するなどして上書きされないように変更して使った方がよさそうです。
また、録画の設定として、保存先のファイル名だけでなく、画面の向きが必要なようです。このあたりはサンプルそのままの実装でも問題ないと思います。
static int GetRotation() => Screen.orientation switch { ScreenOrientation.Portrait => 0, ScreenOrientation.LandscapeLeft => 90, ScreenOrientation.PortraitUpsideDown => 180, ScreenOrientation.LandscapeRight => 270, _ => 0 };
ここからがAPIを呼び出す部分ですが、ARCoreの機能なのでUNITY_ANDROID
のみの処理としてから、"ARCoreSessionSubsystem"を参照しています。
現在Recordingを行っているか、Playbackを行っているかは.recordingStatus
、.playbackStatus
のプロパティで判別しています。
#if UNITY_ANDROID if (m_Session.subsystem is ARCoreSessionSubsystem subsystem) { var session = subsystem.session; if (session == null) return; var playbackStatus = subsystem.playbackStatus; var recordingStatus = subsystem.recordingStatus; ...
Recording開始時の処理です。
if (playbackStatus != ArPlaybackStatus.Finished && GUILayout.Button("Start recording")) { using (var config = new ArRecordingConfig(session)) { config.SetMp4DatasetFilePath(session, m_Mp4Path); config.SetRecordingRotation(session, GetRotation()); var status = subsystem.StartRecording(config); Log($"StartRecording to {config.GetMp4DatasetFilePath(session)} => {status}"); } }
ArRecordingConfig
を作成して、保存先のファイルパス、画面の向きをセットしています。
設定したconfigをsubsystem.StartRecording(config)
の形で使っており、このメソッドがARCoreのRecording APIで録画を開始する処理になりそうです。
停止時の処理はというと、subsystem.StopRecording()
を呼ぶだけでよさそうです。保存先のファイルパスは開始時にconfigで渡しているので、停止時には渡していません。
if (recordingStatus.Recording() && GUILayout.Button("Stop recording")) { var status = subsystem.StopRecording(); Log($"StopRecording() => {status}"); ...
次は、Playback開始時の処理です。
if (File.Exists(m_Mp4Path) && GUILayout.Button("Start playback")) { var status = subsystem.StartPlayback(m_Mp4Path); Log($"StartPlayback({m_Mp4Path}) => {status}"); }
subsystem.StartPlayback()
に保存してある動画のパスを渡しているだけですね。
停止も停止用のメソッドを呼ぶだけです。
if (playbackStatus.Playing() && !recordingStatus.Recording() && GUILayout.Button("Stop playback")) { var status = subsystem.StopPlayback(); Log($"StopPlayback() => {status}"); }
かなり簡単に使えそうですね。
まとめ
Recording and Playback APIを試してみました。
ARは周囲の環境(ロケーション)に大きく依存するため、実際にその場所に行って歩き回らなくても、一度録画してしまえば机上で何度でもテストできるというのは非常に有益です。
実際に使ってみるとかなり便利ですし、会場や現地に行かないと体験できない等、特定のロケーションで実施するARの開発であればさらに威力を発揮します。
使い方が難しくなく、簡単に導入できるのもよいです。
おわりに
同時に公開されたRaw Depthもそうですけど、ARCoreのアップデートは派手さはないものの、既存デバイスも対象として基本性能がベースアップしている感じで好感が持てますね。
目立った新機能がない分、実験的な機能はNianticのSDKに継承されてるような雰囲気もあるので、そちらの続報も待ちたいところです。
あと、AR FoundationはARCore/ARKitと連携取れてて、新機能のリリースとほぼ同時にサポートされるのでよいですね。