ハウツー

CameraX 1.5 での高速撮影とスローモーション動画

所要時間: 6 分
Leo Huang
ソフトウェア エンジニア

動きの速いアクションを鮮明に撮影することは、最新のカメラアプリの重要な機能です。これは、120 fps や 240 fps などのレートでフレームを取得するプロセスである高速キャプチャによって実現されます。この高忠実度キャプチャは、2 つの異なる目的で使用できます。詳細なフレーム単位の分析を行うための高フレームレート動画の作成、または画面上でアクションが劇的に展開されるスローモーション動画の生成です。

以前は、Camera2 API でこれらの機能を実装するには、より実践的なプロセスが必要でした。CameraX 1.5 の新しい高速 API を使用すると、プロセス全体が簡素化され、真の高フレームレート動画と再生可能なスローモーション クリップのどちらでも柔軟に作成できます。この記事では、両方を使いこなす方法をご紹介します。CameraX を初めて使用する場合は、CameraX の概要をご覧ください。


スローモーションの原理

スローモーションの基本原理は、再生するよりもはるかに高いフレームレートで動画をキャプチャすることです。たとえば、120 フレーム/秒(fps)で 1 秒間のイベントを録画し、その録画を標準の 30 fps で再生すると、動画の再生に 4 秒かかります。この時間の「引き伸ばし」によって、ドラマチックなスローモーション効果が生まれ、肉眼では見えないほど速い動きの詳細を確認できます。

最終的な出力動画をスムーズで滑らかなものにするには、通常、30 fps 以上でレンダリングする必要があります。つまり、4 倍のスローモーション動画を作成するには、元のキャプチャ フレームレートが 120 fps 以上である必要があります(120 キャプチャ fps ÷ 4 = 30 再生 fps)。

高フレームレートの映像をキャプチャしたら、次の 2 つの主な方法で目的の結果を得ることができます。

  • プレーヤー処理のスローモーション(高フレームレート動画): 高速録画(120 fps など)は、高フレームレート動画ファイルとして直接保存されます。動画プレーヤーは、再生速度を遅くする責任を負います。これにより、ユーザーは通常再生とスローモーション再生を柔軟に切り替えることができます。
  • 再生可能なスローモーション(再エンコードされた動画): 高速動画ストリームが処理され、標準フレームレート(30 fps など)のファイルに再エンコードされます。フレームのタイムスタンプを調整することで、スローモーション効果が「焼き付け」られます。作成された動画は、特別な処理をしなくても、標準の動画プレーヤーでスローモーションで再生されます。動画はデフォルトでスローモーションで再生されますが、動画プレーヤーは、ユーザーが速度を上げて元の速度で動画を視聴できる再生速度コントロールを提供できます。

CameraX API では、以下に示すように、どちらのアプローチを選択するかを統一された方法で指定できるため、この処理が簡素化されます。


新しい高速動画 API

新しい CameraX ソリューションは、次の 2 つの主要コンポーネント上に構築されています。

  • Recorder#getHighSpeedVideoCapabilities(CameraInfo): このメソッドを使用すると、カメラで高速録画が可能かどうか、また可能な場合はどの解像度(Quality オブジェクト)がサポートされているかを確認できます。
  • HighSpeedVideoSessionConfig: VideoCapturePreview のユースケースをグループ化し、CameraX に統合された高速カメラ セッションを作成するよう指示する特別な構成オブジェクトです。VideoCapture ストリームは設定された高いフレームレートで動作しますが、プレビュー ストリームは通常、画面上でスムーズに表示されるように、カメラ システムによって 30 FPS 以上の標準レートに制限されます。

スタートガイド

開始する前に、アプリの build.gradle.kts ファイルに必要な CameraX 依存関係を追加していることを確認してください。コア CameraX ライブラリとともに camera-video アーティファクトが必要になります。

// build.gradle.kts (Module: app)

