产品资讯

Media3 1.9.0 - 新变化

阅读用时:6 分钟
Kristina Simakova
工程经理

Media3 1.9.0 已发布!除了常规的 bug 修复和性能改进之外,最新版本还包含 4 个新模块或经过大幅重写的模块:

  • media3-inspector - 在播放之外提取元数据和帧
  • media3-ui-compose-material3 - 只需几个步骤即可构建基本的 Material3 Compose 媒体界面
  • media3-cast - 自动处理 Cast 和本地播放之间的过渡
  • media3-decoder-av1 - 基于 dav1d 库的重写扩展解码器,可实现一致的 AV1 播放

我们还对 PreloadManager 添加了缓存和内存管理方面的改进,并提供了多项新的 ExoPlayerTransformer 和 MediaSession 简化功能。

在此版本中,您还可以首次以实验性方式访问 CompositionPlayer,以预览媒体编辑内容。  


请继续阅读以了解详情,并像往常一样查看完整的版本说明,全面了解此版本中的变化。

在播放之外提取元数据和帧

在许多情况下,您可能希望在不开始播放的情况下检查媒体。例如,您可能需要检测视频包含哪些格式、时长是多少,或者检索缩略图。

新的 media3-inspector 模块将所有用于检查媒体(无需播放)的实用程序整合到了一处:

  • MetadataRetrieverMediaItem 中读取时长、格式和静态元数据。
  • FrameExtractor 以从商品中获取帧或缩略图。
  • MediaExtractorCompat 作为 Android 平台 MediaExtractor 类的直接替代项,用于获取文件中样本的详细信息。

MetadataRetriever 和 FrameExtractor 遵循简单的 AutoCloseable 模式。如需了解详情,请参阅我们的新指南页面

  suspend fun extractThumbnail(mediaItem: MediaItem) {

  FrameExtractor.Builder(context, mediaItem).build().use {

    val thumbnail = frameExtractor.getThumbnail().await()

  } 

}

只需几个步骤即可构建基本的 Material3 Compose 媒体界面

在之前的版本中,我们开始提供 Compose 界面元素与播放器实例之间的连接器代码。在 Media3 1.9.0 中,我们添加了一个新的模块 media3-ui-compose-material3,其中包含完全样式化的 Material3 按钮和内容元素。借助它们,您只需几步即可构建媒体界面,同时还可灵活地自定义样式。如果您希望自行构建界面样式,可以使用负责处理所有更新和连接逻辑的构建块,这样您只需专注于设计界面元素。请查看我们的 Compose 界面模块扩展指南页面

我们还在开发更多 Compose 组件,例如预建的进度条、可完全替代 PlayerView 的开箱即用型组件,以及字幕和广告集成。

  @Composable
fun SimplePlayerUI(player: Player, modifier: Modifier = Modifier) {
  Column(modifier) {
    ContentFrame(player)  // Video surface and shutter logic
    Row (Modifier.align(Alignment.CenterHorizontally)) {                 
      SeekBackButton(player)   // Simple controls
      PlayPauseButton(player)
      SeekForwardButton(player)
    }
  }
}

 

image.png

具有开箱即用元素的简单 Compose 播放器界面

自动处理 Cast 和本地播放之间的过渡

media3-cast 模块中的 CastPlayer 已重写,可自动处理本地播放(例如使用 ExoPlayer)和远程 Cast 播放之间的过渡。

设置 MediaSession 时,只需围绕 ExoPlayer 构建 CastPlayer,然后向界面添加 MediaRouteButton,即可完成!

  // MediaSession setup with CastPlayer 

val exoPlayer = ExoPlayer.Builder(context).build()

val castPlayer = CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build()

val session = MediaSession.Builder(context, castPlayer).build()

// MediaRouteButton in UI 

@Composable fun UIWithMediaRouteButton() {

  MediaRouteButton()

}
image.png

Media3 会话演示版应用中的新 CastPlayer 集成

基于 dav1d 的重写扩展程序可实现一致的 AV1 播放

1.9.0 版本包含一个基于热门 dav1d 库完全重写的 AV1 扩展模块。

与所有扩展解码器模块一样,请注意,它需要从源代码构建 才能正确捆绑相关的原生代码。捆绑解码器可在所有设备上提供一致的格式支持,但由于它会在您的进程中运行解码,因此最适合您信任的内容。

将缓存和内存管理集成到 PreloadManager 中

我们还对 PreloadManager 进行了改进。它已经支持您在播放之外将媒体预加载到内存中,然后在需要时无缝地将其交给播放器。虽然性能相当不错,但您仍然需要小心,以免因意外预加载过多内容而超出内存限制。因此,在 Media3 1.9.0 中,我们添加了两项功能,可让此过程更加轻松稳定:

  1. 缓存支持 - 在定义预加载距离时,您现在可以选择 PreloadStatus.specifiedRangeCached(0, 5000) 作为预加载项的目标状态。这会将指定范围添加到磁盘上的缓存中,而不是将数据加载到内存中。这样一来,您就可以提供范围更广的预加载项,因为距离当前项较远的项不再需要占用内存。请注意,这需要在 DefaultPreloadManager.Builder 中设置 Cache
  2. 自动内存管理 - 我们还更新了 LoadControl 接口,以便更好地处理预加载情况,因此您现在可以为内存中的所有预加载项设置明确的内存上限。默认值为 144 MB,您可以在 DefaultLoadControl.Builder 中配置此限制。达到限制后,DefaultPreloadManager 会自动停止预加载,并根据需要自动释放优先级较低的项目的内存。

