サービスに関する最新情報

CameraX 1.5 のご紹介: 強力な動画撮影とプロレベルの画像キャプチャ

所要時間: 7 分
Scott Nien さんのプロフィールを表示
Scott Nien ソフトウェア エンジニア

CameraX チームは、バージョン 1.5 のリリースを発表いたします。今回の最新アップデートでは、プロレベルの機能を簡単に利用できるようにするとともに、カメラ セッションの設定をこれまで以上に簡単に行えるようにすることに重点を置いています。

動画撮影では、美しいスローモーション動画や高フレームレート動画を簡単に撮影できるようになりました。さらに重要なのは、新しい Feature Group API を使用すると、10 ビット HDR と 60 FPS などの複雑な組み合わせを確実に有効にできるため、サポートされているデバイス間で一貫した結果が得られることです。

画像キャプチャの面では、未処理の非圧縮 DNG(RAW)ファイルのキャプチャがサポートされることで、最大限の柔軟性が得られます。さらに、高性能な Camera Extensions を使用している場合でも、ウルトラ HDR 出力を利用できるようになりました。

これらの機能を支えているのが、カメラの設定と再設定を効率化する新しい SessionConfig API です。それでは、これらの魅力的な新機能について詳しく見ていきましょう。

強力な動画撮影: 高速撮影と機能の組み合わせ

CameraX 1.5 では動画機能が大幅に拡張され、よりクリエイティブで堅牢な録画エクスペリエンスが実現します。

スローモーション動画と高フレームレート動画

最も要望の多かった機能の一つであるスローモーション動画が利用可能になりました。高速動画(120 fps や 240 fps など)をキャプチャして、ドラマチックなスローモーション動画に直接エンコードできるようになりました。また、同じ高フレームレートで録画して、非常に滑らかな動画を作成することもできます。

VideoCapture API に精通している場合は、この実装は簡単です。

1. 高速サポートの確認: 新しい Recorder.getHighSpeedVideoCapabilities() メソッドを使用して、デバイスがこの機能をサポートしているかどうかをクエリします。

val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)

val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

if (highSpeedCapabilities == null) {
    // This camera device does not support high-speed video.
    return
}

2. ユースケースを構成してバインドする: 返された videoCapabilities(サポートされている動画の画質情報を含む)を使用して、HighSpeedVideoSessionConfig をビルドします。次に、cameraInfo.getSupportedFrameRateRanges() を使用して、サポートされているフレームレート範囲をクエリし、目的の範囲を設定する必要があります。スローモーション動画を撮影するには、setSlowMotionEnabled(true) を呼び出します。それ以外の場合は、高フレームレート動画が撮影されます。最後のステップは、通常の Recorder.prepareRecording().start() を使用して動画の録画を開始することです。

val preview = Preview.Builder().build()
val quality = highSpeedCapabilities
        .getSupportedQualities(DynamicRange.SDR).first()

val recorder = Recorder.Builder()
      .setQualitySelector(QualitySelector.from(quality)))
      .build()

val videoCapture = VideoCapture.withOutput(recorder)

val frameRateRange = cameraInfo.getSupportedFrameRateRanges(      
       HighSpeedVideoSessionConfig(videoCapture, preview)
).first()

val sessionConfig = HighSpeedVideoSessionConfig(
    videoCapture, 
    preview, 
    frameRateRange = frameRateRange, 
    // Set true for slow-motion playback, or false for high-frame-rate
    isSlowMotionEnabled = true
)

cameraProvider.bindToLifecycle(
     lifecycleOwner, cameraSelector, sessionConfig)

// Start recording slow motion videos. 
val recording = recorder.prepareRecording(context, outputOption)
      .start(executor, {})

互換性と制限事項

高速録画には、特定の CameraConstrainedHighSpeedCaptureSession と CamcorderProfile のサポートが必要です。ユーザー エクスペリエンスの低下を防ぐため、必ず機能チェックを行い、対応デバイスでのみ高速録画を有効にしてください。現在、この機能はほぼすべての Google Pixel デバイスの背面カメラと、他のメーカーの一部のモデルでサポートされています。

詳しくは、ブログ投稿をご覧ください。

特徴を確実に組み合わせる: Feature Group API

CameraX 1.5 では、機能の互換性を推測する必要がなくなる Feature Group API が導入されています。Android 15 の機能の組み合わせをクエリする API に基づいて、複数の機能を同時に有効にできるようになり、安定したカメラ セッションが保証されます。現在、この機能グループは、HDR(HLG)、60 fps、プレビューの手ぶれ補正、ウルトラ HDR をサポートしています。たとえば、Google Pixel 10 と Galaxy S25 シリーズでは、HDR、60 fps、プレビューの手ぶれ補正を同時に有効にできます。今後の機能強化では、4K 録画とウルトラワイド ズームが追加される予定です。

特徴グループ API を使用すると、次の 2 つの重要なユースケースを実現できます。

ユースケース 1: 最高品質を優先する

