Help us understand the problem. What is going on with this article?

AV Foundationで240fpsスローモーション動画撮影を実装する

More than 3 years have passed since last update.

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で諸々教えていただきました。ありがとうございました!

上を目指すプログラマーのためのiPhoneアプリ開発テクニック iOS 7編
加藤 寛人 西方 夏子 藤川 宏之 鈴木 晃 高丘 知央
インプレスジャパン
売り上げランキング: 2,641

関連

AVFoundationを使うレシピは、下記書籍にもいくつか書いたのでもしよろしければ。

『iOSアプリ開発 達人のレシピ100』という本を書きました

shu223
フリーランスiOSエンジニア 著書:『iOS×BLE Core Bluetooth プログラミング』『Metal入門』『実践ARKit』『Depth in Depth』『iOSアプリ開発 達人のレシピ100』他 GitHubの累計スター数23,000超
http://shu223.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした