Primeiros passos

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 para aplicar a ela.
  3. Crie um Transformer, descrevendo 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 para edição 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, é possível compartilhar a saída com outro app ou fazer upload dela para um servidor.

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

Adicionar 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.3.1")
implementation("androidx.media3:media3-effect:1.3.1")
implementation("androidx.media3:media3-common:1.3.1")

Groovy

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

em que 1.3.1 é sua versão preferida. Para encontrar a versão mais recente, consulte 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 a compatibilidade com Java 8

Ative o suporte para Java 8 em todos os arquivos build.gradle que dependem do Transformer, caso ainda não tenha feito isso, 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, 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 saber mais sobre itens de mídia, consulte a página de itens de mídia do ExoPlayer (em inglês). A entrada pode ser um stream progressivo ou um stream adaptável, 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 exportações simultâneas na mesma instância não são compatíveis.

Observação sobre as 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 de 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 publica as chamadas para os métodos do listener na linha de execução do aplicativo.

Ouvir eventos

O método start é assíncrono. Ele retorna imediatamente e o app é notificado sobre eventos pelo listener transmitido para o 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.