最適な機能の組み合わせを使用してキャプチャする場合は、優先順位付きのリストを指定できます。CameraX は、デバイスが完全にサポートする最初の組み合わせを選択して、順番に有効にしようとします。

val sessionConfig = SessionConfig(
    useCases = listOf(preview, videoCapture),
    preferredFeatureGroup = listOf(
        GroupableFeature.HDR_HLG10,
        GroupableFeature.FPS_60,
        GroupableFeature.PREVIEW_STABILIZATION
    )
).apply {
    // (Optional) Get a callback with the enabled features to update your UI.
    setFeatureSelectionListener { selectedFeatures ->
        updateUiIndicators(selectedFeatures)
    }
}
processCameraProvider.bindToLifecycle(activity, cameraSelector, sessionConfig)

この例では、CameraX は次の順序で機能を有効にしようとします。

  1. HDR + 60 FPS + プレビューの手ぶれ補正
  2. HDR + 60 FPS
  3. HDR + プレビューの手ぶれ補正
  4. HDR
  5. 60 FPS + プレビューの手ぶれ補正
  6. 最大 60 FPS
  7. プレビューの手ぶれ補正
  8. なし

ユースケース 2: ユーザー向け設定 UI を構築する

アプリの設定 UI で、サポートされている機能の組み合わせを正確に反映できるようになりました。サポートされていないオプションの切り替えは、下の画像のように無効になります。

unsupported-features-disabled.gif

切り替えボタンをグレー表示にするかどうかを判断するには、次のコードを使用して、機能の組み合わせがサポートされているかどうかを確認します。最初に、個々の機能のステータスをクエリします。機能が有効になったら、有効になった機能とともに残りの機能を再度クエリして、互換性の制約によりトグルをグレー表示にする必要があるかどうかを確認します。

fun disableFeatureIfNotSuported(
   enabledFeatures: Set<GroupableFeature>,     
   featureToCheck:GroupableFeature
) {
 val sessionConfig = SessionConfig(
     useCases = useCases,
     requiredFeatureGroup = enabledFeatures + featureToCheck
 )
 val isSupported = cameraInfo.isFeatureGroupSupported(sessionConfig)

 if (!isSupported) {
     // disable the toggle for featureToCheck
 }
}

詳しくは、Feature Group のブログ投稿をご覧ください。

その他の動画拡張機能

  • 同時カメラの改善: CameraX 1.5.1 では、非コンポジション モードで各 SingleCameraConfig に Preview、ImageCapture、VideoCapture のユースケースを同時にバインドできるようになりました。また、作成モード(CompositionSettings と同じユースケース)では、最終的な合成結果に適用される CameraEffect を設定できるようになりました。
  • 動的なミュート: PendingRecording.withAudioEnabled(boolean initialMuted) を使用してミュート状態で録音を開始し、後でユーザーが Recording.mute(boolean muted) を使用してミュートを解除できるようになりました。
  • ストレージ不足の処理を改善: CameraX が VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE エラーを確実にディスパッチするようになり、アプリがストレージ不足の状況を適切に処理してユーザーに通知できるようになりました。
  • Low Light Boost: 対応デバイス(Google Pixel 10 シリーズなど)では、CameraControl.enableLowLightBoostAsync を有効にすることで、暗い環境でプレビュー ストリームと動画ストリームを自動的に明るくできます。

プロ仕様の画像キャプチャ

CameraX 1.5 では、最高品質と柔軟性を求めるデベロッパー向けに、ImageCapture に大幅なアップグレードが加えられています。

DNG(RAW)撮影でクリエイティブなコントロールを可能に

後処理を完全に制御できるように、CameraX で DNG(RAW)キャプチャがサポートされるようになりました。これにより、カメラセンサーから直接、未処理、未圧縮の画像データにアクセスできるため、プロレベルの編集やカラー グレーディングが可能になります。API は、DNG ファイルのみのキャプチャ、または JPEG と DNG の同時出力のキャプチャをサポートしています。JPEG ファイルと DNG ファイルを同時にキャプチャする方法については、以下のサンプルコードをご覧ください。

val capabilities = ImageCapture.getImageCaptureCapabilities(cameraInfo)
val imageCapture = ImageCapture.Builder().apply {
    if (capabilities.supportedOutputFormats
             .contains(OUTPUT_FORMAT_RAW_JPEG)) {
        // Capture both RAW and JPEG formats.
        setOutputFormat(OUTPUT_FORMAT_RAW_JPEG)
    }
}.build()
// ... bind imageCapture to lifecycle ...


// Provide separate output options for each format.
val outputOptionRaw = /* ... configure for image/x-adobe-dng ... */
val outputOptionJpeg = /* ... configure for image/jpeg ... */
imageCapture.takePicture(
    outputOptionRaw,
    outputOptionJpeg,
    executor,
    object : ImageCapture.OnImageSavedCallback {
        override fun onImageSaved(results: OutputFileResults) {
            // This callback is invoked twice: once for the RAW file
            // and once for the JPEG file.
        }

        override fun onError(exception: ImageCaptureException) {}
    }
)