dependencies {

    val camerax_version = "1.5.1"


    implementation("androidx.camera:camera-core:$camerax_version")

    implementation("androidx.camera:camera-camera2:$camerax_version")

    implementation("androidx.camera:camera-lifecycle:$camerax_version")

    implementation("androidx.camera:camera-video:$camerax_version")

    implementation("androidx.camera:camera-view:$camerax_version")

}

試験運用版 API に関する注意

高速録画 API は現在試験運用版であることにご注意ください。つまり、今後のリリースで変更される可能性があります。これらを使用するには、次のアノテーションをコードに追加してオプトインする必要があります。

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

実装

どちらの結果も、実装は同じ設定手順から始まります。高フレームレート動画とスローモーション動画のどちらを作成するかは、1 つの設定で決まります。

1. ハイスピード撮影を設定する

まず、目標に関係なく、ProcessCameraProvider を取得し、デバイスの機能をチェックして、ユースケースを作成する必要があります。

次のコードブロックは、一時停止関数内の完全な設定フローを示しています。この関数は、lifecycleScope.launch などのコルーチン スコープから呼び出すことができます。

// Add the OptIn annotation at the top of your function or class

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

private suspend fun setupCamera() {

    // Asynchronously get the CameraProvider

    val cameraProvider = ProcessCameraProvider.awaitInstance(this)



    // -- CHECK CAPABILITIES --

    val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA)

    val videoCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

    if (videoCapabilities == null) {

        // This camera device does not support high-speed video.

        return

    }




    // -- CREATE USE CASES --

    val preview = Preview.Builder().build()    


    // You can create a Recorder with default settings.

    // CameraX will automatically select a suitable quality.

    val recorder = Recorder.Builder().build()


    // Alternatively, to use a specific resolution, you can configure the
    // Recorder with a QualitySelector. This is useful if your app has
    // specific resolution requirements or you want to offer user
    // preferences. 

    // To use a specific quality, you can uncomment the following lines.

    // Get the list of qualities supported for high-speed video. 

    // val supportedQualities = videoCapabilities.getSupportedQualities(DynamicRange.SDR)

    // Build the Recorder using the quality from the supported list.

    // val recorderWithQuality = Recorder.Builder()

    //     .setQualitySelector(QualitySelector.from(supportedQualities.first()))

    //     .build()



    // Create the VideoCapture use case, using either recorder or recorderWithQuality

    val videoCapture = VideoCapture.withOutput(recorder)

    // Now you are ready to configure the session for your desired output...

}

2. 出力の選択

次に、作成する動画の種類を決めます。このコードは、上記の setupCamera() suspend 関数内で実行されます。

オプション A: 高フレームレート動画を作成する

最終的なファイルのフレームレートを高くしたい場合(120 fps の動画など)は、このオプションを選択します。

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)


// Query and apply a supported frame rate. Common supported frame rates include 120 and 240 fps.

val supportedFrameRateRanges =

    cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())


sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

オプション B: 再生可能なスローモーション動画を作成する

標準の動画プレーヤーでスローモーションで自動再生される動画が必要な場合は、このオプションを選択します。

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)



// This is the key: enable automatic slow-motion!

sessionConfigBuilder.setSlowMotionEnabled(true)



// Query and apply a supported frame rate. Common supported frame rates include 120, 240, and 480 fps.

val supportedFrameRateRanges =

   cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())

sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

この 1 つのフラグが、再生可能なスローモーション動画を作成する鍵となります。setSlowMotionEnabled が true の場合、CameraX は高速ストリームを処理し、標準の 30 fps 動画ファイルとして保存します。スロー モーションの速度は、キャプチャ フレームレートとこの標準再生速度の比率によって決まります。

次に例を示します。

  • 120 fps で録画すると、1/4 倍速で再生される動画が生成されます(120 ÷ 30 = 4)。
  • 240 fps で録画すると、1/8 倍速で再生される動画が生成されます(240 ÷ 30 = 8)。

すべてを 1 つに: 動画の録画

HighSpeedVideoSessionConfig を構成してライフサイクルにバインドしたら、最後のステップは録画を開始することです。出力オプションの準備、録画の開始、動画イベントの処理のプロセスは、標準の動画キャプチャの場合と同じです。

