Jetpack Media3'teki Transformer API'leri, medya düzenlemeyi etkili ve güvenilir hale getirmek için tasarlanmıştır. Dönüştürücü, aşağıdakiler dahil bir dizi işlemi destekler:
- Kırpma, ölçekleme ve döndürme yoluyla videoyu değiştirme
- Yer paylaşımı ve filtre gibi efektler ekleme
- HDR ve ağır çekim video gibi özel biçimler işleniyor
- Düzenlemeleri uyguladıktan sonra medya öğesini dışa aktarma
Bu sayfada, Transformer'ın kapsadığı bazı temel kullanım alanları açıklanmaktadır. Daha fazla ayrıntı için Media3 Transformer ile ilgili tam rehberlerimize göz atabilirsiniz.
Başlayın
Başlamak için Jetpack Media3'ün Transformer, Effect ve Common modüllerine bağımlılık ekleyin:
implementation "androidx.media3:media3-transformer:1.3.1" implementation "androidx.media3:media3-effect:1.3.1" implementation "androidx.media3:media3-common:1.3.1"
1.3.1
öğesini, kitaplığın tercih ettiğiniz sürümüyle değiştirdiğinizden emin olun. En son sürümü görmek için sürüm notlarına bakabilirsiniz.
Önemli sınıflar
Sınıf | Amaç |
---|---|
Transformer |
Dönüştürme işlemlerini başlatıp durdurun ve çalışan bir dönüşümde ilerleme güncellemelerini kontrol edin. |
EditedMediaItem |
İşlenecek medya öğesini ve buna uygulanacak düzenlemeleri temsil eder. |
Effects |
Ses ve video efektleri koleksiyonu. |
Çıkışı yapılandırma
Transformer.Builder
sayesinde artık TransformationRequest
nesnesi oluşturmaya gerek kalmadan işlevi ayarlayarak videoMimeType
ve audioMimetype
dizinini belirtebilirsiniz.
Biçimler arasında kod dönüştürme
Aşağıdaki kodda, H.265/AVC video ve AAC ses çıkışına Transformer
nesnesinin nasıl yapılandırılacağı gösterilmektedir:
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();
Giriş medyası biçimi, ses veya video için dönüştürme isteğiyle zaten eşleşiyorsa Transformer, otomatik olarak transmuxing yöntemine geçer. Yani, sıkıştırılmış örnekleri giriş container'ından çıkış kapsayıcısına herhangi bir değişiklik yapmadan kopyalar. Böylece hem işlem maliyeti hem de kod çözme ve aynı biçimde yeniden kodlamada olası kalite kaybı önlenir.
HDR modunu ayarlama
Giriş medyası dosyası HDR biçimindeyse Transformer'ın HDR bilgilerini işleme şekli için birkaç farklı mod arasından seçim yapabilirsiniz. Büyük olasılıkla HDR_MODE_KEEP_HDR
veya HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL
kullanmak istersiniz.
HDR_MODE_KEEP_HDR |
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL |
|
---|---|---|
Açıklama | HDR verilerini koruyarak HDR çıkış biçimi, HDR giriş biçimiyle aynıdır. | HDR girişi, OpenGL ton eşleyici kullanarak SDR'ye ton eşlenir. Diğer bir deyişle, çıkış biçimi SDR olacaktır. |
Destek | FEATURE_HdrEditing özellikli bir kodlayıcıya sahip cihazlarda 31 ve üzeri API düzeylerinde desteklenir. |
29 ve üzeri API düzeylerinde desteklenir. |
Hatalar | Desteklenmiyorsa bunun yerine HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL kullanmayı deneyin. |
Desteklenmiyorsa bir ExportException hatası verir. |
Gerekli kodlama özelliklerini destekleyen ve Android 13 (API düzeyi 33) veya sonraki sürümleri çalıştıran cihazlarda Transformer
nesneleri HDR videoları düzenlemenize olanak tanır.
Aşağıdaki kodda gösterildiği gibi, Composition
nesnesini oluştururken HDR_MODE_KEEP_HDR
varsayılan moddur:
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();
Medya öğesi hazırlama
MediaItem
, uygulamanızdaki ses veya video öğesini temsil eder. EditedMediaItem
, uygulanacak dönüştürmelerle birlikte bir MediaItem
toplar.
Video kırpma
Bir videonun istenmeyen bölümlerini kaldırmak için MediaItem
öğesine ClippingConfiguration
ekleyerek özel başlangıç ve bitiş konumları ayarlayabilirsiniz.
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();
Yerleşik efektleri kullanma
Media3, yaygın dönüşümler için bir dizi yerleşik video efekti içerir. Örneğin:
Sınıf | Etki |
---|---|
Presentation |
Medya öğesini çözünürlüğe veya en boy oranına göre ölçeklendirin |
ScaleAndRotateTransformation |
Medya öğesini bir çarpana göre ölçeklendirin ve/veya medya öğesini döndürün |
Crop |
Medya öğesini daha küçük veya daha büyük bir kareye göre kırpın |
OverlayEffect |
Medya öğesinin üstüne metin veya resim yer paylaşımı ekleyin |
Ses efektleri için ham (PCM) ses verilerini dönüştürecek bir dizi AudioProcessor
örneği ekleyebilirsiniz. Örneğin, ses kanallarını karıştırmak ve ölçeklendirmek için ChannelMixingAudioProcessor
kullanabilirsiniz.
Bu efektleri kullanmak için efekt veya ses işlemcisinin bir örneğini oluşturun, medya öğesine uygulamak istediğiniz ses ve video efektleriyle Effects
öğesinin bir örneğini oluşturun, ardından Effects
nesnesini bir EditedMediaItem
öğesine ekleyin.
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();
Özel efektler oluşturun
Media3'teki efektleri genişleterek kullanım alanlarınıza özel özel efektler oluşturabilirsiniz. Aşağıdaki örnekte, oynatmanın ilk saniyesinde videoyu kareyi dolduracak şekilde yakınlaştırmak için MatrixTransformation
alt sınıfını kullanın:
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();
Bir efektin davranışını daha da özelleştirmek için GlShaderProgram
uygulayın. Giriş çerçevelerini işlemek için queueInputFrame()
yöntemi kullanılır. Örneğin, MediaPipe'in makine öğrenimi özelliklerinden yararlanmak için MediaPipe FrameProcessor
kullanarak her kareyi bir MediaPipe grafiği üzerinden gönderebilirsiniz. Bunun bir örneğini Transformer demo uygulamasında görebilirsiniz.
Efektleri önizle
ExoPlayer ile dışa aktarma işlemine başlamadan önce bir medya öğesine eklenen efektleri önizleyebilirsiniz. EditedMediaItem
için kullanılan Effects
nesnesini kullanarak ExoPlayer örneğinizde setVideoEffects()
yöntemini çağırın.
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();
Ses efektlerini ExoPlayer ile de önizleyebilirsiniz. ExoPlayer
örneğinizi oluştururken, oynatıcının ses oluşturucularını sizin AudioProcessor
dizinizi kullanan bir AudioSink
ses çıkışı sağlayacak şekilde yapılandıran bir özel RenderersFactory
aktarın. Aşağıdaki örnekte bunu DefaultRenderersFactory
öğesinin buildAudioSink()
yöntemini geçersiz kılarak yapıyoruz.
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();
Dönüşüm başlatma
Son olarak, düzenlemelerinizi uygulamak ve elde edilen medya öğesini dışa aktarmaya başlamak için bir Transformer
oluşturun.
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);
Benzer şekilde, gerekirse dışa aktarma işlemini Transformer.cancel()
ile iptal edebilirsiniz.
İlerleme güncellemelerini kontrol edin
Transformer.start
hemen geri döner ve eşzamansız olarak çalışır. Bir dönüşümün mevcut ilerleme durumunu sorgulamak için Transformer.getProgress()
çağrısı yapın.
Bu yöntemde ProgressHolder
gerekir. İlerleme durumu mevcutsa (yöntem PROGRESS_STATE_AVAILABLE
değerini döndürürse) sağlanan ProgressHolder
değeri, mevcut ilerleme yüzdesiyle güncellenir.
Ayrıca, tamamlama veya hata etkinlikleri hakkında bildirim almak için Transformer
cihazınıza bir dinleyici de ekleyebilirsiniz.