プロダクト ニュース

単一の機能を超えて: CameraX 1.5 で機能の組み合わせを保証する

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

最新のカメラアプリは、強力で重複する機能によって定義されます。ユーザーは、美しい HDR で動画を録画し、60 FPS で滑らかな動きをキャプチャし、プレビューの手ぶれ補正でスムーズな映像を撮影することを期待しています。多くの場合、これらすべてを同時に行います。

開発者として、私たちは現実がもっと複雑であることを知っています。特定のデバイスが特定の組み合わせをサポートしていることを確認するにはどうすればよいですか?これまで、複数の機能を有効にすることは、多くの場合、ギャンブルでした。個々の機能のサポートを確認することはできますが、それらを組み合わせると、未定義の動作が発生したり、最悪の場合、カメラ セッションが失敗したりする可能性があります。この不確実性により、デベロッパーは保守的にならざるを得ず、対応するデバイスのユーザーが可能な限り最高の体験を利用できなくなります。

たとえば、HDR と 60 FPS の動画を同時に安定してサポートするプレミアム デバイスはごくわずかです。そのため、ほとんどのアプリでは、大半のスマートフォンでユーザー エクスペリエンスが低下するのを防ぐために、両方を同時に有効にしないようにしています。

この問題を解決するため、CameraX の Feature Group を導入します。これは、この推測を不要にするように設計された新しい API です。カメラを構成する前に、特定の機能の組み合わせがサポートされているかどうかをクエリできるようになりました。また、優先順位を CameraX に伝えるだけで、最もサポートされている組み合わせを有効にすることもできます。

CameraX を初めて使用する方へ

新しい Feature Group API について詳しく説明する前に、CameraX の概要を簡単に説明します。CameraX は、カメラアプリの開発を容易にすることを目的とした Jetpack サポート ライブラリです。ほとんどの Android デバイスで機能する、使いやすく一貫性のある API サーフェスを提供するほか、Android 6.0(API レベル 23)への下位互換性も備えています。CameraX を初めて使用する場合は、公式ドキュメントを確認し、Codelab を試して始めることをおすすめします。

Feature Group API で構築できるもの

機能の組み合わせを試す必要がなくなり、組み合わせをサポートできないデバイスでエラーを回避しながら、対応するハードウェア(Google Pixel 10 Pro など)で HDR と 60 FPS の動画を同時に撮影するなど、可能な限り最高のカメラ エクスペリエンスを自信を持って提供できます。

unnamed.png

HDR と 60 FPS の両方を同時に有効にしている Google Pixel 10 Pro

無題(1).png

HDR と 60 FPS を同時に実行できない古いデバイスでは、HDR のみが有効になり、60 FPS オプションは無効になります。

Feature Group API を使用すると、次のことができます。

  • よりスマートで動的な UI を構築する: リアルタイムのハードウェア サポートに基づいて、UI の設定をインテリジェントに有効または無効にします。たとえば、ユーザーが HDR を有効にした場合、そのデバイスでその組み合わせがサポートされていなければ、60 FPS オプションをすぐにグレーアウトして無効にできます。 
unsupported-features-disabled.gif
  • 信頼性の高い「高画質」モードを提供: 優先順位付きの希望する機能のリストでカメラを構成します。CameraX は、特定のデバイスに最適な組み合わせを自動的に検出して有効にし、複雑なデバイス固有のロジックなしで優れた結果を保証します。
  • カメラ セッションの失敗を防ぐ: サポートを事前に確認することで、カメラがサポートされていない組み合わせを構成しようとするのを防ぎ、クラッシュの一般的な原因を排除して、スムーズなユーザー エクスペリエンスを提供します。

仕組み: コア コンポーネント

新しい API は、SessionConfigCameraInfo へのキー追加を中心に構成されています。

  1. GroupableFeature: この API は、HDR_HLG10FPS_60PREVIEW_STABILIZATIONIMAGE_ULTRA_HDR などの、グループ化可能な一連の事前定義された機能を導入します。計算上の制約により、この API が提供する信頼性の高いグループ化が可能なのは、特定の一連の機能のみです。YouTube では、このリストの拡大に積極的に取り組んでおり、今後のリリースでより多くの機能のサポートを導入する予定です。
     
  2. 新しい SessionConfig パラメータ: カメラ セッションの開始に使用されるこのクラスで、2 つの新しいパラメータが使用できるようになりました。
    • requiredFeatureGroup: 構成を成功させるためにサポートが必須となる機能に使用します。ユーザーが明示的に有効にする機能(「HDR」スイッチの切り替えなど)に最適です。決定論的で一貫したエクスペリエンスを確保するため、リクエストされた組み合わせが対象外の場合、bindToLifecycle 呼び出しは機能リクエストを無視するのではなく、IllegalArgumentException をスローします。この結果を事前にクエリするには、CameraInfo#isFeatureGroupSupported API(詳細は下記)を使用する必要があります。
    • preferredFeatureGroup: 望ましいがオプションの機能に使用します。たとえば、デフォルトの「高画質」モードを実装する場合などです。必要な機能のリストを優先順位に従って並べた状態で指定すると、デバイスがサポートする最も優先度の高い組み合わせが CameraX によって自動的に有効になります。
  3. CameraInfo#isFeatureGroupSupported(): これは、機能グループがサポートされているかどうかを明示的に確認するためのコアクエリ メソッドです。アプリの UI でサポートされている機能オプションのみをユーザーに提供するのに適しています。SessionConfig を渡すと、その組み合わせがサポートされているかどうかを示すブール値が返されます。必要な機能を持つ SessionConfig をバインドする場合は、まずこの API を使用して、その機能がサポートされていることを確認する必要があります。 

