Cómo empezar

Para comenzar a usar Transformer, sigue estos pasos:

  1. Agrega Media3 Transformer como dependencia en tu proyecto.
  2. Compila un objeto EditedMediaItem que represente el contenido multimedia que se procesará y las ediciones que se le aplicarán.
  3. Crea un objeto Transformer que describa el resultado requerido y un objeto de escucha para los eventos de finalización y error.
  4. Inicia la operación de exportación y pasa el EditedMediaItem para editar y una ruta de acceso de salida. Durante la exportación, puedes consultar el progreso actual o cancelar la operación.
  5. Cuando finalice la exportación, controla el resultado según sea necesario. Por ejemplo, puedes compartir el resultado con otra app o subirlo a un servidor.

Sigue leyendo para obtener más detalles sobre estos pasos y consulta TransformerActivity en la app de demostración del transformador para ver un ejemplo completo.

Agrega Media3 Transformer como dependencia

La forma más sencilla de comenzar a usar Transformer es agregar dependencias de Gradle en la biblioteca en el archivo build.gradle del módulo de tu app:

Kotlin

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

Groovy

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

donde 1.7.1 es la versión que prefieres. Para conocer la versión más reciente, consulta las notas de la versión.

Puedes encontrar más información sobre los módulos de biblioteca disponibles en la página de Google Maven AndroidX Media3.

Cómo activar la compatibilidad con Java 8

Si aún no lo hiciste, debes activar la compatibilidad con Java 8 en todos los archivos build.gradle que dependan de Transformer. Para ello, agrega lo siguiente a la sección android:

compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}

Cómo iniciar una transformación

A continuación, se muestra un ejemplo de cómo crear un EditedMediaItem para quitar el audio de un archivo de entrada y, luego, crear y configurar una instancia de Transformer para exportar video H.265/HEVC y generar el resultado en 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 obtener más información sobre los elementos multimedia, consulta la página de elementos multimedia de ExoPlayer. La entrada puede ser un flujo progresivo o adaptable, pero la salida siempre es un flujo progresivo. En el caso de las entradas adaptables, siempre se seleccionan las pistas de mayor resolución para la transformación. La entrada puede tener cualquier formato de contenedor compatible con ExoPlayer, pero la salida siempre es un archivo MP4.

Puedes ejecutar varias operaciones de exportación de forma secuencial en la misma instancia de Transformer, pero no se admiten exportaciones simultáneas con la misma instancia.

Nota sobre los subprocesos

Se debe acceder a las instancias de Transformer desde un solo subproceso de la aplicación, y los métodos de escucha se llaman en el mismo subproceso. En la mayoría de los casos, el subproceso de la aplicación puede ser el subproceso principal de la aplicación. Internamente, Transformer trabaja en segundo plano y publica sus llamadas a los métodos de escucha en el subproceso de la aplicación.

Cómo detectar eventos

El método start es asíncrono. Devuelve el resultado de inmediato, y se notifica a la app sobre los eventos a través del objeto de escucha que se pasa al compilador de 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 incluye información sobre el archivo de salida, como el tamaño del archivo y las tasas de bits promedio para el audio y el video, según corresponda.

Recibir actualizaciones del progreso

Llama a Transformer.getProgress para consultar el progreso actual de una transformación. El valor devuelto indica el estado de progreso. Si el estado de progreso es PROGRESS_STATE_AVAILABLE, el ProgressHolder proporcionado se actualiza con el porcentaje de progreso actual. En el siguiente ejemplo, se muestra cómo consultar periódicamente el progreso de una transformación, en el que se puede implementar el método updateProgressInUi para actualizar una barra de progreso.

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

Cómo cancelar una transformación

Si el usuario decide salir de un flujo de exportación, cancela la operación de exportación con Transformer.cancel. Los recursos, como los códecs de video por hardware, son limitados, en especial en los dispositivos de gama baja, por lo que es importante hacerlo para liberar recursos si no se necesita la salida.