カメラ拡張機能のウルトラ HDR

カメラ拡張機能の優れた計算写真学(夜間モードなど)と、ウルトラ HDR の鮮やかな色とダイナミック レンジを組み合わせた、両方の長所を活かした撮影が可能です。この機能は、Google Pixel 9 / 10 シリーズや Samsung S24 / S25 シリーズなど、最近の多くのプレミアム Android スマートフォンでサポートされています。

// Support UltraHDR when Extension is enabled. 

val extensionsEnabledCameraSelector = extensionsManager
     .getExtensionEnabledCameraSelector(
        CameraSelector.DEFAULT_BACK_CAMERA, ExtensionMode.NIGHT)

val imageCapabilities = ImageCapture.getImageCaptureCapabilities(
               cameraProvider.getCameraInfo(extensionsEnabledCameraSelector)

val imageCapture = ImageCapture.Builder()
     .apply {
       if (imageCapabilities.supportedOutputFormats
                .contains(OUTPUT_FORMAT_JPEG_ULTRA_HDR) {
           setOutputFormat(OUTPUT_FORMAT_JPEG_ULTRA_HDR)

       }

     }.build()

コア API とユーザビリティの強化

新しい構成方法: SessionConfig

上記の例でわかるように、SessionConfig は CameraX 1.5 の新しいコンセプトです。構成を一元化し、次の 2 つの主な方法で API を簡素化します。

  1. 手動による unbind() 呼び出しが不要: CameraX API はライフサイクルに対応しています。アクティビティまたは他の LifecycleOwner が破棄されると、ユースケースは暗黙的に「バインド解除」されます。ただし、ユースケースを更新したり、カメラを切り替えたりする場合は、再バインドする前に unbind() または unbindAll() を呼び出す必要があります。CameraX 1.5 では、新しい SessionConfig をバインドすると、CameraX がセッションをシームレスに更新するため、バインド解除の呼び出しが不要になります。
  2. 決定論的なフレームレート制御: 新しい SessionConfig API では、フレームレートを管理する決定論的な方法が導入されています。以前の setTargetFrameRate はヒントにすぎませんでしたが、この新しいメソッドでは、構成が成功すると、指定されたフレームレート範囲が適用されることが保証されます。精度を確保するには、CameraInfo.getSupportedFrameRateRanges(SessionConfig) を使用して、サポートされているフレームレートをクエリする必要があります。完全な SessionConfig を渡すことで、CameraX はストリーム構成に基づいてサポートされている範囲を正確に判断できます。

Camera-Compose が安定版に

Jetpack Compose をご利用の皆様に、camera-compose ライブラリの安定版バージョン 1.5.1 がリリースされたことをお知らせします。このリリースには、moveableContentOf や Pager などの Compose 機能での CameraXViewfinder の使用に関連する重要なバグの修正と、プレビューの引き伸ばしの問題の解決が含まれています。今後も camera-compose に機能を追加していく予定です。

ImageAnalysis と CameraControl の改善

  • ライトの強さの調整: 新しい API により、デバイスのライトをきめ細かく制御できます。CameraInfo.getMaxTorchStrengthLevel() を使用して、サポートされている最大強度をクエリし、CameraControl.setTorchStrengthLevel() で目的のレベルを設定できます。
  • ImageAnalysis での NV21 のサポート: ImageAnalysis から NV21 画像形式を直接リクエストできるようになり、他のライブラリや API との統合が簡素化されました。これは、ImageAnalysis.Builder.setOutputImageFormat(OUTPUT_IMAGE_FORMAT_NV21) を呼び出すことで有効になります。

今すぐ始めましょう

今すぐ依存関係を CameraX 1.5 に更新して、魅力的な新機能をお試しください。皆様が構築されるマップ エクスペリエンスを楽しみにしております。

CameraX 1.5 を使用するには、libs.versions.toml に次の依存関係を追加してください。(1.5.1 には、多くの重要なバグの修正と、同時カメラの改善が含まれているため、1.5.1 を使用することをおすすめします)。

[versions]

camerax = "1.5.1"


[libraries]

..

androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "camerax" }

androidx-camera-compose = { module = "androidx.camera:camera-compose", version.ref = "camerax" }

androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "camerax" }

androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "camerax" }

androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camerax" }

androidx-camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "camerax" }

次に、これらをモジュールの build.gradle.kts 依存関係に追加します。

dependencies {

  ..

  implementation(libs.androidx.camera.core)
  implementation(libs.androidx.camera.lifecycle)

  implementation(libs.androidx.camera.camera2)

  implementation(libs.androidx.camera.view) // for PreviewView 
  implementation(libs.androidx.camera.compose) // for compose UI

  implementation(libs.androidx.camera.extensions) // For Extensions 

}

ご質問がある場合や、CameraX チームへの連絡をご希望の場合は、CameraX デベロッパー ヘルプグループに参加するか、バグレポートを提出してください。

作成者:
続きを読む