実装の実際

これらのコンポーネントを使用して、カメラ エクスペリエンスを向上させる方法を見てみましょう。

シナリオ 1: 「ベスト エフォート」高品質モード

可能な限り最適な機能をデフォルトで有効にするには、優先順位付きのリストを preferredFeatureGroup に渡します。この例では、CameraX に HDR、60 FPS、プレビューの手ぶれ補正の順に優先するよう指示しています。CameraX は、考えられるすべての組み合わせをチェックし、デバイスがサポートする最適な組み合わせを選択する複雑な処理を行います。

たとえば、デバイスが HDR と 60 FPS を同時に処理できるが、プレビュー安定化は処理できない場合、CameraX は最初の 2 つを有効にして、3 つ目を破棄します。これにより、複雑なデバイス固有のチェックを記述することなく、可能な限り最高のユーザー エクスペリエンスを実現できます。

cameraProvider.bindToLifecycle(

    lifecycleOwner,

    cameraSelector,

    SessionConfig(

        useCases = listOf(preview, videoCapture),

        // The order of features in this list determines their priority. 

        // CameraX will enable the best-supported combination based on these

        // priorities: HDR_HLG10 > FPS_60 > Preview Stabilization.  

        preferredFeatureGroup =

           listOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION),

    ).apply {

        // (Optional) Get a callback with the enabled features

        // to update your UI. 

        setFeatureSelectionListener { selectedFeatures ->

            updateUiIndicators(selectedFeatures)

        }

    }

)

このコード スニペットでは、CameraX は次の優先順位で機能の組み合わせを有効にしようとし、デバイスが完全にサポートする最初の組み合わせを選択します。

  1. HDR + 60 FPS + プレビューの手ぶれ補正
  2. HDR + 60 FPS
  3. HDR + プレビューの手ぶれ補正
  4. HDR
  5. 60 FPS + プレビューの手ぶれ補正
  6. 60 FPS
  7. プレビューの手ぶれ補正
  8. 上記の機能以外

シナリオ 2: リアクティブ UI を構築する

ユーザーの選択に応答し、サポートされていない機能の組み合わせをユーザーが選択できないようにする UI を作成するには、サポートを直接クエリします。次の関数は、ユーザーの現在の選択と互換性のない機能をチェックし、対応する UI 要素を無効にできるようにします。

/**

 * Returns a list of features that are NOT supported in combination

 * with the currently selected features.

 */

fun getUnsupportedFeatures(

    currentFeatures: Set<GroupableFeature>

): Set<GroupableFeature> {

    val unsupportedFeatures = mutableSetOf<GroupableFeature>()

    val appFeatureOptions = setOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION)


    // Iterate over every available feature option in your app. 

    appFeatureOptions.forEach { featureOption ->

        // Skip features the user has already selected. 

        if (currentFeatures.contains(featureOption)) return@forEach


        // Check if adding this new feature is supported. 

        val isSupported = cameraInfo.isFeatureGroupSupported(

            SessionConfig(

                useCases = useCases,

                // Check the new feature on top of existing ones.

                requiredFeatureGroup = currentFeatures + featureOption

            )

        )


        if (!isSupported) {

            unsupportedFeatures.add(featureOption)

        }

    }


    return unsupportedFeatures

}

このロジックを ViewModel または UI コントローラに接続して、ユーザー入力に応答し、動作が保証された構成でカメラを再バインドできます。

// Invoked when user turns some feature on/off.

fun onFeatureChange(currentFeatures: Set<GroupableFeature>) {

    // Identify features that are unsupported with the current selection.

    val unsupportedFeatures = getUnsupportedFeatures(currentFeatures)



    // Update app UI so that users can't enable them.

    updateDisabledFeatures(unsupportedFeatures)



    // Since the UI now only allows selecting supported feature combinations, 

    // `currentFeatures` is always valid. This allows setting

    // `requiredFeatureGroup` directly, without needing to re-check for

    // support or set a feature selection listener.  

    cameraProvider.bindToLifecycle(

        lifecycleOwner,

        cameraSelector,

        SessionConfig(

            useCases = listOf(preview, videoCapture),

            requiredFeatureGroup = currentFeatures,

        )

    )

}

これらのコンセプトを動作中のアプリで確認するには、Google の内部テストアプリをご覧ください。このアプリでは、上記の「ベスト エフォート」と「リアクティブ UI」の両方のシナリオが完全に実装されています。

注: これはテスト アプリケーションであり、公式にサポートされているサンプルではありません。Feature Group API の優れたリファレンスですが、本番環境での使用向けに調整されていません。

今すぐ始めましょう

Feature Group API を使用すると、高度なカメラ機能の操作の曖昧さが解消されます。機能サポートをクエリする決定論的な方法を提供することで、より強力で信頼性の高いカメラアプリを自信を持って構築できます。

この API は CameraX 1.5 で試験運用版として提供されており、1.6 リリースで完全に安定版となる予定です。今後もサポートと改善が予定されています。

詳細については、公式ドキュメントをご覧ください。皆様の作品を楽しみにしています。また、フィードバックもお待ちしております。ご意見、ご要望、問題の報告は、次の方法でお送りいただけます。

作成者:

続きを読む