iPhone5s以降で登場した機能として、秒間120コマ(2013年当時。最近は240コマ)までの高速撮影 があり、標準カメラアプリではこれを利用した スローモーション動画撮影機能 が可能となっています。
これに類する機能をAVFoundationで実装できないかやってみたところ、うまくいったので、その方法を紹介します。
##できたもの
サンプルアプリをGitHubにアップしております。
スクショ下部にあるように、 デフォルト / 60fps / 240fps を切り替えられるようになっています。
このアプリを使って撮ったものがこちら(寒かったので外に出てすぐ目の前にあったこれを撮影しました)。
120fps Slow-Motion video recorded using AVFoundation.
(中盤をスローモーションにしています。)
##実装方法
わりと複雑な処理になったので、 AVFoundation関連の処理を全部ラップしたクラス をつくりました。
そのラッパークラス TTMCaptureManager
を使うと、下記のように 3行 で実装できます。
###1. 初期化
self.captureManager = [[TTMCaptureManager alloc] initWithPreviewView:self.view];
###2. 録画開始
[self.captureManager startRecording];
###3. 録画停止
[self.captureManager stopRecording];
停止したときに撮影した動画を保存する、とかはデリゲートメソッドを使用します。そのあたりはサンプルをご参照ください。
また今はこのサンプルの用途しか考慮されてないAPIになっているのですが、これから動画処理とかは積極的にやっていくので、随時拡張していく所存です。
##ラッパーを使わない実装
大部分はAVCapture~で動画撮影する場合の一般的な処理で、240fps実装ならではのポイントは AVCaptureManager の次の部分に集約されています。
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceFormat *selectedFormat = nil;
int32_t maxWidth = 0;
AVFrameRateRange *frameRateRange = nil;
for (AVCaptureDeviceFormat *format in [videoDevice formats]) {
for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) {
CMFormatDescriptionRef desc = format.formatDescription;
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(desc);
int32_t width = dimensions.width;
if (range.minFrameRate <= desiredFPS && desiredFPS <= range.maxFrameRate && width >= maxWidth) {
selectedFormat = format;
frameRateRange = range;
maxWidth = width;
}
}
}
if (selectedFormat) {
if ([videoDevice lockForConfiguration:nil]) {
NSLog(@"selected format:%@", selectedFormat);
videoDevice.activeFormat = selectedFormat;
videoDevice.activeVideoMinFrameDuration = CMTimeMake(1, (int32_t)desiredFPS);
videoDevice.activeVideoMaxFrameDuration = CMTimeMake(1, (int32_t)desiredFPS);
[videoDevice unlockForConfiguration];
}
}
処理の内容としては、
- AVCaptureDevice の formats プロパティから使用可能なフォーマットのリストを取得
- その中から所望のfpsを満たすものを探索
- 同じfpsなら幅がより大きい方をとる
- 見つかれば AVCaptureDevice の activeFormat プロパティにセットする
ということを行っています。
#Special Thanks!!
@hkato193 さんにTwitterで諸々教えていただきました。ありがとうございました!
インプレスジャパン
売り上げランキング: 2,641
##関連
- iOS のオーディオ/サウンド処理について学べる書籍10冊+α
- シャッター音の鳴らないカメラアプリの実装方法
- UIImagePickerController を使わないカメラアプリの実装方法
- AVFoundation 使用時のカメラ起動を高速化する
- ダウンロード可能な Audio Unit 関連のサンプルコード11個
- PerfumeのモーションキャプチャデータをiOSアプリ内で動かしてみる
AVFoundationを使うレシピは、下記書籍にもいくつか書いたのでもしよろしければ。