一文掌握 Media3 1.5.0 的新功能

一文掌握 Media3 1.5.0 的新功能

作者 / 工程经理 Kristina Simakova

Media3 1.5.0 已推出

Transformer 现在支持动态照片和更快的图像编码。我们还简化了 DefaultPreloadManager 和 ExoPlayer 的设置,使其更加易于使用。不止如此,我们添加了一个新的 IAMF 解码器、一个 Kotlin 监听器扩展程序,并通过委托实现了更简单的播放器优化。

如要详细了解有关所有新 API 和错误修复的信息,欢迎您查看 完整的版本说明

Transformer 优化

动态照片支持

Transformer 现在支持导出动态照片。如果设置了相应的 MediaItem 图像持续时间,则会导出动态照片的图像 (请参阅 MediaItem.Builder().setImageDurationMs()),否则,将导出动态照片的视频。请注意,无论哪种情况下,都不应设置 EditedMediaItem 的持续时间,因为系统会自动调整为相应的 MediaItem 的图像持续时间。

更快的图像编码

此版本通过对 DefaultVideoFrameProcessor.queueInputBitmap() 的优化,提升了图像到视频的编码速度。DefaultVideoFrameProcessor 现在将提供给 queueInputBitmap() 的 Bitmap 视为不可变对象。GL 管道将仅对输入 Bitmap 进行一次重采样和颜色转换。因此,将大型 (例如 1200 万像素) 图像作为输入的 Transformer 操作执行速度更快。

AudioEncoderSettings

VideoEncoderSettings 类似,Transformer 现在支持 AudioEncoderSettings,可用于设置所需的编码配置文件和比特率。

编辑列表支持

Transformer 现在会将第一个视频帧转换为从 0 开始。这修复了在某些包含编辑列表的文件中出现的音视频同步问题。

不支持的轨道类型日志记录

此版本包括改进了不支持的轨道类型的日志记录,可为问题排查和调试提供更详细的信息。

Media3 Muxer

在之前的某个版本中,我们添加了一个新的 Muxer 库,可用于创建 MP4 容器文件。Media3 Muxer 支持多种音频和视频编解码器,可顺畅处理各种媒体格式。此外,这个新库还具备一些高级功能,包括:

  • B-frame 支持

  • 碎片化的 MP4 输出

  • 编辑列表支持

Muxer 库可以作为 gradle 依赖项包含在内:

implementation ("androidx.media3:media3-muxer:1.5.0")

Media3 Muxer 与 Transformer

如要将 Media3 Muxer 与 Transformer 一起使用,请在创建 Transformer 时将 InAppMuxer.Factory (其内部封装了 Media3 Muxer) 设置为 Muxer factory:

val transformer = Transformer.Builder(context)
    .setMuxerFactory(InAppMuxer.Factory.Builder().build())
    .build()

简化 DefaultPreloadManager ExoPlayer 的设置

在 Media3 1.5.0 中,我们增加了 DefaultPreloadManager.Builder,可使您更加容易地构建预加载组件和播放器。此前,我们要求您先实例化多个必要组件 (如 RenderersFactoryTrackSelectorFactoryLoadControlBandwidthMeter 和预加载/播放 Looper),并在将这些组件注入 DefaultPreloadManager 构造函数和 ExoPlayer.Builder 时,十分谨慎地正确共享这些组件。通过使用新的 DefaultPreloadManager.Builder,这个过程变得简单多了:

  • 使用所有默认组件构建 DefaultPreloadManager 和 ExoPlayer 实例。
val preloadManagerBuilder = DefaultPreloadManager.Builder()
val preloadManager = preloadManagerBuilder.build()
val player = preloadManagerBuilder.buildExoPlayer()
  • 使用自定义共享组件构建 DefaultPreloadManager 和 ExoPlayer 实例。
val preloadManagerBuilder = DefaultPreloadManager.Builder().setRenderersFactory(customRenderersFactory)
// The resulting preloadManager uses customRenderersFactoryval preloadManager = preloadManagerBuilder.build()
// The resulting player uses customRenderersFactoryval player = preloadManagerBuilder.buildExoPlayer()
  • 构建 DefaultPreloadManagerExoPlayer 实例,并在 ExoPlayer 上设置自定义的仅播放配置。
val preloadManagerBuilder = DefaultPreloadManager.Builder()
val preloadManager = preloadManagerBuilder.build()
// Tune the playback-only configurations
val playerBuilder = ExoPlayer.Builder().setFooEnabled()
// The resulting player will have playback feature "Foo" enabled
val player = preloadManagerBuilder.buildExoPlayer(playerBuilder)

预加载下个播放列表项目

我们在 ExoPlayer 中增加了预加载下个播放列表项目功能。默认情况下,播放列表预加载功能处于禁用状态,但可以通过设定预加载到内存的持续时间来启用该功能:

player.preloadConfiguration =
    PreloadConfiguration(/* targetPreloadDurationUs= */ 5_000_000L)

