Vamos começar

A introdução ao Transformer consiste nas seguintes 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, descrevendo a saída necessária e um listener para eventos de conclusão e de erro.
  4. Inicie a operação de exportação, transmitindo o EditedMediaItem para editar e um caminho de saída. Durante a exportação, é possível consultar o progresso atual ou cancelar a operação.
  5. Quando a exportação for concluída, processe a saída conforme necessário. Por exemplo, você pode compartilhar a saída para outro app ou fazer upload dela para um servidor.

Leia mais sobre essas etapas e consulte TransformerActivity no app de demonstração do transformador 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 à biblioteca no arquivo build.gradle do módulo do app:

Kotlin

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

Groovy

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

em que 1.4.1 é a versão que você prefere. 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 Google Maven AndroidX Media3.

Ativar o suporte a Java 8

Se ainda não estiver ativado, ative o suporte ao Java 8 em todos os arquivos build.gradle que dependem do Transformer adicionando 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, enviando 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 de itens de mídia do ExoPlayer. A entrada pode ser um stream progressivo ou adaptativo, mas a saída é sempre um stream 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 não é possível fazer exportações simultâneas com a mesma instância.

Observação sobre linhas de execução

As instâncias do transformador precisam ser acessadas em 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 linha de execução principal do aplicativo. Internamente, o Transformer trabalha em segundo plano e publica as chamadas para métodos de listener na linha de execução do aplicativo.

Ouvir eventos

O método start é assíncrono. Ele retorna imediatamente, e o app é notificado dos 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 e as taxas de bits médias de á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 do 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 de baixo custo. Portanto, é importante fazer isso para liberar recursos se a saída não for necessária.