多くの人が Android デバイスを使って動画を共有しています。受信した動画の品質は、共有アプリによって処理されるため、元の動画より劣ることがよくあります。このドキュメントでは、共有動画の品質を最適化する方法と、回避すべき一般的な動画処理の問題について説明します。HDR 動画コンテンツの共有を最適化するには、このページの Transformer モジュールを使用して HDR を SDR にコード変換するをご覧ください。
動画を共有する準備を行う際には、解像度を一定に保ち、動画の品質をできるだけ高く維持することが重要です。
共有パイプライン
図 1 は、動画共有の典型的なフローを示しています。
このパイプラインには以下のステップが含まれています。
- 動画をキャプチャしてエンコードします。キャプチャ中にエフェクトを追加できます。または、ユーザーがこの手順をスキップして、別のアプリから事前に録画されたストレージから動画を選択することもできます。
- 動画の編集、フィルタ、レタッチなどの処理を行う。
- コード変換に備えて、動画の拡大縮小やサイズ変更を行います。
- 動画をコード変換して共有します。多くの場合、手順 2 のフィルタリングはこの手順の一環として適用されます。
このパイプラインには 2 つのステップがあり、動画の品質を決定するパラメータを設定できます。初期録画中のエンコードと、共有前のコード変換です。また、コード変換の最終ステップの前に動画のサイズ変更が必要になることもあります。それも品質に影響を与える可能性があります。
推奨事項
表 1 に、動画品質の 5 つの主要なパラメータと、これらのパラメータを使用する手順を示します。
パラメータ | キャプチャ | 共有 |
プロファイル | Y | Y |
解像度 | Y | Y |
ビットレート | Y | Y |
量子化パラメータ(QP) | (まれに) | Y |
B フレーム | × | Y |
プロファイル
より良い結果を得るには、特定のコーデックで提供されているより高度なプロファイルを使用します。AVC エンコードには、高プロファイルとレベル 4 を選択します。
解像度、切り抜き、拡大縮小
共有用にコード変換する前に、スケーリング ステップでキャプチャした動画の初期解像度を変更できますが、スケーリングによって動画の品質が低下することがあります。スケーリングを回避し、パイプライン全体で使用できる最初のエンコードの解像度を選択することをおすすめします。また、特に切り抜かれた画像をアップスケールすると、極端に切り抜くと画質が低下することに注意してください。次のガイドラインに沿って対応してください。
- 最終的な共有解像度以上の解像度を選択します。
キャプチャ解像度は、すべての中間ステップがより大きな解像度をサポートするように設計されている場合を除きます(初期キャプチャ中の高いビットレートなど)。
- 共有エンコードの解像度が 720x1,280 の場合は、720x1,280 のキャプチャ解像度をおすすめします。
- キャプチャと共有の間の中間ステップに切り抜きが含まれている場合は、より高いキャプチャ解像度(1080x1920 など)を使用し、余分なピクセルを処理するためにキャプチャ ビットレートを上げます。
極端な切り抜きは、特に切り抜かれた画像が拡大される場合に、画像の品質が低下します。
低解像度から高解像度へのアップスケーリングは避けてください。アップスケーリングは存在しないディテールを生み出そうと試みます。最初から高い解像度で処理します。
アップスケールする必要がある場合は、エンコード パラメータを調整します。たとえば、解像度を上げた場合のピクセル数が 2 倍の場合は、ビットレートを 2 倍にします。
解像度とビットレートは相関しています。たとえば、最終的に低ビットレートにコード変換される共有パイプラインで高解像度の動画を伝送すると、低解像度から開始するよりも画質が低くなります。ビットレートが低下すると、解像度を下げると良い結果が得られるクロスオーバー ポイントが増えます。
ビットレート | 解像度 |
5 Mbps 以上 | 1080x1920 |
1.5 ~ 5 Mbps 以上 | 720x1280 |
1.5 Mbps 以下 | SD で同等。同じアスペクト比 9:16 のピクセルは約 416×736 です |
多くの人気アプリは、720p 以下の解像度で動画を共有します。このデータは、1.5 ~ 5 Mbps のビットレート ターゲットには 720p の解像度が適切な選択であることを示しています。
ビットレート
録音中
エンコード ビットレートが高いほど動画品質の改善は最も大きくなります。ネイティブのカメラアプリと一致するビットレートを選択することをおすすめします。解像度が 720x1280 の場合、キャプチャ ビットレートは 10 Mbps をおすすめします。
キャプチャ エンコードはデバイス上で行われるため、高いビットレートを使用することで、ほとんど悪影響を及ぼすことなく共有ステップの変換の大部分を補正できます。サイズの大きいファイルはデバイス上での操作にのみ使用されます。
表 2 に示すように、最終的なコード変換ステップでビットレートを下げることができます。
共有
ビットレートはアップロードされる動画のサイズに直接関係するため、共有時に最も影響が大きいです。動画の画質、ファイル送信時間、クラウド ストレージのコストはトレードオフの関係にあります。
この段階では、キャプチャ時よりもエンコード プロファイル、B フレーム、QP 境界値の選択も重要です。
良好な映像品質を確保するために、4 ~ 5 Mbps(解像度 720x1280 の場合)のビットレートをおすすめします。
量子化パラメータ(QP)
Android 12 以降では、QP キーが標準化されており、MediaFormat
API と NDK メディア ライブラリで使用できます。以前の Android バージョンでは、QP 操作は MediaFormat
構成でベンダー固有のキーを使用するフレームワーク関数を通じてのみ利用可能でした。
録音中
動画のキャプチャ中は、常に利用できるとは限らない QP 設定ではなく、ビットレート コントロールを使用します。
キャプチャ ビットレート(720x1280 の場合)が 10 Mbps の場合、QP 設定を調整することはおすすめしません。キャプチャ ビットレートが大幅に低い場合(720x1280 では 5 Mbps 未満)、QP 設定を 40 に設定すると、コーデックがターゲット ビットレートを過度に頻繁にオーバーシュートさせることなく、品質を向上できます。
共有
特にビットレートが 4 Mbps 未満の場合は、最大 QP 境界を 40 にすることをおすすめします。これにより、エンコードされた動画の品質は最小限に抑えられますが、より高いビットレートの結果が生成される可能性があります。ビットレートの増加は動画の複雑さによって異なります共有アプリは、生成された動画のビットレートの多少のばらつきは許容できる場合もありますが、特定のしきい値を超える増加は許容しないこともあります。
ビットレートの増加を制限するには、制限の少ない(高い)最大 QP 境界を使用して共有用に動画を再エンコードします。これにより、コーデックが品質を犠牲にして動画の他の部分を保持しやすくなります。これはコード変換処理であるため、共有する動画はすでにキャプチャされているため、動画を再エンコードして共有できます。
欠点は、これらの異なるパラメータでコード変換ステップを繰り返すと、動画の共有に時間がかかることです。このレイテンシを短縮する方法の 1 つは、部分的にコード変換された動画を調べて、ビットレートの超過を許容できる範囲を超えているかどうかを判断することです。そうでない場合は、コード変換を停止し、より適切な QP パラメータで再試行できます。
B フレームとエンコード プロファイル
B フレームは、Android 10 以降を実行している場合にのみ、共有ステップで使用することを検討します。
すべてのデバイスがメイン プロファイルまたはハイ プロファイルをサポートしているとは限らないため、アプリは CodecCapabilities
を使用して、サポートされているエンコード プロファイルをチェックする必要があります。AVC エンコーダでサポートされている最上位のプロファイル(High > Main > ベースライン)を使用します。最も安全な結果を得るには、ベースライン プロファイルを使用する場合は、B フレーム(KEY_LATENCY
または KEY_MAX_B_FRAMES
)を構成しないでください。エンコーダによっては、構成が失敗する場合があります。
次のコード セグメントでは、AVC エンコーダの構成に使用される 'MediaFormat format'
を前提としています。
Android 10
API 29 以降
サポートされている最も高いプロファイルを使用し、B フレーム パラメータを 1 に設定します。
format.setInt32(KEY_PROFILE, AVCProfileHigh);
format.setInt32(KEY_MAX_B_FRAMES, 1);
この場合、KEY_LATENCY
を設定しないでください。
Android 8、8.1、9
API 26、27、28
サポートされる最高のプロファイルを使用するが、B フレームの生成を無効にする。これにより、これらのシステム バージョンの MediaMuxer
のいくつかの制限に対処できます。
format.setInt32(KEY_PROFILE, AVCProfileHigh);
format.setInt32(KEY_LATENCY, 1);
KEY_LATENCY
値はコーデックが B フレームを生成できないようにしますが、他のコーデック効率も利用します。
アプリで MediaMuxer
を使用して最終出力ファイルをアセンブルしない場合は、KEY_LATENCY
の値を 1 ではなく 2 に設定することで、B フレームを有効にできます。これにより、コーデックが B フレームを生成できるようになります。
Android 7.1 以前
API 25 以前
最も安全な結果を得るには、ベースライン プロファイルを使用します。
format.setInt32(KEY_PROFILE, AVCProfileBaseline);
バージョン 7 より前では、Android AOSP はベースライン プロファイルのみをサポートしています。ただし、OEM はベンダー固有のプロファイルを使用するなどして、一部のデバイスでメイン/ハイ プロファイルを有効にしている可能性があります。
アプリで MediaMuxer
を使用していない場合、メイン プロファイルまたはハイ プロファイルを使用できます(コーデックがサポートしている場合)。B フレームの数を制御するための公開フォーマット鍵はありません。
Transformer モジュールを使用して HDR を SDR にコード変換する
Android 13(API レベル 33)以降では、Jetpack Media3 の Transformer モジュールを使用して、HDR をサポートしていないアプリ、サービス、デバイスと HDR コンテンツを共有することをおすすめします。Transformer モジュールは、入力 HDR 動画ストリームを SDR にトーン マッピングし、その結果を MP4 として保存することで、細部や画像の明るさを損なうことなく正常に再生できるようにします。
注: Android 12(API レベル 32)から Android 7.0(API レベル 24)までのシステム バージョンをターゲットとするデバイスでは、Transformer モジュールの動作が異なります。デバイスが HDR をサポートしている場合、アプリはトーン マッピングなしでコンテンツを再生します。デバイスが HDR をサポートしていない場合は、HDR トーン マッピングがサポートされていないことを示すエラーがスローされます。
次のコードは、入力を SDR にトーン マッピングして入力形式(H.264/AVC など)に再エンコードする Transformer をセットアップしています。
Kotlin
val transformer = Transformer.Builder(context) .setTransformationRequest( TransformationRequest.Builder() .setHdrMode(TransformationRequest.HDR_MODE_TONE_MAP_HDR_TO_SDR) .build()) .addListener(/* ... */) .build()
Java
Transformer transformer = new Transformer.Builder(context) .setTransformationRequest( new TransformationRequest.Builder() .setHdrMode(TransformationRequest.HDR_MODE_TONE_MAP_HDR_TO_SDR) .build()) .addListener(/* ... */) .build();
トーン マッピング機能を試すには、Transformer デモアプリをご覧ください。
MediaCodec
を使用してトーン マッピングを設定することもできますが、実装はより複雑です。詳細については、MediaCodec
のリファレンス ドキュメントをご覧ください。