Jetpack Media3 Transformer позволяет редактировать, конвертировать и экспортировать медиаконтент на устройствах Android. На этой странице рассказывается, как настроить основные преобразования:
- Перекодирование и перемультиплексирование. Преобразуйте аудио- и видеоформаты или пропустите повторное кодирование, скопировав образец контейнера (перемультиплексирование).
- Удаление дорожек. Удаление аудио- или видеодорожек из медиафайлов.
- Обрезка и оптимизация. Вы можете обрезать медиаконтент по временной метке, а также ускорить экспорт с помощью списков редактирования MP4 и оптимизации обрезки.
- Видеоэффекты. Изменяйте масштаб и поворот видео, а также применяйте к нему пользовательские шейдерные эффекты OpenGL. Результат можно посмотреть в ExoPlayer.
- Изображения. Превращайте статичные изображения в видеоклипы с заданной продолжительностью и частотой кадров.
- Обработка аудио. Объединяйте несколько экземпляров
AudioProcessor, чтобы изменять необработанные аудиоданные.
Как перекодировать файлы в другие форматы
При создании Transformer можно указать, в каких форматах будут сохраняться аудио- и видеофайлы. Например, в следующем коде показано, как настроить Transformer для вывода видео в формате H.264/AVC и аудио в формате AAC:
Kotlin
Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H264) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build()
Java
new Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H264) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build();
Если входной формат медиафайла уже соответствует конфигурациям для аудио или видео, Transformer автоматически переключается на трансмуксирование, то есть копирует сжатые образцы из входного контейнера в выходной без изменений. Это позволяет избежать вычислительных затрат и потенциальной потери качества при декодировании и повторном кодировании в том же формате.
Как удалить аудио- или видеозапись
Удалите аудио или видео, используя EditedMediaItem.Builder, например:
Kotlin
EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()
Java
new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();
Как обрезать клип
Вы можете удалить все медиафайлы за пределами указанных временных меток начала и окончания, задав конфигурацию обрезки для входного медиаобъекта. Например, чтобы создать клип, содержащий только медиаконтент между 10 и 20 секундами, выполните следующие действия:
Kotlin
val inputMediaItem = MediaItem.Builder() .setUri(uri) .setClippingConfiguration( MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(10_000) .setEndPositionMs(20_000) .build() ) .build()
Java
MediaItem inputMediaItem = new MediaItem.Builder() .setUri(uri) .setClippingConfiguration( new MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(10_000) .setEndPositionMs(20_000) .build()) .build();
Списки изменений MP4
Для более быстрой обрезки Transformer поддерживает списки редактирования MP4, что позволяет более эффективно выполнять редактирование только с обрезкой без полного перекодирования видео. Этот метод использует существующие закодированные образцы и "предварительный ролик" в списке изменений, который указывает проигрывателю начать воспроизведение с определенной точки, пропуская нежелательный начальный сегмент.
Чтобы значительно ускорить редактирование, связанное только с обрезкой, вызовите experimentalSetMp4EditListTrimEnabled(true).
Kotlin
Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build()
Java
new Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build();
Как оптимизировать обрезку
Чтобы уменьшить задержку при обрезке начала видео, включите оптимизацию обрезки.
Kotlin
Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build()
Java
new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build();
Это ускоряет экспорт, поскольку декодируется и повторно кодируется как можно меньшая часть видео, а затем повторно закодированные данные объединяются с остальной частью исходного видео. Оптимизация основана на возможности объединить часть входного файла с новым закодированным выходным файлом, а это значит, что формат выходного файла кодировщика и формат входного файла должны быть совместимы. Например, если файл был создан на устройстве с другой реализацией кодера, то, скорее всего, оптимизировать его не получится.
Чтобы оптимизация прошла успешно, кодировщик, предоставленный Transformer через EncoderFactory, должен иметь уровень и профиль, совместимые с входным форматом.
Эта оптимизация работает только с одноэлементными входными файлами MP4 без эффектов, за исключением видеоэффектов no op и поворотов, кратных 90 градусам. Если оптимизация не удастся, Transformer автоматически вернется к обычному экспорту и сообщит о результате оптимизации в ExportResult.OptimizationResult.
Мы проверяем эту функцию и планируем сделать ее доступной в одном из следующих релизов.
Редактирование видео
EditedMediaItems содержат списки аудиопроцессоров и видеоэффектов, которые нужно применять в определенном порядке. Библиотека содержит реализации видеоэффектов для распространенных случаев использования. Вы также можете написать собственные эффекты и передать их при создании отредактированных медиаобъектов.
Вы можете изменить масштаб медиафайла, чтобы сэкономить ресурсы обработки или пропускную способность при работе с входными данными очень высокого разрешения, например видео 4K или 8K. Например, чтобы пропорционально масштабировать изображение до высоты 480 пикселей, выполните следующие действия:
Kotlin
EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects( Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf(Presentation.createForHeight(480)), ) ) .build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects( new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of(Presentation.createForHeight(480)))) .build();
Вы также можете задать коэффициент масштабирования, например чтобы уменьшить размер вдвое:
Kotlin
val editedMediaItem = EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects( Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf( ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build() ), ) ) .build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects( new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of( new ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build()))) .build();
Настроить ротацию можно следующим образом:
Kotlin
EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects( Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf( ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build() ), ) ) .build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects( new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of( new ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build()))) .build();
Собственные видеоэффекты
Конструктор Effects принимает список аудио- и видеоэффектов, которые нужно применить.
Внутренний фреймворк Transformer для работы с эффектами преобразует список видеоэффектов в последовательность программ шейдеров OpenGL, которые применяются по порядку. В некоторых случаях фреймворк эффектов может применить несколько эффектов с помощью одной программы шейдера.
Например, одна программа шейдера может применять несколько последовательных преобразований матрицы, что повышает эффективность и качество.
Видеоэффекты также поддерживаются для предварительного просмотра в ExoPlayer с помощью ExoPlayer.setVideoEffects. Пример использования этого API можно найти в демонстрационном приложении с эффектами.
В демонстрационном приложении есть примеры специальных видеоэффектов.
Ввод изображения
Transformer поддерживает изображения, обрабатывая их как статические видеоклипы. Чтобы настроить изображение в качестве источника входных данных, выполните следующие действия:
Создайте
MediaItem, используяMediaItem.Builder. Укажите продолжительность показа изображения в выходном видео, вызвав функциюsetImageDurationMs.Создайте объект
EditedMediaItem, который будет содержать объектMediaItem. Укажите целевую частоту кадров для сгенерированного видеопотока, используяEditedMediaItem.Builder#setFrameRate.
В следующем примере показано, как настроить входное изображение для создания пятисекундного видео с частотой 30 кадров в секунду:
Kotlin
val imageMediaItem = MediaItem.Builder() .setUri(imageUri) .setImageDurationMs(5000) // 5 seconds .build() val editedImageItem = EditedMediaItem.Builder(imageMediaItem) .setFrameRate(30) // 30 frames per second .build()
Java
MediaItem imageMediaItem = new MediaItem.Builder() .setUri(imageUri) .setImageDurationMs(5000) // 5 seconds .build(); new EditedMediaItem.Builder(imageMediaItem) .setFrameRate(30) // 30 frames per second .build();
Редактирование аудио
Аудиоэффекты реализуются путем применения последовательности экземпляров AudioProcessor к необработанному аудио (PCM). ExoPlayer поддерживает передачу аудиопроцессоров в метод DefaultAudioSink.Builder, что позволяет просматривать изменения аудио.