Чтобы начать работу с Transformer, выполните следующие действия:
- Добавьте Media3 Transformer в качестве зависимости в проект.
- Создайте объект
EditedMediaItem, представляющий медиафайл, который нужно обработать, и изменения, которые нужно к нему применить. - Создайте объект
Transformer, описывающий требуемые выходные данные и прослушиватель для событий завершения и ошибок. - Запустите операцию экспорта, передав
EditedMediaItemдля редактирования и путь к выходному файлу. Во время экспорта вы можете запросить текущий прогресс или отменить операцию. - После завершения экспорта обработайте выходные данные нужным образом. Например, вы можете поделиться результатом в другом приложении или загрузить его на сервер.
Ниже приведены подробные сведения об этих шагах, а в демоприложении 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. Ресурсы, такие как аппаратные видеокодеки, ограничены, особенно на устройствах низкого класса, поэтому важно делать это, чтобы освободить ресурсы, если выходные данные не нужны.