CALINTとは

CALINT(カリント)とは、株式会社moegiよりリリースされた、いわゆるプロットマッピングカメラアプリです。
※現在はiOSのみリリース済み

カメラで撮影を行いながら、同時に地図や速度、カメラの向きや標高などを記録できます。
具体的には、mp4、csv、gpxファイルを同時に記録できるアプリになります。

詳しくは、以下の公式サイト、および使用イメージを是非ご覧ください!

公式サイト: CALINT

使用イメージ

こちらの動画を見ていただければおおよそのアプリのイメージが掴んでいただけるかと思います!
ハイキングやドライブ、電車内・飛行機内からの撮影等、様々なシーンでご利用いただけるかと(^^)

開発時の話

諸事情により内部の作りの詳細についてはあまり記述できませんが、せっかくなので開発時の苦労話等を少しご紹介します

アーキテクチャについて

今回はReactorKitを用いたFluxアーキテクチャを採用しました。

理由としては、アプリの特性上、様々なトリガー(ユーザーのタップや、GPSのコールバック、ファイル保存時のコールバック等)で処理が走る為、トリガーに関わらず処理のフローを一方向に限定し、各処理の記述位置を明確にしてコードをシンプルにし、バグを減らしたかった為です。
(ただでさえ録画周りで原因不明なクラッシュが発生しやすい・・・)

また、非同期での処理を前提とした構成にすることで、様々なトリガーによって処理が走った場合でも、自然とユーザー操作を邪魔しない(UIスレッドをブロックしない)作りにするという狙いもありました。

iOSでの録画について

iOSでのカメラを用いた録画方法については、Qiita等にいくつかの良質な記事が挙がっています。

ただし、今回の要件として、カメラに映った映像をそのまま録画するのではなく、画面上に表示している地図や速度計等のViewも同時に記録する必要がありました。

その場合、以下の2通りの録画方法を検討しました。

  1. カメラでキャプチャした映像にViewを合成し記録する
  2. デバイスに表示されているViewを丸ごと記録する

1. カメラでキャプチャした映像にViewを合成し記録する

こちらの方法についてまず試したところ、合成すべきViewの内容(地図や速度)が常に変化するものである為、毎フレーム合成し直す必要があり、処理が1フレームの時間内に収まらず、録画ファイルが明らかにコマ落ちしているような品質になってしまい、断念しました。
ただし、こちらの方法ではiOSが備えているカメラの手ぶれ補正機能を使えるという大きなメリットがある為、撮影内容のクオリティを求める場合はこちらの方法をお勧めします。

2. デバイスに表示されているViewを丸ごと記録する

こちらは、iOS11から搭載されたスクリーンレコーディングとほぼ同じイメージです。(参考記事

そして、嬉しいことに単純に撮影するだけであれば、ReplayKitという上記のスクリーンレコーディングがアプリ内からできるツールが標準で用意されています。 (参考記事

ただし、上記参考記事のようなシンプルな使い方を行った場合、撮影終了時に RPPreviewController を呼び出してユーザーに保存またはシェアさせる、といったフローになる(プログラム側で勝手に保存できない)為、ReplayKitで撮影し渡されたbufferを AVAssetWriter を用いて毎フレーム記録する、という方法を取っています。

ReplayKitを使った撮影

これが、様々な要因でクラッシュします・・・
また、クラッシュした際に出てくるメッセージが Error Domain=com.apple.ReplayKit.RPRecordingErrorDomain Code=-5807 "Recording interrupted by multitasking and content resizing" といったよく分からないものばかりです。
エラーコードっぽいものが出てますが、このコードの詳細についてはAppleのドキュメントに一切記載が無い為、非常に苦労しました・・・

iOSシミュレータが使えない

カメラ機能をフルに使ったアプリである為、シミュレータでの開発がほぼできず、 iPhone X 等の対応を実機でやらざるを得ず、こちらもまた苦労しました・・・

さいごに

とりとめのない紹介になってしまいましたが、アプリ内容や開発話等、何かありましたらTwitter等で気軽に呼びかけていただければと思います!