Vamos começar

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

  1. Adicione o Transformer da Media3 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 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 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 transformador para ver 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.1")
implementation("androidx.media3:media3-effect:1.11.1")
implementation("androidx.media3:media3-common:1.11.1")

Groovy

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

em que 1.11.1 é a versão de sua preferência. Para conferir a versão mais recente, consulte as notas da versão.

Para mais informações sobre os módulos de biblioteca disponíveis, consulte a página do Google Maven AndroidX Media3.

Ativar a compatibilidade com o 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, gerando o resultado em 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 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 não há suporte para exportações simultâneas com a mesma instância.

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

Observação sobre linhas de execução

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

Detectar eventos

O método start é assíncrono. Ele retorna imediatamente, e o app é notificado sobre 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, como tamanho e 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 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. 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 com Transformer.cancel. Recursos como codecs de vídeo de hardware são limitados, especialmente em dispositivos de baixo custo. Por isso, é importante fazer isso para liberar recursos se a saída não for necessária.