转换

在格式之间进行转码

您可以在构建 Transformer 时指定要生成的输出音频和视频格式。例如,以下代码展示了如何配置 Transformer 以输出 H.264/AVC 视频和 AAC 音频:

Kotlin

Transformer.Builder(context)
  .setVideoMimeType(MimeTypes.VIDEO_H264)
  .setAudioMimeType(MimeTypes.AUDIO_AAC)
  .build()

Java

new Transformer.Builder(context)
    .setVideoMimeType(MimeTypes.VIDEO_H264)
    .setAudioMimeType(MimeTypes.AUDIO_AAC)
    .build();

如果输入媒体格式已与音频 或视频的配置匹配,Transformer 会自动切换到 混流 ,即从输入容器将压缩的样本复制到输出容器,而不进行 修改。这样可以避免以相同格式进行解码和重新编码所产生的计算成本和潜在的质量损失。

移除音频或视频

使用 EditedMediaItem.Builder 移除音频或视频,例如:

Kotlin

EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()

Java

new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();

剪辑片段

您可以通过在输入媒体项上设置剪辑配置,移除指定开始和结束时间戳之外的任何媒体。例如,如需生成仅包含 10 秒到 20 秒之间的媒体的片段,请执行以下操作:

Kotlin

val inputMediaItem =
  MediaItem.Builder()
    .setUri(uri)
    .setClippingConfiguration(
      MediaItem.ClippingConfiguration.Builder()
        .setStartPositionMs(10_000)
        .setEndPositionMs(20_000)
        .build()
    )
    .build()

Java

MediaItem inputMediaItem =
    new MediaItem.Builder()
        .setUri(uri)
        .setClippingConfiguration(
            new MediaItem.ClippingConfiguration.Builder()
                .setStartPositionMs(10_000)
                .setEndPositionMs(20_000)
                .build())
        .build();

MP4 编辑列表

为了更快地进行剪辑,Transformer 支持 MP4 编辑列表,从而可以更高效地进行“仅剪辑”编辑,而无需重新转码整个视频。此方法利用现有编码样本和编辑列表中的“前贴片广告”,该广告会指示播放器从特定点开始播放,从而有效地跳过不需要的初始片段。

如需显著加快仅剪辑编辑的速度,请调用 experimentalSetMp4EditListTrimEnabled(true)

Kotlin

Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build()

Java

new Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build();
请务必注意,并非所有媒体播放器都支持“前贴片广告”位置。这意味着,当使用此类播放器时,无论任何编辑列表信息可能指定不同的起始点,文件都将从编码样本的绝对开头开始播放。

优化剪辑

如需缩短剪辑视频开头的延迟时间,请启用剪辑优化。

Kotlin

Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build()

Java

new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build();

这会尽可能少地解码和重新编码视频,然后将重新编码的数据与原始视频的其余部分拼接在一起,从而加快导出速度。优化依赖于能够将输入文件的部分内容与新编码的输出拼接在一起,这意味着编码器的输出格式和输入格式必须兼容。因此,举例来说,如果文件最初是在具有不同编码器实现的设备上生成的,则很可能无法应用优化。 如需成功进行优化,通过 EncoderFactory 提供给 Transformer 的编码器必须具有与输入格式兼容的级别和配置文件。

此优化仅适用于单项 MP4 输入,且没有效果,但无操作视频效果和可被 90 度整除的旋转除外。如果优化失败,Transformer 会自动回退到正常导出,并在 ExportResult.OptimizationResult 中报告优化结果。

我们正在验证此功能,并预计它会在后续版本中成为非实验性功能。

视频编辑

EditedMediaItems 具有音频处理器和视频效果列表,可按顺序应用。该库包含适用于常见用例的视频效果实现,您也可以编写自定义效果并在构建经过编辑的媒体项时传入这些效果。

您可以重新缩放媒体,这在处理非常高分辨率的输入(例如 4k 或 8k 视频)时有助于节省处理资源或带宽。 例如,如需按比例缩放至 480 像素高,请执行以下操作:

Kotlin

EditedMediaItem.Builder(MediaItem.fromUri(uri))
  .setEffects(
    Effects(
      /* audioProcessors= */ listOf(),
      /* videoEffects= */ listOf(Presentation.createForHeight(480)),
    )
  )
  .build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(
        new Effects(
            /* audioProcessors= */ ImmutableList.of(),
            /* videoEffects= */ ImmutableList.of(Presentation.createForHeight(480))))
    .build();

或者,您也可以按给定的比例缩放,例如,如需将大小减半,请执行以下操作:

Kotlin

val editedMediaItem =
  EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(
      Effects(
        /* audioProcessors= */ listOf(),
        /* videoEffects= */ listOf(
          ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build()
        ),
      )
    )
    .build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(
        new Effects(
            /* audioProcessors= */ ImmutableList.of(),
            /* videoEffects= */ ImmutableList.of(
                new ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build())))
    .build();

您可以采用相同的方式配置旋转:

Kotlin

EditedMediaItem.Builder(MediaItem.fromUri(uri))
  .setEffects(
    Effects(
      /* audioProcessors= */ listOf(),
      /* videoEffects= */ listOf(
        ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build()
      ),
    )
  )
  .build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(
        new Effects(
            /* audioProcessors= */ ImmutableList.of(),
            /* videoEffects= */ ImmutableList.of(
                new ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build())))
    .build();

自定义视频效果

Effects 构造函数接受要应用的音频和视频效果列表。在内部,Transformer 的效果框架会将视频效果列表转换为按顺序应用的 GL 着色器程序序列。在某些情况下,效果框架能够使用一个着色器程序应用多种效果。 例如,一个着色器程序可以应用多个连续的矩阵转换,从而提高效率和质量。

ExoPlayer 中也支持使用 ExoPlayer.setVideoEffects 预览视频效果。如需查看如何使用此 API 的示例,请查看 效果演示版应用

演示版应用包含自定义视频效果的示例。

图片输入

Transformer 通过将图片视为静态视频片段来支持图片输入。如需将图片配置为输入源,请按以下步骤操作:

  • 使用 MediaItem.Builder 创建 MediaItem。通过调用 setImageDurationMs 指定图片在输出视频中的显示时长。

  • 构建封装 MediaItemEditedMediaItem。使用 EditedMediaItem.Builder#setFrameRate 为生成的视频流指定目标帧速率。

以下示例展示了如何配置图片输入以生成一个 5 秒的视频,帧速率为每秒 30 帧:

Kotlin

val imageMediaItem =
  MediaItem.Builder()
    .setUri(imageUri)
    .setImageDurationMs(5000) // 5 seconds
    .build()

val editedImageItem =
  EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build()

Java

MediaItem imageMediaItem =
    new MediaItem.Builder()
        .setUri(imageUri)
        .setImageDurationMs(5000) // 5 seconds
        .build();
new EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build();

音频编辑

音频效果是通过将一系列 AudioProcessor 实例应用于原始 (PCM) 音频来实现的。ExoPlayer 支持将音频处理器传递给 DefaultAudioSink.Builder,从而可以预览音频编辑。