iPhone5sだけのスペシャルな機能として、秒間120コマでの高速撮影 があり、標準カメラアプリではこれを利用した スローモーション動画撮影機能 が可能となっています。
これに類する機能をAVFoundationで実装できないかやってみたところ、うまくいったので、その方法を紹介します。
できたもの
サンプルアプリをGitHubにアップしております。
- GitHub - shu223/SlowMotionVideoRecorder: 120/240 fps SLO-MO video recorder using AVFoundation. Including convenient wrapper class.
スクショ下部にあるように、 デフォルト / 60fps / 120fps を切り替えられるようになっています。
このアプリを使って撮ったものがこちら *1。
120fps Slow-Motion video recorded using AVFoundation.
(中盤をスローモーションにしています *2。)
実装方法
わりと複雑な処理になったので、AVFoundation関連の処理を全部ラップしたクラスをつくりました。
そのラッパークラス『AVCaptureManager』を使うと、下記のように3行で実装できます。
1. 初期化
self.captureManager = [[AVCaptureManager alloc] initWithPreviewView:self.view];
2. 録画開始
[self.captureManager startRecording];
3. 録画停止
[self.captureManager stopRecording];
停止したときに撮影した動画を保存する、とかはデリゲートメソッドを使用します。そのあたりはサンプルをご参照ください。
また今はこのサンプルの用途しか考慮されてないAPIになっているのですが、これから動画処理とかは積極的にやっていくので、随時拡張していく所存です。
ラッパーを使わない実装
大部分はAVCapture〜で動画撮影する場合の一般的な処理で、120fps実装ならではのポイントは 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
関連
- http://d.hatena.ne.jp/shu223/20121125/1353877706
- http://d.hatena.ne.jp/shu223/20121202/1354436478
- http://d.hatena.ne.jp/shu223/20121001/1354384097
- http://d.hatena.ne.jp/shu223/20121203/1356509154
- http://d.hatena.ne.jp/shu223/20130221/1361394373
- http://d.hatena.ne.jp/shu223/20131213/1386908558
AVFoundationを使うレシピは、下記書籍にもいくつか書いたのでもしよろしければ。
http://d.hatena.ne.jp/shu223/20130528/1369714635