Transformer API di Jetpack Media3 dirancang agar pengeditan media berperforma dan dapat diandalkan. Transformer mendukung sejumlah operasi, termasuk:
- Mengubah video dengan pemangkasan, penskalaan, dan rotasi
- Menambahkan efek seperti overlay dan filter
- Memproses format khusus seperti HDR dan video gerak lambat
- Mengekspor item media setelah menerapkan pengeditan
Halaman ini memandu Anda untuk mempelajari beberapa kasus penggunaan utama yang dibahas oleh Transformer. Untuk mengetahui detail selengkapnya, Anda dapat membaca panduan lengkap kami tentang Media3 Transformer.
Memulai
Untuk memulai, tambahkan dependensi pada modul Transformer, Effect, dan Common di Jetpack Media3:
implementation "androidx.media3:media3-transformer:1.3.1" implementation "androidx.media3:media3-effect:1.3.1" implementation "androidx.media3:media3-common:1.3.1"
Pastikan untuk mengganti 1.3.1
dengan versi library
pilihan Anda. Anda dapat membaca catatan rilis untuk melihat versi terbaru.
Class penting
Class | Tujuan |
---|---|
Transformer |
Mulai dan hentikan transformasi serta periksa pembaruan progres pada transformasi yang sedang berjalan. |
EditedMediaItem |
Menampilkan item media yang akan diproses dan pengeditan yang akan diterapkan padanya. |
Effects |
Kumpulan efek audio dan video. |
Mengonfigurasi output
Dengan Transformer.Builder
, Anda kini dapat menentukan direktori videoMimeType
dan
audioMimetype
dengan menyetel fungsi tanpa perlu membuat
objek TransformationRequest
.
Melakukan transcoding antarformat
Kode berikut menunjukkan cara mengonfigurasi objek Transformer
untuk
menghasilkan video H.265/AVC dan audio 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();
Jika format media input sudah cocok dengan permintaan transformasi untuk audio atau video, Transformer akan otomatis beralih ke transmuxing, yaitu menyalin sampel yang dikompresi dari penampung input ke penampung output tanpa modifikasi. Hal ini menghindari biaya komputasi serta potensi hilangnya kualitas dari decoding dan encoding ulang dalam format yang sama.
Setel mode HDR
Jika file media input dalam format HDR, Anda dapat memilih di antara beberapa
mode berbeda terkait cara Transformer memproses informasi HDR. Anda mungkin
ingin menggunakan HDR_MODE_KEEP_HDR
atau
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL
.
HDR_MODE_KEEP_HDR |
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL |
|
---|---|---|
Deskripsi | Pertahankan data HDR. Artinya, format output HDR sama dengan format input HDR. | Tonemap HDR input ke SDR menggunakan tone-mapper OpenGL, yang berarti format outputnya akan dalam SDR. |
Dukungan | Didukung pada API level 31+ untuk perangkat yang menyertakan encoder dengan kemampuan FEATURE_HdrEditing . |
Didukung pada API level 29+. |
Error | Jika tidak didukung, coba gunakan HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL sebagai gantinya. |
Jika tidak didukung, tampilkan ExportException . |
Pada perangkat yang mendukung kemampuan encoding yang diperlukan dan menjalankan Android 13
(API level 33) atau yang lebih baru, objek Transformer
memungkinkan Anda mengedit video HDR.
HDR_MODE_KEEP_HDR
adalah mode default saat mem-build objek Composition
,
seperti yang ditunjukkan dalam kode berikut:
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();
Menyiapkan item media
MediaItem
merepresentasikan item audio
atau video di aplikasi Anda. EditedMediaItem
mengumpulkan MediaItem
beserta
transformasi untuk diterapkan padanya.
Memangkas video
Untuk menghapus bagian video yang tidak diinginkan, Anda dapat menetapkan posisi awal dan akhir kustom dengan menambahkan ClippingConfiguration
ke MediaItem
.
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();
Gunakan efek bawaan
Media3 menyertakan sejumlah efek video bawaan untuk transformasi umum, misalnya:
Class | Efek |
---|---|
Presentation |
Menskalakan item media berdasarkan resolusi atau rasio aspek |
ScaleAndRotateTransformation |
Menskalakan item media dengan pengganda dan/atau memutar item media |
Crop |
Memangkas item media ke bingkai yang lebih kecil atau lebih besar |
OverlayEffect |
Menambahkan overlay teks atau gambar di atas item media |
Untuk efek audio, Anda dapat menambahkan urutan
instance AudioProcessor
yang akan mengubah data audio mentah (PCM). Misalnya, Anda dapat menggunakan
ChannelMixingAudioProcessor
untuk mencampur dan menskalakan saluran audio.
Untuk menggunakan efek ini, buat instance efek atau pemroses audio, build
instance Effects
dengan efek audio dan video yang ingin Anda terapkan ke
item media, lalu tambahkan objek Effects
ke 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();
Membuat efek kustom
Dengan memperluas efek yang disertakan di Media3, Anda dapat membuat efek kustom
khusus untuk kasus penggunaan Anda. Pada contoh berikut, gunakan subclass
MatrixTransformation
untuk memperbesar video agar mengisi frame selama detik
pertama pemutaran:
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();
Untuk menyesuaikan perilaku efek lebih lanjut, terapkan
GlShaderProgram
. Metode
queueInputFrame()
digunakan untuk memproses frame input. Misalnya, untuk
memanfaatkan kemampuan machine learning
MediaPipe, Anda dapat menggunakan
MediaPipe FrameProcessor
untuk mengirim setiap frame melalui grafik MediaPipe. Lihat contohnya dalam
aplikasi demo Transformer.
Efek pratinjau
Dengan ExoPlayer, Anda dapat melihat pratinjau efek
yang ditambahkan ke item media sebelum memulai proses ekspor. Dengan menggunakan objek
Effects
yang sama seperti untuk EditedMediaItem
, panggil setVideoEffects()
pada
instance ExoPlayer Anda.
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();
Anda juga dapat melihat pratinjau efek audio dengan ExoPlayer. Saat mem-build
instance ExoPlayer
, teruskan RenderersFactory
kustom yang mengonfigurasi
perender audio pemutar untuk menghasilkan audio ke AudioSink
yang menggunakan
urutan AudioProcessor
. Pada contoh di bawah, kita melakukannya dengan mengganti metode buildAudioSink()
dari DefaultRenderersFactory
.
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();
Memulai transformasi
Terakhir, buat Transformer
untuk menerapkan pengeditan Anda dan mulai mengekspor
item media yang dihasilkan.
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);
Anda juga dapat membatalkan proses ekspor jika diperlukan dengan
Transformer.cancel()
.
Memeriksa pembaruan progres
Transformer.start
segera ditampilkan dan berjalan secara asinkron. Untuk membuat kueri
progres transformasi saat ini, panggil
Transformer.getProgress()
.
Metode ini memerlukan ProgressHolder
, dan jika status progres tersedia,
yaitu, jika metode menampilkan PROGRESS_STATE_AVAILABLE
, ProgressHolder
yang
disediakan akan diperbarui dengan persentase progres saat ini.
Anda juga dapat menambahkan pemroses ke Transformer
untuk menerima notifikasi tentang penyelesaian atau peristiwa error.