通过使用上述 PreloadConfiguration,播放器尝试为播放列表中的下一个项目预加载五秒钟的媒体内容。仅当系统没有加载当前播放所需的媒体时,预加载功能才会启动。这样可以避免预加载占用主要播放内容的带宽。

启用预加载功能后,当用户跳转到下一个项目,而播放缓冲区尚未到达下一个项目时,预加载可以帮助充分缩短衔接延迟。通过将视频、音频和文本样本预加载到样本队列,这项功能可以将下个播放项目的开头内容准备就绪。预加载的时间段随后会被排队到播放器中,预加载的样本立即可用并随时可供编解码器进行渲染。

选择启用后,可以通过使用 PreloadConfiguration.DEFAULT 再次关闭播放列表预加载功能,以停用播放列表预加载:

player.preloadConfiguration = PreloadConfiguration.DEFAULT

新 IAMF 解码器和 Kotlin 监听器扩展程序

1.5.0 版本包含一个新的 media3-decoder-iamf 模块,该模块支持以 MP4 文件形式播放 IAMF 沉浸式音频轨道。如果应用想要试用此功能,则需在本地构建 libiamf 解码器。您可以参阅 Media3 自述文件 了解完整说明。

implementation ("androidx.media3:media3-decoder-iamf:1.5.0")

此版本还包含一个新的 media3-common-ktx 模块,这是用于 Kotlin 特定功能的模块。此模块的第一个版本包含一个挂起函数,可以让调用方监听 Player.Listener.onEventsmedia3-ui-compose 模块 (已随 Media3 1.6.0 一起推出) 使用此构建模块来支持 Jetpack Compose 播放界面。

implementation ("androidx.media3:media3-common-ktx:1.5.0")

通过委托轻松定制播放器

Media3 自 1.0.0 版以来,提供了 ForwardingPlayer 实现,我们之前曾建议,当应用想要通过使用 装饰器模式 自定义 Player 的运作方式时,应该使用这个实现。一个非常常见的用例是允许或禁止某些播放器命令 (以便在界面中显示/隐藏某些按钮)。遗憾的是,使用 ForwardingPlayer 正确执行此操作非常困难且容易出错,因为必须一致地重写多个方法,并处理监听器。受限于文章篇幅,不在此使用示例代码说明上述方法的复杂程度,因此我们直接 切入重点

为了使此类自定义操作更轻松,1.5.0 版本新增了 ForwardingSimpleBasePlayer,基于 SimpleBasePlayer 提供的一致性保证进行构建,能够更轻松地根据装饰器模式建立一致的播放器实现。现在,可以更加轻松地使用相同的命令修改 Player

class PlayerWithoutSeekToNext(player: Player) : ForwardingSimpleBasePlayer(player) {
  override fun getState(): State {
    val state = super.getState()
    return state
      .buildUpon()
      .setAvailableCommands(
        state.availableCommands.buildUpon().remove(COMMAND_SEEK_TO_NEXT).build()
      )
      .build()
  }

  // We don't need to override handleSeek, because it is guaranteed not to be called for
  // COMMAND_SEEK_TO_NEXT since we've marked that command unavailable.
}

MediaSession:媒体项目的命令按钮

媒体项目的命令按钮允许会话应用声明某些媒体项目支持的命令,这些命令可以通过 MediaController 或 MediaBrowser 方便地显示和执行:

△ 屏幕截图:Android Automotive OS 媒体中心中媒体项目的命令按钮。

△ 屏幕截图:Android Automotive OS 媒体中心中媒体项目的命令按钮。

您可以查阅 Android Developer 官方网站,了解详细内容。

这是 Media3 中等效于旧版 "自定义浏览操作" API 的功能,Media3 可以与其完全互操作。与旧版 API 不同,媒体项目的命令按钮不需要 MediaLibraryService,而是 Media3 MediaSession 的一项功能。因此,这些按钮能够以相同的方式供 MediaController 和 MediaBrowser 使用。

如果您遇到任何问题,有功能请求或想要分享反馈,请使用 GitHub 上的 Media3 问题跟踪页 进行问题反馈。

这篇文章是我们 "相机与媒体 Spotlight Week" 系列的内容之一。在此系列中,我们会提供包括文章、视频、示例代码等资源,以帮助您提升应用中的媒体体验。

版权声明

禁止一切形式的转载-禁止商用-禁止衍生 申请授权

脉脉不得语
脉脉不得语
Zhengzhou Website
Android Developer | https://androiddevtools.cn and https://androidweekly.io Funder | GDG Zhengzhou Funder & Ex Organizer | http://Toast.show(∞) Podcast Host

你已经成功订阅到 Android 开发技术周报
太棒了!接下来,完成检验以获得全部访问权限 Android 开发技术周报
欢迎回来!你已经成功登录了。
Unable to sign you in. Please try again.
成功!您的帐户已完全激活,您现在可以访问所有内容。
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.
🍗