この記事では高速構成に焦点を当てるため、録画プロセスについては詳しく説明しません。FileOutputOptions オブジェクトまたは MediaStoreOutputOptions オブジェクトの準備から VideoRecordEvent コールバックの処理まで、あらゆることに関する包括的なガイドについては、VideoCapture ドキュメントを参照してください。

// Bind the session config to the lifecycle

cameraProvider.bindToLifecycle(

    this as LifecycleOwner,

    CameraSelector.DEFAULT_BACK_CAMERA,

    sessionConfigBuilder.build() // Bind the config object from Option A or B

)



// Start the recording using the VideoCapture use case

val recording = videoCapture.output

    .prepareRecording(context, outputOptions) // See docs for creating outputOptions

    .start(ContextCompat.getMainExecutor(context)) { recordEvent ->

        // Handle recording events (e.g., Start, Pause, Finalize)

    }

Google フォトでスローモーション動画をサポート

CameraX で setSlowMotionEnabled(true) を有効にすると、標準の動画プレーヤーやギャラリー アプリでスローモーションとしてすぐに認識して再生できるように、動画ファイルが作成されます。特に Google フォトでは、キャプチャ フレームレートが 120、240、360、480、960 fps のスローモーション動画に対して、次のような機能が強化されています。

  • サムネイルでの UI の識別: Google フォト ライブラリで、スローモーション動画は特定の UI 要素で識別され、通常の動画と区別されます。
normal.png
  • 再生中の速度調整可能なセグメント: スローモーション動画の再生中に、動画のどの部分をスローモーションで再生し、どの部分を通常の速度で再生するかを調整できるコントロールが Google フォトに表示され、ユーザーはクリエイティブなコントロールを行うことができます。編集した動画は、[共有] ボタンを使用して新しい動画ファイルとしてエクスポートできます。このとき、定義したスローモーション セグメントは保持されます。
normal2.png

デバイスのサポートに関する注意事項

CameraX の高速 API は、基盤となる Android の CamcorderProfile システムに依存して、デバイスがサポートする高速解像度とフレームレートを決定します。CamcorderProfiles は Android 互換性テストスイート(CTS)によって検証されるため、デバイスの報告された動画録画機能は信頼できます。

つまり、内蔵カメラアプリでスローモーション動画を録画できるデバイスでも、CameraX 高速 API が機能するとは限りません。この不一致は、デバイス メーカーがデバイスのファームウェアで CamcorderProfile エントリを設定する責任を負っているためです。必要な高速プロファイル(CamcorderProfile.QUALITY_HIGH_SPEED_1080PCamcorderProfile.QUALITY_HIGH_SPEED_720P など)が含まれていないことがあります。これらのプロファイルがない場合、Recorder.getHighSpeedVideoCapabilities()null を返します。

そのため、Recorder.getHighSpeedVideoCapabilities() を使用してサポートされている機能をプログラムで確認することが重要です。これは、さまざまなデバイスで一貫したエクスペリエンスを確保するための最も信頼性の高い方法です。Recorder.getHighSpeedVideoCapabilities() が null を返すデバイスで HighSpeedVideoSessionConfig をバインドしようとすると、オペレーションは IllegalArgumentException で失敗します。Google Pixel デバイスでは、これらの高速プロファイルが常に含まれているため、サポートを確認できます。また、Motorola Edge 30、OPPO Find N2 Flip、Sony Xperia 1 V など、他のメーカーのさまざまなデバイスも高速動画機能をサポートしています。


まとめ

CameraX 高速動画 API は、強力かつ柔軟です。技術分析用の真のハイフレームレート映像が必要な場合でも、アプリに映画のようなスローモーション効果を追加したい場合でも、HighSpeedVideoSessionConfig は統一されたシンプルなソリューションを提供します。setSlowMotionEnabled フラグの役割を理解することで、両方のユースケースを簡単にサポートし、ユーザーがよりクリエイティブなコントロールを行えるようにすることができます。

作成者:

続きを読む