Transformacje

klipy, stosować efekty wideo i optymalizować eksportowanie. keywords_public: Media3, Transformer, transkodowanie, edycja wideo, przycinanie, przetwarzanie audio, multimedia na Androidzie

Transkodowanie między formatami

Podczas tworzenia transformatora możesz określić formaty wyjściowe audio i wideo, które chcesz uzyskać. Na przykład poniższy kod pokazuje, jak skonfigurować Transformer, aby generował wideo H.264/AVC i dźwięk 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, konfigurując przycinanie w przypadku wejściowego elementu multimedialnego. Aby na przykład utworzyć klip zawierający tylko multimedia między 10 a 20 sekundą:

Kotlin

val inputMediaItem =
  MediaItem.Builder()
    .setUri(uri)
    .setClippingConfiguration(
      MediaItem.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();

Listy edycji MP4

Aby przyspieszyć przycinanie, Transformer obsługuje listy edycji MP4, co pozwala na bardziej wydajne edycje „tylko przycinanie” bez pełnego przekodowywania wideo. Ta metoda wykorzystuje istniejące zakodowane próbki i „reklama przed filmem” na liście edycji, który instruuje odtwarzacz, aby rozpoczął odtwarzanie w określonym momencie, skutecznie pomijając niechciany początkowy segment.

Aby znacznie przyspieszyć edycję polegającą tylko na przycinaniu, wywołaj experimentalSetMp4EditListTrimEnabled(true).

Kotlin

Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build()

Java

new Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build();
Pamiętaj, że nie wszystkie odtwarzacze multimedialne obsługują pozycję „reklama przed filmem”. Oznacza to, że gdy taki odtwarzacz jest używany, odtwarzanie pliku rozpocznie się od samego początku zakodowanej próbki, niezależnie od informacji na liście zmian, które mogą określać inny punkt początkowy.

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ż dekoduje i ponownie koduje jak najmniejszą część filmu, a następnie łączy ponownie zakodowane dane z resztą oryginalnego filmu. Optymalizacja polega na możliwości połączenia części pliku wejściowego z nowo zakodowanym plikiem wyjściowym, 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.

Zmiany w filmach

EditedMediaItems zawierają listy procesorów dźwięku i efektów wideo, które należy zastosować w odpowiedniej 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ść w przypadku danych wejściowych o bardzo wysokiej rozdzielczości, takich 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 w wersji demonstracyjnej zawiera przykłady niestandardowych efektów wideo.

Obraz wejściowy

Transformer obsługuje dane wejściowe w postaci obrazów, traktując je jako statyczne klipy wideo. Aby skonfigurować obraz jako źródło sygnału, wykonaj te czynności:

  • Utwórz MediaItem za pomocą MediaItem.Builder. Określ czas wyświetlania obrazu w filmie wyjściowym, wywołując funkcję setImageDurationMs.

  • Utwórz element EditedMediaItem, który będzie zawierać element MediaItem. Określ docelową liczbę klatek na sekundę dla wygenerowanego strumienia wideo za pomocą EditedMediaItem.Builder#setFrameRate.

Przykład poniżej pokazuje, jak skonfigurować dane wejściowe obrazu, aby wygenerować 5-sekundowy film z częstotliwością 30 klatek na sekundę:

Kotlin

val imageMediaItem =
  MediaItem.Builder()
    .setUri(imageUri)
    .setImageDurationMs(5000) // 5 seconds
    .build()

val editedImageItem =
  EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build()

Java

MediaItem imageMediaItem =
    new MediaItem.Builder()
        .setUri(imageUri)
        .setImageDurationMs(5000) // 5 seconds
        .build();
new EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build();

Zmiany w dźwięku

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.