Media3 Transformer を使用して基本的な動画編集アプリを作成する

Jetpack Media3 の Transformer API は、メディア編集を可能にするように設計されています。 パフォーマンスと信頼性に優れていますTransformer は多くのオペレーション、 含まれます。

  • トリミング、スケーリング、回転による動画の変更
  • オーバーレイやフィルタなどの効果を追加する
  • HDR やスローモーション動画などの特殊な形式の処理
  • 編集を適用した後にメディア アイテムをエクスポートする

このページでは、このモジュールで取り上げる主なユースケースについて Transformer です。詳細については、このモジュールの Media3 Transformer

始める

まず、Transformer、Effect、Common モジュールに対する依存関係を追加します。 Jetpack Media3:

implementation "androidx.media3:media3-transformer:1.4.1"
implementation "androidx.media3:media3-effect:1.4.1"
implementation "androidx.media3:media3-common:1.4.1"

1.4.1 は、ご使用のバージョンに置き換えてください。 ライブラリです。詳しくは、 リリースノート 最新のバージョンを確認してください。

重要なクラス

クラス 目的
Transformer 変換を開始および停止し、実行中の変換の進行状況を確認します。
EditedMediaItem 処理するメディア アイテムとそれに適用する編集を表します。
Effects 音声エフェクトと動画エフェクトのコレクション。

出力を構成する

Transformer.Builder では、videoMimeTypeaudioMimetype ディレクトリの作成なしで関数を設定すれば、 TransformationRequest オブジェクト。

フォーマット間のコード変換

次のコードは、Transformer オブジェクトを H.265/AVC 動画と AAC オーディオを出力する機能:

Kotlin

val transformer = Transformer.Builder(context)
    .setVideoMimeType(MimeTypes.VIDEO_H265)
    .setAudioMimeType(MimeTypes.AUDIO_AAC)
    .build()

Java

Transformer transformer = new Transformer.Builder(context)
    .setVideoMimeType(MimeTypes.VIDEO_H265)
    .setAudioMimeType(MimeTypes.AUDIO_AAC)
    .build();