依赖 ExoPlayer 中简化的新默认行为

与往常一样,我们还对 ExoPlayer 进行了许多增量改进。仅举几例:

  • 静音和取消静音 - 我们之前已经有 setVolume 方法,但现在添加了便捷的 muteunmute 方法,以便轻松恢复之前的音量,而无需自行跟踪。
  • 卡顿播放器检测 - 在极少数情况下,播放器可能会卡在缓冲或播放状态,而没有任何进展,例如,由于编解码器问题或配置错误。您的用户会感到恼火,但您在 Google Analytics 中却永远看不到这些问题!为了更清楚地说明这一点,播放器现在会在检测到卡住状态时报告 StuckPlayerException
  • 默认情况下使用唤醒锁定 - 唤醒锁定管理之前是选择性加入的,导致在后台运行时,播放进度可能会严重延迟,但很难找到这种边缘情况。现在,此功能为选择停用,因此您无需担心,还可以移除播放期间的所有手动唤醒锁定处理。
  • 简化了字幕按钮逻辑的设置 - 将 TrackSelectionParameters 更改为“开启/关闭字幕”出乎意料地难以实现,因此我们为此用例添加了一个简单的布尔值 selectTextByDefault 选项。

简化 MediaSession 中的媒体按钮偏好设置

到目前为止,如果您想在 Android Auto 或 WearOS 上的媒体通知抽屉中定义要显示的按钮,就需要定义自定义命令和按钮,即使您只是想触发标准播放器方法也是如此。

Media3 1.9.0 具有新功能,可让此过程变得简单得多 - 您现在可以使用标准播放器命令定义媒体按钮偏好设置,而无需进行任何自定义命令处理。

  session.setMediaButtonPreferences(listOf(
    CommandButton.Builder(CommandButton.ICON_FAST_FORWARD) // choose an icon
      .setDisplayName(R.string.skip_forward)
      .setPlayerCommand(Player.COMMAND_SEEK_FORWARD) // choose an action 
      .build()
))
image.png

包含快进按钮的媒体按钮偏好设置

用于实时预览的 CompositionPlayer

1.9.0 版本在新的 @ExperimentalApi 注释下引入了 CompositionPlayer。此注释表示该功能可用于实验,但仍处于开发阶段。

CompositionPlayer 是 Media3 编辑 API 中的一个新组件,专为实时预览媒体编辑而设计。CompositionPlayer 基于熟悉的 Media3 Player 接口构建,可让用户在提交导出流程之前查看更改的实际效果。它使用与您传递给 Transformer 以进行导出时相同的 Composition 对象,通过统一预览和导出的数据模型来简化编辑工作流程。

我们鼓励您开始使用 CompositionPlayer 并分享您的反馈,同时密切关注即将发布的帖子和文档更新,以了解更多详情。

将 InAppMuxer 用作 Transformer 中的默认复用器

转换器现在使用 InAppMp4Muxer 作为写入媒体容器文件的默认混合器。在内部,InAppMp4Muxer 依赖于 Media3 Muxer 模块,可在所有 API 版本中提供一致的行为。

请注意,虽然 Transformer 默认不再使用 Android 平台的 MediaMuxer,但如果您的使用情形需要,您仍然可以通过 setMuxerFactory 提供 FrameworkMuxer.Factory

新增了速度调整 API

1.9.0 版简化了媒体编辑的速度调整 API。我们在 EditedMediaItem.Builder 中直接引入了用于控制速度的新方法,使 API 更加直观。您现在可以通过对 EditedMediaItem.Builder 调用 setSpeed(SpeedProvider provider) 来更改片段的速度:

  val speedProvider = object : SpeedProvider {
    override fun getSpeed(presentationTimeUs: Long): Float {
        return speed
    }

    override fun getNextSpeedChangeTimeUs(timeUs: Long): Long {
        return C.TIME_UNSET
    }
}

EditedMediaItem speedEffectItem = EditedMediaItem.Builder(mediaItem)
    .setSpeed(speedProvider)
    .build()

这种新方法取代了之前使用 Effects#createExperimentalSpeedChangingEffects() 的方法,我们已弃用该方法,并将在未来的版本中移除它。

为 EditedMediaItemSequence 引入了轨道类型

在 1.9.0 版中,EditedMediaItemSequence 要求在创建序列期间指定所需的输出轨道类型。此更改可确保整个 Composition 中的轨道处理更加明确和稳健。

这是通过接受一组轨道类型(例如 C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO)的新 EditedMediaItemSequence.Builder 构造函数完成的。

为了简化创建过程,我们添加了新的静态便捷方法:

  • EditedMediaItemSequence.withAudioFrom(List<EditedMediaItem>)
  • EditedMediaItemSequence.withVideoFrom(List<EditedMediaItem>)
  • EditedMediaItemSequence.withAudioAndVideoFrom(List<EditedMediaItem>)

建议您迁移到新的构造函数或便捷方法,以便更清晰、更可靠地定义序列。

创建纯视频序列的示例:

  EditedMediaItemSequence videoOnlySequence =
    EditedMediaItemSequence.Builder(setOf(C.TRACK_TYPE_VIDEO))
        .addItem(editedMediaItem)
        .build()

如果您遇到任何 bug,或者有任何疑问或功能请求,请通过 Media3 问题跟踪器与我们联系。我们期待您的来信!

继续阅读