ハウツー

CameraX 1.5 での高速キャプチャとスローモーション動画

6 分で読了
Leo Huang
ソフトウェア エンジニア

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

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


スローモーションの原理

スローモーションの基本的な原理は、再生するよりもはるかに高いフレームレートで動画をキャプチャすることです。たとえば、1 秒間のイベントを 120 フレーム/秒(FPS) で録画し、その録画を標準の 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: これは、VideoCapture ユースケースと Preview ユースケースをグループ化する特別な構成オブジェクトで、統合された高速カメラ セッションを作成するように CameraX に指示します。VideoCapture ストリームは構成された高フレームレートで動作しますが、Preview ストリームは通常、画面にスムーズに表示されるように、カメラ システムによって少なくとも 30 FPS の標準レートに制限されます。

スタートガイド

手順を開始する前に、必要な CameraX 依存関係をアプリの build.gradle.kts ファイルに追加していることを確認してください。コア 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 を取得し、デバイスの機能を確認して、ユースケースを作成する必要があります。

次のコードブロックは、suspend 関数内の完全な設定フローを示しています。この関数は、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)。

すべてをまとめる: 動画を録画する

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 システムに依存して、デバイスがサポートする高速解像度とフレームレートを決定します。CamcorderProfile は 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 フラグの役割を理解することで、両方のユースケースを簡単にサポートし、ユーザーにクリエイティブな操作を提供できます。

執筆者:

続きを読む