Interfejsy Transformer API w Jetpack Media3 zostały zaprojektowane do edycji multimediów wydajną i niezawodną. Transformer obsługuje wiele operacji, w tym:
- Modyfikowanie filmu za pomocą przycinania, skalowania i obracania
- dodawanie efektów, takich jak nakładki i filtry;
- Przetwarzanie specjalnych formatów, takich jak HDR i filmy w zwolnionym tempie
- Eksportowanie elementu multimedialnego po zastosowaniu zmian
Na tej stronie omawiamy wybrane kluczowe przypadki użycia Transformer. Więcej informacji znajdziesz w pełnych przewodnikach: Media3 Transformer.
Rozpocznij
Aby rozpocząć, dodaj zależność do modułów Transformer, Efekt i Powszechne 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"
Zastąp 1.4.1
preferowaną wersją
bibliotece. Możesz zapoznać się z
informacje o wersji
aby zobaczyć najnowszą wersję.
Ważne zajęcia
Kategoria | Cel |
---|---|
Transformer |
Rozpoczynaj i zatrzymuj przekształcenia oraz sprawdzaj aktualizacje trwającej przekształcenia. |
EditedMediaItem |
Reprezentuje element multimedialny do przetworzenia i zmiany, które mają zostać do niego zastosowane. |
Effects |
Kolekcja efektów audio i wideo. |
Skonfiguruj dane wyjściowe
Korzystając z Transformer.Builder
, możesz teraz określić videoMimeType
i
audioMimetype
przez ustawienie funkcji bez konieczności tworzenia
TransformationRequest
obiekt.
Transkoduj między formatami
Ten kod pokazuje, jak skonfigurować obiekt Transformer
wyjście wideo H.265/AVC i dźwięk w formacie 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();
Jeśli format nośnika wejściowego jest już zgodny z żądaniem przekształcenia dźwięku lub wideo, Transformer automatycznie przełącza się na transmuksowanie, czyli kopiowanie skompresowanych próbek z kontenera wejściowego do kontenera wyjściowego bez modyfikacji. Pozwala to uniknąć kosztów obliczeniowych i potencjalnej utraty jakości na dekodowaniu i ponownym kodowaniu w tym samym formacie.
Ustaw tryb HDR
Jeśli wejściowy plik multimedialny jest w formacie HDR, możesz wybrać jedną z tych opcji:
w różnych trybach przetwarzania informacji HDR przez Transformer. Prawdopodobnie
chcesz użyć funkcji HDR_MODE_KEEP_HDR
lub
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL
HDR_MODE_KEEP_HDR |
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL |
|
---|---|---|
Opis | Zachowaj dane HDR, co oznacza, że format wyjściowy jest taki sam jak format wyjściowy HDR. | Zmapowanie tonalnego obrazu HDR do SDR za pomocą mapera tonów OpenGL – oznacza to, że format wyjściowy będzie zapisany w SDR. |
Pomoc | Obsługiwane na poziomach API 31 i nowszych w przypadku urządzeń z koderem z obsługą FEATURE_HdrEditing . |
Obsługiwane na poziomach API 29 i nowszych. |
Błędy | Jeśli ta funkcja nie jest obsługiwana, spróbuj użyć interfejsu HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL . |
Jeśli nie jest obsługiwany, wysyła ExportException . |
Na urządzeniach, które obsługują wymagane funkcje kodowania i mają Androida 13
(poziom interfejsu API 33) lub wyższy, obiekty Transformer
umożliwiają edytowanie filmów HDR.
Domyślnym trybem podczas tworzenia obiektu Composition
jest HDR_MODE_KEEP_HDR
.
jak w tym kodzie:
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();
Przygotowywanie elementu multimedialnego
MediaItem
oznacza plik audio.
lub element wideo w aplikacji. EditedMediaItem
zbiera: MediaItem
z przekształceniami, które mają do niego zastosowanie.
Przycinanie filmu
Aby usunąć niechciane fragmenty filmu, możesz ustawić niestandardowy początek i koniec filmu
pozycji, dodając ClippingConfiguration
do 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();
Korzystanie z wbudowanych efektów
Media3 zawiera wiele wbudowanych efektów wideo przydatnych przy typowych przekształceniach, np.:
Kategoria | Efekt |
---|---|
Presentation |
Skaluj element multimedialny według rozdzielczości lub formatu obrazu |
ScaleAndRotateTransformation |
Skaluj element multimedialny o mnożnik lub obróć element multimedialny |
Crop |
Przytnij element multimedialny do mniejszej lub większej klatki |
OverlayEffect |
Dodaj nakładkę z tekstem lub obrazem na element multimedialny. |
Do efektów dźwiękowych możesz dodać sekwencję
AudioProcessor
które przekształcą nieprzetworzone dane dźwiękowe (PCM). Na przykład możesz użyć
ChannelMixingAudioProcessor
do miksowania i skalowania kanałów audio.
Aby użyć tych efektów, utwórz instancję efektu lub procesora dźwięku, utwórz
wystąpienie elementu Effects
z efektami audio i wideo, które chcesz zastosować
wybierz element multimedialny, a potem dodaj do obiektu EditedMediaItem
obiekt Effects
.
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();
Tworzenie efektów niestandardowych
Rozszerzając efekty dostępne w Media3, możesz tworzyć efekty niestandardowe
do swoich potrzeb. W poniższym przykładzie użyj podklasy
MatrixTransformation
, aby powiększyć film i zapełnić klatkę nad pierwszą
sekunda odtwarzania:
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();
Aby jeszcze bardziej dostosować działanie efektu, zaimplementuj funkcję
GlShaderProgram
Metoda queueInputFrame()
jest używana do przetwarzania ramek wejściowych. Aby na przykład:
wykorzystują systemy uczące się
MediaPipe, możesz użyć parametru
MediaPipe FrameProcessor
;
aby wysłać każdą klatkę za pomocą grafu MediaPipe. Zobacz przykład w
Aplikacja demonstracyjna Transformer.
Podgląd efektów
ExoPlayer pozwala podglądać efekty
dodany do elementu multimedialnego przed rozpoczęciem procesu eksportowania. Używanie tego samego
Effects
obiekt jak w przypadku EditedMediaItem
, wywołaj setVideoEffects()
na
instancji 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();
Możesz też przetestować efekty dźwiękowe w narzędziu ExoPlayer. Podczas tworzenia
ExoPlayer
, przekaż niestandardowe źródło RenderersFactory
, które konfiguruje
mechanizm renderowania dźwięku w odtwarzaczu do wersji AudioSink
, która używa Twojego
Sekwencja AudioProcessor
. W przykładzie poniżej robimy to, zastępując
Metoda buildAudioSink()
dla 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();
Rozpocznij przekształcanie
Na koniec utwórz plik Transformer
, aby zastosować zmiany, i zacznij eksportować
utworzony element multimedialny.
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);
W razie potrzeby możesz w podobny sposób anulować proces eksportowania, używając
Transformer.cancel()
Sprawdzanie aktualnych informacji o postępach
Funkcja Transformer.start
wraca natychmiast i działa asynchronicznie. Aby wysłać zapytanie
obecny postęp przekształcenia, wywołanie
Transformer.getProgress()
Ta metoda wymaga ProgressHolder
, a jeśli stan postępu jest dostępny,
oznacza to, że jeśli metoda zwraca PROGRESS_STATE_AVAILABLE
, podana wartość
Aplikacja ProgressHolder
zostanie zaktualizowana o aktualny odsetek postępu.
Możesz też dołączyć
listener
do: Transformer
, aby otrzymywać powiadomienia o zdarzeniach zakończenia lub błędach.