入力メディア形式が音声の変換リクエストとすでに一致している場合 Transformer は、Transmuxing(変換、 圧縮されたサンプルが入力コンテナから出力コンテナに あります。これにより、モデルの計算コストや品質の低下を 再エンコードを行います。

HDR モードを設定する

入力メディア ファイルが HDR 形式の場合、数種類から選択できます Transformer による HDR 情報の処理方法に関する複数のモードがあります。おそらく HDR_MODE_KEEP_HDR または HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL

HDR_MODE_KEEP_HDR HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL
説明 HDR データを保持します。つまり、HDR 出力形式は HDR 入力形式と同じです。 OpenGL トーンマッパーを使用して HDR 入力を SDR にトーンマッピングします。つまり、出力形式は SDR になります。
サポート FEATURE_HdrEditing 機能を備えたエンコーダを備えたデバイスの場合、API レベル 31 以降でサポートされています。 API レベル 29 以降でサポートされています。
エラー サポートされていない場合は、代わりに HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL を使用します。 サポートされていない場合は、ExportException がスローされます。

必要なエンコード機能をサポートし、Android 13 を搭載したデバイス (API レベル 33)以降では、Transformer オブジェクトを使用して HDR 動画を編集できます。 HDR_MODE_KEEP_HDR は、Composition オブジェクト構築時のデフォルト モードです。 コードのようになります。

Kotlin

val composition = Composition.Builder(
    ImmutableList.of(videoSequence))
    .setHdrMode(HDR_MODE_KEEP_HDR)
    .build()

Java

Composition composition = new Composition.Builder(
    ImmutableList.of(videoSequence))
    .setHdrMode(Composition.HDR_MODE_KEEP_HDR)
    .build();

メディア アイテムを準備する

MediaItem は音声を表す 追加できますEditedMediaItemMediaItem を収集します。 適用する変換が含まれます

動画をカットする

動画内の不要な部分を削除するには、カスタムの開始と終了を設定します MediaItemClippingConfiguration を追加することで、位置を変更できます。

Kotlin

val clippingConfiguration = MediaItem.ClippingConfiguration.Builder()
    .setStartPositionMs(10_000) // start at 10 seconds
    .setEndPositionMs(20_000) // end at 20 seconds
    .build()
val mediaItem = MediaItem.Builder()
    .setUri(videoUri)
    .setClippingConfiguration(clippingConfiguration)
    .build()

Java

ClippingConfiguration clippingConfiguration = new MediaItem.ClippingConfiguration.Builder()
    .setStartPositionMs(10_000) // start at 10 seconds
    .setEndPositionMs(20_000) // end at 20 seconds
    .build();
MediaItem mediaItem = new MediaItem.Builder()
    .setUri(videoUri)
    .setClippingConfiguration(clippingConfiguration)
    .build();

組み込みのエフェクトを使用する

Media3 には、一般的な変換、 次に例を示します。

クラス 効果
Presentation メディア アイテムを解像度またはアスペクト比で拡大縮小する
ScaleAndRotateTransformation メディア アイテムを乗数で拡大縮小するか、メディア アイテムをローテーションしてください
Crop メディア アイテムを小さなフレームまたは大きなフレームに切り抜く
OverlayEffect メディア アイテムの上にテキストまたはイメージ オーバーレイを追加する

オーディオ エフェクトの場合は、 AudioProcessor 未加工(PCM)音声データを変換する複数のインスタンスがあります。たとえば、 ChannelMixingAudioProcessor 音声チャンネルのミキシングやスケーリングを行えます。

これらのエフェクトを使用するには、そのエフェクトまたはオーディオ プロセッサのインスタンスを作成し、 適用する音声効果と動画効果を含む Effects のインスタンス 次に、Effects オブジェクトを EditedMediaItem に追加します。

Kotlin

val channelMixingProcessor = ChannelMixingAudioProcessor()
val rotateEffect = ScaleAndRotateTransformation.Builder().setRotationDegrees(60f).build()
val cropEffect = Crop(-0.5f, 0.5f, -0.5f, 0.5f)

val effects = Effects(listOf(channelMixingProcessor), listOf(rotateEffect, cropEffect))

val editedMediaItem = EditedMediaItem.Builder(mediaItem)
    .setEffects(effects)
    .build()

Java

ChannelMixingAudioProcessor channelMixingProcessor = new ChannelMixingAudioProcessor();
ScaleAndRotateTransformation rotateEffect = new ScaleAndRotateTransformation.Builder()
    .setRotationDegrees(60f)
    .build();
Crop cropEffect = new Crop(-0.5f, 0.5f, -0.5f, 0.5f);

Effects effects = new Effects(
    ImmutableList.of(channelMixingProcessor),
    ImmutableList.of(rotateEffect, cropEffect)
);

EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(mediaItem)
    .setEffects(effects)
    .build();

カスタム エフェクトを作成する

Media3 に含まれるエフェクトを拡張することで、カスタム エフェクトを作成できます。 固有のユースケースに適応できます次の例では、サブクラスを使用します。 MatrixTransformation: 動画を拡大して最初のフレーム内に収める :

Kotlin

val zoomEffect = MatrixTransformation { presentationTimeUs ->
    val transformationMatrix = Matrix()
    // Set the scaling factor based on the playback position
    val scale = min(1f, presentationTimeUs / 1_000f)
    transformationMatrix.postScale(/* x */ scale, /* y */ scale)
    transformationMatrix
}

val editedMediaItem = EditedMediaItem.Builder(inputMediaItem)
    .setEffects(Effects(listOf(), listOf(zoomEffect))
    .build()

Java

MatrixTransformation zoomEffect = presentationTimeUs -> {
    Matrix transformationMatrix = new Matrix();
    // Set the scaling factor based on the playback position
    float scale = min(1f, presentationTimeUs / 1_000f);
    transformationMatrix.postScale(/* x */ scale, /* y */ scale);
    return transformationMatrix;
};

EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(inputMediaItem)
    .setEffects(new Effects(ImmutableList.of(), ImmutableList.of(zoomEffect)))
    .build();

効果の動作をさらにカスタマイズするには、 GlShaderProgram。「 queueInputFrame() メソッドは入力フレームを処理するために使用されます。たとえば、 Google Cloud の ML 機能を MediaPipe では、 MediaPipe FrameProcessor MediaPipe グラフを介して各フレームを送信しますこの例を Transformer デモアプリ

効果をプレビュー

ExoPlayer を使用すると、効果をプレビューできます。 追加する必要があります。同じ Effects オブジェクトについては、EditedMediaItemsetVideoEffects() を呼び出して ExoPlayer インスタンス。

Kotlin

val player = ExoPlayer.builder(context)
    .build()
    .also { exoPlayer ->
        exoPlayer.setMediaItem(inputMediaItem)
        exoPlayer.setVideoEffects(effects)
        exoPlayer.prepare()
    }

Java

ExoPlayer player = new ExoPlayer.builder(context).build();
player.setMediaItem(inputMediaItem);
player.setVideoEffects(effects);
exoPlayer.prepare();

ExoPlayer でオーディオ エフェクトをプレビューすることもできます。カスタムモデルを構築する際は、 ExoPlayer インスタンスを設定するには、このインターフェースを構成するカスタムの RenderersFactory を のオーディオ レンダラを使用して、オーディオを AudioSink に出力します。 AudioProcessor シーケンス。以下の例では、 DefaultRenderersFactorybuildAudioSink() メソッド。

Kotlin

val player = ExoPlayer.Builder(context, object : DefaultRenderersFactory(context) {
    override fun buildAudioSink(
        context: Context,
        enableFloatOutput: Boolean,
        enableAudioTrackPlaybackParams: Boolean,
        enableOffload: Boolean
    ): AudioSink? {
        return DefaultAudioSink.Builder(context)
            .setEnableFloatOutput(enableFloatOutput)
            .setEnableAudioTrackPlaybackParams(enableAudioTrackPlaybackParams)
            .setOffloadMode(if (enableOffload) {
                     DefaultAudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED
                } else {
                    DefaultAudioSink.OFFLOAD_MODE_DISABLED
                })
            .setAudioProcessors(arrayOf(channelMixingProcessor))
            .build()
        }
    }).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context, new DefaultRenderersFactory(context) {
        @Nullable
        @Override
        protected AudioSink buildAudioSink(
            Context context,
            boolean enableFloatOutput,
            boolean enableAudioTrackPlaybackParams,
            boolean enableOffload
        ) {
            return new DefaultAudioSink.Builder(context)
                .setEnableFloatOutput(enableFloatOutput)
                .setEnableAudioTrackPlaybackParams(enableAudioTrackPlaybackParams)
                .setOffloadMode(
                    enableOffload
                        ? DefaultAudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED
                        : DefaultAudioSink.OFFLOAD_MODE_DISABLED)
                .setAudioProcessors(new AudioProcessor[]{channelMixingProcessor})
                .build();
        }
    }).build();

変換を開始する

最後に、Transformer を作成して編集内容を適用し、 結果として得られるメディア アイテムです。

Kotlin

val transformer = Transformer.Builder(context)
    .addListener(listener)
    .build()
transformer.start(editedMediaItem, outputPath)

Java

Transformer transformer = new Transformer.Builder(context)
    .addListener(listener)
    .build();
transformer.start(editedMediaItem, outputPath);

エクスポート プロセスも、必要に応じてキャンセルできます。 Transformer.cancel()

進行状況の更新を確認する

Transformer.start はすぐに返され、非同期で実行されます。クエリを行うために、 現在の変革の進捗状況、 Transformer.getProgress()。 このメソッドは ProgressHolder を受け取り、進行状況が利用可能な場合、 つまり、メソッドが PROGRESS_STATE_AVAILABLE を返した場合、指定された ProgressHolder は現在の進行状況の割合で更新されます。

また、 リスナー Transformer に送信して、完了またはエラーイベントに関する通知を受け取ります。