Media3 1.9.0 已发布!除了修复一些常见 bug 和提升性能之外,最新版本还包含 4 个 新模块或经过大幅重写的模块:
media3-inspector- 在播放之外提取元数据和帧media3-ui-compose-material3- 只需几个步骤即可构建基本的 Material3 Compose 媒体界面media3-cast- 自动处理 Cast 播放和本地播放之间的转换media3-decoder-av1- 使用基于 dav1d 库重写的扩展解码器实现一致的 AV1 播放
我们还为 PreloadManager 添加了缓存和内存管理方面的改进,并提供了多个新的 ExoPlayer、Transformer 和 MediaSession 简化功能。
在此版本中,您还可以首次以实验方式访问 CompositionPlayer,以预览媒体编辑内容。
请继续阅读以了解详情,并像往常一样查看完整的版本说明,全面了解此版本中的变化。
在播放之外提取元数据和帧
在许多情况下,您可能需要在不开始播放的情况下检查媒体。例如,您可能需要检测媒体包含哪些格式或时长是多少,或者检索缩略图。
新的 media3-inspector 模块将所有用于在不播放的情况下检查媒体的实用程序整合到一处:
MetadataRetriever,用于从MediaItem中读取时长、格式和静态元数据。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 界面元素与 Player 实例之间的连接器代码。在 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)
}
}
}
具有开箱即用元素的简单 Compose 播放器界面
自动处理 Cast 播放和本地播放之间的转换
CastPlayer 在 media3-cast 模块中经过重写,可自动处理本地播放(例如使用 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()
}
Media3 会话演示版应用中的新 CastPlayer 集成
使用基于 dav1d 重写的扩展实现一致的 AV1 播放
1.9.0 版本包含一个基于热门 dav1d 库完全重写的 AV1 扩展模块。
与所有扩展解码器模块一样,请注意,它需要从源代码构建 才能正确捆绑相关原生代码。捆绑解码器可在所有设备上提供一致性和格式支持,但由于它会在您的进程中运行解码,因此最适合您信任的内容。
将缓存和内存管理集成到 PreloadManager 中
我们还改进了 PreloadManager。它已经支持您在播放之外将媒体预加载到内存中,然后在需要时无缝地将其交给播放器。虽然性能相当不错,但您仍然需要小心,避免因意外预加载过多而超出内存限制。因此,在 Media3 1.9.0 中,我们添加了两项功能,让此过程变得更加轻松和稳定:
- 缓存支持 – 在定义预加载的范围时,您现在可以选择
PreloadStatus.specifiedRangeCached(0, 5000)作为预加载项的目标状态。这会将指定的范围添加到磁盘上的缓存中,而不是将数据加载到内存中。这样一来,您可以提供更大的预加载项范围,因为距离当前项较远的项不再需要占用内存。请注意,这需要在DefaultPreloadManager.Builder中设置Cache。 - 自动内存管理 – 我们还更新了
LoadControl接口,以便更好地处理预加载情况,因此您现在可以为内存中的所有预加载项设置明确的内存上限。默认值为 144 MB,您可以在DefaultLoadControl.Builder中配置该限制。DefaultPreloadManager会在达到限制后自动停止预加载,并在需要时自动释放优先级较低的项的内存。
依赖 ExoPlayer 中新的简化默认行为
与往常一样,我们还对 ExoPlayer 进行了许多增量改进。仅举几例:
- 静音和取消静音 – 我们已经有一个
setVolume方法,但现在添加了便捷的mute和unmute方法,以便轻松恢复之前的音量,而无需自行跟踪。 - 卡顿播放器检测 \- 在某些罕见情况下,播放器可能会卡在缓冲或播放状态,而没有任何进展,例如,由于编解码器问题或配置错误。您的用户会感到恼火,但您在分析中永远看不到这些问题!为了让这一点更加明显,播放器现在会在检测到卡顿状态时报告
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()
))
具有快进按钮的媒体按钮偏好设置
CompositionPlayer,用于实时预览
1.9.0 版本在新的 @ExperimentalApi 注解下引入了 CompositionPlayer。该注解表示它可用于实验,但仍处于开发阶段。
CompositionPlayer 是 Media3 编辑 API 中的一个新组件,专为实时预览媒体编辑内容而设计。CompositionPlayer 基于熟悉的 Media3 Player 接口构建,允许用户在提交导出流程之前查看更改效果。它使用与您传递给 Transformer 以进行导出的 Composition 对象相同,通过统一预览和导出的数据模型来简化编辑工作流。
我们建议您开始使用 CompositionPlayer 并分享 您的反馈,并密切关注即将发布的博文和文档更新,以了解更多详情。
InAppMuxer 作为 Transformer 中的默认多路复用器
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 问题跟踪器与我们联系。我们期待您的加入!
继续阅读
-
产品动态
我们很高兴地宣布,Android XR 现已正式支持 Unreal Engine 和 Godot。我们还推出了旨在提高您的工作效率并启用新的 XR 功能的新工具:Android XR Engine Hub 和 Android XR Interaction Framework。
Luke Hopkins • 4 分钟阅读时间
-
产品动态
随着 Android 17 的发布,我们将过渡到自适应优先开发标准。您的用户不再依赖于单一的设备形态;他们会在手机、可折叠设备、平板电脑、笔记本电脑、汽车显示屏和沉浸式 XR 环境之间切换。
Fahd Imtiaz • 4 分钟阅读时间
-
产品动态
我们很高兴分享 Google TV 功能和开发者工具,这些功能和工具旨在提高您的内容的可发现性,并为您的应用做好准备,以适应未来的电视体验。
Paul Lammertsma • 4 分钟阅读时间
随时了解最新动态
每周通过电子邮件接收最新的 Android 开发洞见 每周。