リプレイデータを使って AR コンテンツ開発する

# リプレイデータとは

ARKit をつかってコンテンツ開発をする際に、あらかじめ実デバイスをつかってカメラ映像やセンサーデータ（replay data）を記録しておいて、開発環境時にそれをで再生することで実デバイスがなくてもカメラをぐりぐり動かさなくても現地にいかなくても開発できるようにする仕組み。

[MoAR](https://whatever.co/moar/) 開発チームはわたし (@Saqoosha) ときだくん (@kidapu) が東京、おかだくん (@migifun) が岡山、いぶくん (@asus4) がベルリン、って離れてるのでこのリプレイデータを使って開発できることはかなり重要だった。

VPS 使ったコンテンツの場合は現地に行けたとしてもずっとその対象ビルの前で開発するわけにもいかないので、なにかしらデスクトップで開発できる状態にしておかないとめちゃくちゃ開発がやりにくい。

# Geospatial API でリプレイデータが使えない

[Recording and Replaying AR Session Data \| Apple Developer Documentation](https://developer.apple.com/documentation/arkit/arsession/recording_and_replaying_ar_session_data)

↑の Apple のドキュメントに従ってふつうに Reality Composer でリプレイデータを録画すると GPS の位置情報も同時に記録される。
![rc1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2595/ad1afc7a-272c-1d2f-35e8-bf25e4f81eb3.jpeg)
デフォルトで "LOCATION RECORDING ON" になってる。

で、このリプレイデータを使って Geospatial API を使ったコードを実行しようすると以下のようなエラーが発生してカメラ映像が真っ暗になってまったく動作しない。

```
⛔️⛔️⛔️ ERROR [MOVReaderInterface]: Error Domain=com.apple.AppleCV3DMOVKit.readererror Code=9 "CVAUserEvent: Error Domain=com.apple.videoeng.streamreaderwarning Code=0 "Cannot grab metadata. Unknown metadata stream 'CVAUserEvent'." UserInfo={NSLocalizedDescription=Cannot grab metadata. Unknown metadata stream 'CVAUserEvent'.}" UserInfo={NSLocalizedDescription=CVAUserEvent: Error Domain=com.apple.videoeng.streamreaderwarning Code=0 "Cannot grab metadata. Unknown metadata stream 'CVAUserEvent'." UserInfo={NSLocalizedDescription=Cannot grab metadata. Unknown metadata stream 'CVAUserEvent'.}} ⛔️⛔️⛔️
[Session] ARSession <0x10270a060>: did fail with error: Error Domain=com.apple.arkit.error Code=101 "Required sensor unavailable." UserInfo={NSLocalizedDescription=Required sensor unavailable., NSLocalizedFailureReason=A required sensor is not available on this device.}
```

試しに "LOCATION RECORDING" を OFF にしたデータでリプレイするとエラーが消えてカメラ映像もリプレイデータで記録した映像が流し込まれていて一見動作しているように見えるんだけど、LOCATION RECORDING を OFF っているので Geospatial API がまず最初に必要とする位置情報が取得できなくっていつまでたっても localize しない。

じゃあ Xcode にはダミーの位置情報を起動時に与える Location Simulation 機能があるのでそれで位置情報を差し込めばいけるのでは？と思ってビルの緯度経度を設定してみてもやっぱり localize しない。

なんでかなーと思って普通にデバイス上でちゃんと localize する状態とリプレイデータでダメな状態の位置情報を `CLLocationManager` を使って比べてみると高度が違う… しかし Xcode の Location Simulation 機能には高度を指定する機能は無い…

ということで Geospatial API を使う場合はリプレイデータが使用できない… 開発めんどい… のかと思いきや位置情報だけの問題なのでビル付近（内部）にいて位置情報がホンモノに近い状態であればリプレイデータ使用時でも Geospatial API がちゃんと localize してコンテンツ開発できるのでした。yay!

# Location Anchors だとちゃんとリプレイデータ使える

ARKit の Location Anchors を使う場合はふつうに Reality Composer で LOCATION RECORDING ON にしたリプレイデータがふつうに使えるのでふつうにどこにいても VPS コンテンツ開発できる。

MoAR ではビル付近で開発できる場合は LOCATION RECORDING OFF なリプレイデータで Geospatial API で開発、遠いとこで開発するときは LOCATION RECORDING ON で Location Anchors で開発っていうように2パターンのターゲットつくって VPS を内部で切り替えられるようにしてた。（Geospatial API のが精度がいいので

# 機種ごとにリプレイデータを作らないといけない？

どうやら Reality Composer で録画したときの機種とリプレイデータを使用する機種が違うと使えないっぽい。
iPhone 13 で録画したリプレイデータは iPhone 12 で開発するときには使えないし逆もダメ。（iPhone 11 のリプレイデータは iPhone 13 で使えたような気がするけど、ちょっとそのへんの法則がよくわからない…
![Screen Shot 2022-12-05 at 18.26.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2595/1460340e-42d5-395f-b093-190323ba35fe.png)
↑ MoAR 開発時に使っていたリプレイデータたち。機種ごととか Geospatial API 用と Location Anchors 用とあと視点位置の違いとか昼と夜の違いとかのバリエーションがいっぱいあってリプレイデータもいっぱいある。

# リプレイデータの転送もうちょっと速くならん？

ファイルサイズが大きいってのもあるかもしれないけど Xcode からリプレイデータを iPhone にコピーするがめちゃくちゃ遅くて5分ぐらい待つ。（長さによるけど

いくつかのパターンのリプレイデータを切り替えようとするとそのたびに転送が始まってめっちゃ待つことになるのでなんとかならんかなーと思っている。

# 便利

とはいえ AR (VPS) コンテンツ開発で現地に行かなくても開発できるしデスクで再現できればイテレーションも早くなるのでめちゃんこ便利。

Unity とかでも使えればいいのに〜、みたいな話を @asus4 が書いてくれるっぽいので期待。