Media3 1.9.0 现已发布!除了常规的问题修复和性能改进之外,最新版本还包含四个全新或经过大幅重写的模块:
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 和本地播放之间的转换
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()
}
Media3 会话演示应用中新增了 CastPlayer 集成
基于 dav1d 重写的扩展程序,可实现一致的 AV1 播放
1.9.0 版本包含一个完全重写的 AV1 扩展模块,该模块基于热门的 dav1d 库。
与所有扩展解码器模块一样,请注意,它需要从源代码构建 才能正确捆绑相关原生代码。捆绑解码器可在所有设备上提供一致性和格式支持,但由于它在您的进程中运行解码,因此最适合您信任的内容。
将缓存和内存管理集成到 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 并分享您的反馈,同时请留意即将发布的帖子和文档更新,了解更多详情。
在 Transformer 中将 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 问题跟踪器与我们联系。我们期待您的加入!
-
产品资讯随着智能体开发不断加速,Android 工程领域正迈向一个令人振奋的新境界:从辅助性代码补全,跃升至智能体在您的指挥下执行端到端任务。您可以完全自主、灵活地选择要使用的模型和智能体。
Jason Buchel • 阅读用时:3 分钟 -
产品资讯今天,我们分享了如何将“不只是商店”的愿景推进到下一个阶段。从月活跃用户数超过 2.5 亿的“我”标签页,到连接超过 7 亿玩家资料的统一游戏平台,Google Play 始终致力于满足用户的各种需求。
Paul Feng • 阅读用时:3 分钟 -
产品资讯我们很高兴能通过 Googlebook 帮助用户表达自我,并让他们能够使用这些工具。
Cyrus Stoller • 阅读用时:2 分钟
每周通过电子邮件接收最新的 Android 开发洞见。