入门

使用 Transformer 入门包含以下步骤

  1. 在您的项目中添加 Media3 Transformer 作为依赖项。
  2. 构建一个 EditedMediaItem,表示要处理的媒体和要应用于它的编辑。
  3. 构建一个 Transformer,描述所需的输出和完成和错误事件的侦听器。
  4. 启动导出操作,传入要编辑的 EditedMediaItem 和一个输出路径。在导出期间,您可以查询当前进度或取消操作。
  5. 导出完成后,根据需要处理输出。例如,您可以将输出共享到其他应用程序或将其上传到服务器。

阅读更多关于这些步骤的详细信息,并在 TransformerActivity 中查看 transformer 演示应用程序 以获取完整示例。

添加 Media3 Transformer 作为依赖项

开始使用 Transformer 的最简单方法是在应用程序模块的 build.gradle 文件中添加对库的 gradle 依赖项

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"

其中 1.4.1 是您首选的版本。最新的版本可以在 发行说明 中找到。

有关可用库模块的更多信息,请参阅 Google Maven AndroidX Media3 页面

启用 Java 8 支持

如果尚未启用,您需要在所有依赖 Transformer 的 build.gradle 文件中启用 Java 8 支持,方法是在 android 部分添加以下内容

compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}

启动转换

以下是一个创建 EditedMediaItem 以删除输入文件的音频,然后创建和配置 Transformer 实例以导出 H.265/HEVC 视频,并将结果输出到 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);

有关媒体项目的更多信息,请参阅 ExoPlayer 媒体项目页面。输入可以是渐进式流或自适应流,但输出始终是渐进式流。对于自适应输入,始终选择最高分辨率的轨道进行转换。输入可以是 ExoPlayer 支持的任何容器格式 支持,但输出始终是 MP4 文件。

您可以在同一个 Transformer 实例上按顺序执行多个导出操作,但不支持使用同一个实例进行并发导出。

关于线程的说明

必须从单个应用程序线程访问 Transformer 实例,并且监听器方法将在同一个线程上调用。在大多数情况下,应用程序线程可以是应用程序的主线程。在内部,Transformer 在后台完成其工作,并将其对监听器方法的调用发布到应用程序线程上。

监听事件

start 方法是异步的。它会立即返回,并且应用程序会通过传递给 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 包含有关输出文件的信息,包括文件大小以及音频和视频的平均比特率(如果适用)。

获取进度更新

调用 Transformer.getProgress 查询转换的当前进度。返回值表示进度状态。如果进度状态为 PROGRESS_STATE_AVAILABLE,则提供的 ProgressHolder 将使用当前进度百分比更新。以下示例展示了如何定期查询转换的进度,其中 updateProgressInUi 方法可以用来更新进度条。

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

取消转换

如果用户选择退出导出流程,请使用 Transformer.cancel 取消导出操作。硬件视频编解码器之类的资源有限,尤其是在低端设备上,因此如果不需要输出,则必须这样做以释放资源。