Transkodowanie między formatami
Podczas tworzenia transformatora możesz określić wyjściowe formaty audio i wideo, które chcesz uzyskać. Na przykład poniższy kod pokazuje, jak skonfigurować Transformer, aby generował wideo w formacie H.264/AVC i dźwięk w formacie AAC:
Kotlin
Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H264) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build()
Java
new Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H264) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build();
Jeśli format wejściowego pliku multimedialnego jest zgodny z konfiguracjami audio 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 związanej z dekodowaniem i ponownym kodowaniem w tym samym formacie.
Usuwanie dźwięku lub obrazu
Usuń dźwięk lub obraz za pomocą ikony EditedMediaItem.Builder
, na przykład:
Kotlin
EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()
Java
new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();
Przycinanie klipu
Możesz usunąć wszystkie multimedia poza określonymi znacznikami czasu rozpoczęcia i zakończenia, ustawiając konfigurację przycinania w wejściowym elemencie multimedialnym. Aby na przykład utworzyć klip zawierający tylko multimedia między 10 a 20 sekundą:
Kotlin
val inputMediaItem = MediaItem.Builder() .setUri(uri) .setClippingConfiguration( ClippingConfiguration.Builder() .setStartPositionMs(10_000) .setEndPositionMs(20_000) .build()) .build()
Java
MediaItem inputMediaItem = new MediaItem.Builder() .setUri(uri) .setClippingConfiguration( new MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(10_000) .setEndPositionMs(20_000) .build()) .build();
Optymalizacja wersji
Aby skrócić czas oczekiwania na przycięcie początku filmu, włącz optymalizację przycinania.
Kotlin
Transformer.Builder(context) .experimentalSetTrimOptimizationEnabled(true) .build()
Java
new Transformer.Builder(context) .experimentalSetTrimOptimizationEnabled(true) .build();
Przyspiesza to eksportowanie, ponieważ dekodowanie i ponowne kodowanie jest ograniczone do minimum, a następnie ponownie zakodowane dane są łączone z resztą oryginalnego filmu. Optymalizacja polega na możliwości połączenia części pliku wejściowego z nowo zakodowanymi danymi wyjściowymi, co oznacza, że format wyjściowy kodera i format wejściowy muszą być zgodne. Jeśli na przykład plik został pierwotnie utworzony na urządzeniu z inną implementacją kodera, prawdopodobnie nie będzie można zastosować optymalizacji.
Aby optymalizacja się powiodła, koder przekazany do modelu Transformer za pomocą parametru EncoderFactory
musi mieć poziom i profil zgodne z formatem wejściowym.
Ta optymalizacja działa tylko w przypadku danych wejściowych MP4 z jednym zasobem bez efektów, z wyjątkiem efektów wideo „bez operacji” i obrotów podzielnych przez 90 stopni. Jeśli optymalizacja się nie powiedzie, Transformer automatycznie powróci do normalnego eksportu i zwróci wynik optymalizacji w ExportResult.OptimizationResult
.
Sprawdzamy tę funkcję i spodziewamy się, że w przyszłej wersji przestanie być eksperymentalna.
Edycje filmów
EditedMediaItems
zawierają listy procesorów audio i efektów wideo, które można stosować w określonej kolejności; Biblioteka zawiera implementacje efektów wideo w przypadku typowych zastosowań. Możesz też napisać własne efekty i przekazać je podczas tworzenia edytowanych elementów multimedialnych.
Możesz zmienić skalę multimediów, co może być przydatne, aby zaoszczędzić zasoby przetwarzania lub przepustowość podczas pracy z danymi wejściowymi o bardzo wysokiej rozdzielczości, takimi jak filmy w rozdzielczości 4K lub 8K. Aby na przykład proporcjonalnie przeskalować obraz do wysokości 480 pikseli:
Kotlin
EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf(Presentation.createForHeight(480)) )).build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of(Presentation.createForHeight(480)))) .build();
Możesz też skalować według danego współczynnika, np. aby zmniejszyć rozmiar o połowę:
Kotlin
val editedMediaItem = EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf( ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build()) )).build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of( new ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build()))) .build();
Rotację możesz skonfigurować w ten sam sposób:
Kotlin
EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf( ScaleAndRotateTransformation.Builder() .setRotationDegrees(90f) .build()) )).build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of( new ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build()))) .build();
Niestandardowe efekty wideo
Konstruktor Effects
akceptuje listę efektów audio i wideo do zastosowania.
Wewnętrznie framework efektów Transformer przekształca listę efektów wideo w sekwencję programów cieniowania GL, które są stosowane w odpowiedniej kolejności. W niektórych przypadkach framework efektów może zastosować wiele efektów za pomocą jednego programu cieniowania.
Na przykład jeden program cieniujący może stosować wiele kolejnych przekształceń macierzowych, co zwiększa wydajność i jakość.
Efekty wideo są też obsługiwane w podglądzie w ExoPlayerze za pomocą ExoPlayer.setVideoEffects
. Przykład użycia tego interfejsu API znajdziesz w aplikacji demonstracyjnej efektu.
Aplikacja demonstracyjna zawiera przykłady niestandardowych efektów wideo.
Edycje audio
Efekty audio są implementowane przez zastosowanie sekwencji instancji AudioProcessor
do surowego dźwięku (PCM). ExoPlayer obsługuje przekazywanie procesorów dźwięku do
DefaultAudioSink.Builder
, co umożliwia podgląd zmian w dźwięku.