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

Начало работы с Transformer состоит из следующих шагов:

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

Прочтите более подробную информацию об этих шагах и посмотрите TransformerActivity в демонстрационном приложении Transformer для получения полного примера.

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

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

Котлин

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

классный

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

где 1.4.0 — ваша предпочтительная версия. Последнюю версию можно найти, просмотрев примечания к выпуску .

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

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

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

compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}

Начать трансформацию

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

Котлин

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)

Ява

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 выполняет свою работу в фоновом режиме и отправляет вызовы методов прослушивателя в поток приложения.

Слушайте события

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

Котлин

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)
  }
}

Ява

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 для обновления индикатора выполнения.

Котлин

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)
        }
      }
    }
)

Ява

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 . Ресурсы, такие как аппаратные видеокодеки, ограничены, особенно на устройствах более низкого уровня, поэтому важно сделать это, чтобы освободить ресурсы, если выходные данные не нужны.