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