Начало работы с Transformer
состоит из следующих шагов:
- Добавьте Media3 Transformer в качестве зависимости в свой проект.
- Создайте
EditedMediaItem
представляющий носитель для обработки и изменения, которые нужно применить к нему. - Создайте
Transformer
, описывающий требуемый вывод и прослушиватель событий завершения и ошибок. - Запустите операцию экспорта, передав
EditedMediaItem
для редактирования и путь вывода. Во время экспорта вы можете запросить текущий прогресс или отменить операцию. - По завершении экспорта обрабатывайте выходные данные по мере необходимости. Например, вы можете поделиться выводом в другом приложении или загрузить его на сервер.
Прочтите более подробную информацию об этих шагах и посмотрите TransformerActivity
в демонстрационном приложении Transformer для получения полного примера.
Добавьте Media3 Transformer в качестве зависимости
Самый простой способ начать использовать Transformer — добавить зависимости Gradle от библиотеки в файл build.gradle
вашего модуля приложения:
Котлин
implementation("androidx.media3:media3-transformer:1.4.1") implementation("androidx.media3:media3-effect:1.4.1") implementation("androidx.media3:media3-common:1.4.1")
классный
implementation "androidx.media3:media3-transformer:1.4.1" implementation "androidx.media3:media3-effect:1.4.1" implementation "androidx.media3:media3-common:1.4.1"
где 1.4.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
.
Котлин
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
. Ресурсы, такие как аппаратные видеокодеки, ограничены, особенно на устройствах более низкого уровня, поэтому важно сделать это, чтобы освободить ресурсы, если выходные данные не нужны.