Преобразования

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, что позволяет просматривать изменения аудио.