Начало работы

Чтобы начать работу с Transformer, выполните следующие действия:

  1. Добавьте Media3 Transformer в качестве зависимости в проект.
  2. Создайте объект EditedMediaItem, представляющий медиафайл, который нужно обработать, и изменения, которые нужно к нему применить.
  3. Создайте объект Transformer, описывающий требуемые выходные данные и прослушиватель для событий завершения и ошибок.
  4. Запустите операцию экспорта, передав EditedMediaItem для редактирования и путь к выходному файлу. Во время экспорта вы можете запросить текущий прогресс или отменить операцию.
  5. После завершения экспорта обработайте выходные данные нужным образом. Например, вы можете поделиться результатом в другом приложении или загрузить его на сервер.

Ниже приведены подробные сведения об этих шагах, а в демоприложении Transformer вы найдете полный пример с использованием TransformerActivity.

Добавьте Media3 Transformer в качестве зависимости

Самый простой способ начать работу с Transformer – добавить зависимости gradle в библиотеку в файле build.gradle модуля приложения:

Kotlin

implementation("androidx.media3:media3-transformer:1.11.1")
implementation("androidx.media3:media3-effect:1.11.1")
implementation("androidx.media3:media3-common:1.11.1")

Яркий

implementation "androidx.media3:media3-transformer:1.11.1"
implementation "androidx.media3:media3-effect:1.11.1"
implementation "androidx.media3:media3-common:1.11.1"

где 1.11.1 – нужная вам версия. Последнюю версию можно найти в примечаниях к выпуску.

Дополнительную информацию о доступных модулях библиотеки можно найти на странице Google Maven AndroidX Media3.

Включить поддержку Java 8

Если поддержка Java 8 ещё не включена, ее нужно включить во всех файлах build.gradle, которые зависят от Transformer. Для этого добавьте в раздел android следующий код:

compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}

Как начать преобразование

Ниже приведен пример создания EditedMediaItem для удаления аудио из входного файла, а затем создания и настройки экземпляра Transformer для экспорта видео H.265/HEVC с выводом результата в outputPath.

Kotlin

val inputMediaItem = MediaItem.fromUri("path_to_input_file")
val editedMediaItem = EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()
val transformer =
  Transformer.Builder(context)
    .setVideoMimeType(MimeTypes.VIDEO_H265)
    .addListener(transformerListener)
    .build()
transformer.start(editedMediaItem, outputPath)

Java

MediaItem inputMediaItem = MediaItem.fromUri("path_to_input_file");
EditedMediaItem editedMediaItem =
    new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();
Transformer transformer =
    new Transformer.Builder(context)
        .setVideoMimeType(MimeTypes.VIDEO_H265)
        .addListener(transformerListener)
        .build();
transformer.start(editedMediaItem, outputPath);

Дополнительную информацию о мультимедийных объектах можно найти на странице ExoPlayer. Входной поток может быть прогрессивным или адаптивным, но выходной поток всегда прогрессивный. Для адаптивных входных данных всегда выбираются дорожки с самым высоким разрешением. Входные данные могут быть в любом формате контейнера, поддерживаемом ExoPlayer, но выходные данные всегда будут в формате MP4.

Вы можете последовательно выполнять несколько операций экспорта в одном экземпляре Transformer, но одновременный экспорт в одном экземпляре не поддерживается.

Подробнее о создании генеративных медиа на основе нескольких входных данных…

Примечание о цепочках писем

Доступ к экземплярам Transformer должен осуществляться из одного потока приложения, а методы прослушивателя вызываются в том же потоке. В большинстве случаев в качестве потока приложения можно использовать основной поток. Transformer работает в фоновом режиме и отправляет вызовы методам прослушивателя в потоке приложения.

Как отслеживать события

Метод start является асинхронным. Он возвращает результат немедленно, а приложение получает уведомления о событиях через прослушиватель, переданный в конструктор Transformer.

Kotlin

val transformerListener: Transformer.Listener =
  object : Transformer.Listener {
    override fun onCompleted(composition: Composition, result: ExportResult) {
      playOutput()
    }

    override fun onError(
      composition: Composition,
      result: ExportResult,
      exception: ExportException,
    ) {
      displayError(exception)
    }
  }

Java

Transformer.Listener transformerListener =
    new Transformer.Listener() {
      @Override
      public void onCompleted(Composition composition, ExportResult result) {
        playOutput();
      }

      @Override
      public void onError(
          Composition composition, ExportResult result, ExportException exception) {
        displayError(exception);
      }
    };

ExportResult содержит информацию о выходном файле, включая его размер и средний битрейт аудио и видео (если применимо).

Получайте уведомления о прогрессе

Вызовите Transformer.getProgress, чтобы запросить текущий ход преобразования. Возвращаемое значение указывает на состояние выполнения. Если статус выполнения – PROGRESS_STATE_AVAILABLE, то в ProgressHolder будет указан текущий процент выполнения. В примере ниже показано, как периодически запрашивать ход преобразования. Метод updateProgressInUi можно реализовать для обновления индикатора выполнения.

Kotlin

transformer.start(inputMediaItem, outputPath)
val progressHolder = ProgressHolder()
mainHandler.post(
  object : Runnable {
    override fun run() {
      val progressState: @ProgressState Int = transformer.getProgress(progressHolder)
      updateProgressInUi(progressState, progressHolder)
      if (progressState != Transformer.PROGRESS_STATE_NOT_STARTED) {
        mainHandler.postDelayed(/* r= */ this, /* delayMillis= */ 500)
      }
    }
  }
)

Java

transformer.start(inputMediaItem, outputPath);
ProgressHolder progressHolder = new ProgressHolder();
mainHandler.post(
    new Runnable() {
      @Override
      public void run() {
        @Transformer.ProgressState int progressState = transformer.getProgress(progressHolder);
        updateProgressInUi(progressState, progressHolder);
        if (progressState != PROGRESS_STATE_NOT_STARTED) {
          mainHandler.postDelayed(/* r= */ this, /* delayMillis= */ 500);
        }
      }
    });

Как отменить преобразование

Если пользователь решит отказаться от экспорта, отмените операцию с помощью Transformer.cancel. Ресурсы, такие как аппаратные видеокодеки, ограничены, особенно на устройствах низкого класса, поэтому важно делать это, чтобы освободить ресурсы, если выходные данные не нужны.