入门

Transformer 入门包括以下步骤

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

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

添加 Media3 Transformer 作为依赖项

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

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"

其中 1.7.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 取消导出操作。硬件视频编解码器等资源有限,尤其是在低端设备上,因此如果不需要输出,取消操作以释放资源非常重要。