Vamos começar

Para começar a usar o Transformer, siga estas etapas:

  1. Adicione o Media3 Transformer como uma dependência no seu projeto.
  2. Crie um EditedMediaItem que represente a mídia a ser processada e as edições a serem aplicadas a ela.
  3. Crie um Transformer que descreva a saída necessária e um listener para eventos de conclusão e erro.
  4. Inicie a operação de exportação, transmitindo o EditedMediaItem a ser editado e um caminho de saída. Durante a exportação, você pode consultar o progresso atual ou cancelar a operação.
  5. Quando a exportação terminar, processe a saída conforme necessário. Por exemplo, você pode compartilhar a saída com outro app ou fazer upload dela para um servidor.

Leia mais detalhes sobre essas etapas e consulte TransformerActivity no app de demonstração do Transformer para conferir um exemplo completo.

Adicionar o Media3 Transformer como uma dependência

A maneira mais fácil de começar a usar o Transformer é adicionar dependências do Gradle na biblioteca no arquivo build.gradle do módulo do app:

Kotlin

implementation("androidx.media3:media3-transformer:1.11.0")
implementation("androidx.media3:media3-effect:1.11.0")
implementation("androidx.media3:media3-common:1.11.0")

Groovy

implementation "androidx.media3:media3-transformer:1.11.0"
implementation "androidx.media3:media3-effect:1.11.0"
implementation "androidx.media3:media3-common:1.11.0"

em que 1.11.0 é a versão preferida. A versão mais recente pode ser encontrada consultando as notas da versão.

Mais informações sobre os módulos de biblioteca disponíveis podem ser encontradas na página do Google Maven AndroidX Media3.

Ativar o suporte ao Java 8

Se ainda não estiver ativado, você precisará ativar o suporte ao Java 8 em todos os arquivos build.gradle que dependem do Transformer. Para isso, adicione o seguinte à seção android:

compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}

Iniciar uma transformação

Confira um exemplo de como criar um EditedMediaItem para remover o áudio de um arquivo de entrada e, em seguida, criar e configurar uma instância Transformer para exportar vídeo H.265/HEVC, gerando o resultado para 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);

Para mais informações sobre itens de mídia, consulte a página Itens de mídia do ExoPlayer. A entrada pode ser um fluxo progressivo ou adaptável, mas a saída é sempre um fluxo progressivo. Para entradas adaptáveis, as faixas de maior resolução são sempre selecionadas para a transformação. A entrada pode ser de qualquer formato de contêiner compatível com o ExoPlayer, mas a saída é sempre um arquivo MP4.

É possível executar várias operações de exportação sequencialmente na mesma instância Transformer, mas as exportações simultâneas com a mesma instância não são compatíveis.

Para informações sobre como gerar mídia compondo várias entradas, consulte Edição de vários recursos.

Observação sobre linhas de execução

As instâncias do Transformer precisam ser acessadas de uma única linha de execução do aplicativo, e os métodos do listener são chamados na mesma linha de execução. Na maioria dos casos, a linha de execução do aplicativo pode ser apenas a principal. Internamente, o Transformer faz o trabalho em segundo plano e envia as chamadas para os métodos do listener na linha de execução do aplicativo.

Detectar eventos

O método start é assíncrono. Ele retorna imediatamente, e o app é notificado de eventos pelo listener transmitido ao builder 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 inclui informações sobre o arquivo de saída, incluindo o tamanho do arquivo e as taxas de bits médias para áudio e vídeo, conforme aplicável.

Receber atualizações de progresso

Chame Transformer.getProgress para consultar o progresso atual de uma transformação. O valor retornado indica o estado de progresso. Se o estado de progresso for PROGRESS_STATE_AVAILABLE, o ProgressHolder fornecido será atualizado com a porcentagem de progresso atual. O exemplo a seguir mostra como consultar periodicamente o progresso de uma transformação, em que o método updateProgressInUi pode ser implementado para atualizar uma barra de progresso.

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);
        }
      }
    });

Cancelar uma transformação

Se o usuário optar por sair de um fluxo de exportação, cancele a operação de exportação com Transformer.cancel. Recursos como codecs de vídeo de hardware são limitados, especialmente em dispositivos mais simples. Por isso, é importante fazer isso para liberar recursos se a saída não for necessária.