在 Android 12(API 级别 31)及更高版本中,当不支持 HEVC 的应用打开以 HEVC (H.265) 等格式录制的视频时,系统可以自动将其转换为 AVC (H.264)。此功能允许视频捕获应用对设备上录制的视频使用更现代、更节省存储空间的编码,同时不牺牲与其他应用的兼容性。
以下格式可以对设备上创建的内容进行自动转码
媒体格式 | XML 属性 | MediaFormat mime 类型 |
---|---|---|
HEVC (H.265) | HEVC | MediaFormat.MIMETYPE_VIDEO_HEVC |
HDR10 | HDR10 | MediaFeature.HdrType.HDR10 |
HDR10+ | HDR10Plus | MediaFeature.HdrType.HDR10_PLUS |
Android 假定应用可以支持所有媒体格式的播放,因此兼容媒体转码默认处于关闭状态。
何时使用转码
转码是计算密集型操作,会在打开视频文件时增加显著的延迟。例如,在 Pixel 3 手机上,一分钟的 HEVC 视频文件转码为 AVC 大约需要 20 秒。因此,您只应在将视频文件发送出设备时才进行转码。例如,当与同一应用的其他用户或不支持现代视频格式的云服务器共享视频文件时。
在打开视频文件进行设备上播放或创建缩略图时,请勿进行转码。
配置转码
应用可以通过声明其媒体能力来控制其转码行为。声明这些能力有两种方式:在代码中声明或在资源中声明。
在代码中声明能力
您可以通过构建 ApplicationMediaCapabilities
对象实例在代码中声明媒体能力
Kotlin
val mediaCapabilities = ApplicationMediaCapabilities.Builder() .addSupportedVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC) .addUnsupportedHdrType(MediaFeature.HdrType.HDR10) .addUnsupportedHdrType(MediaFeature.HdrType.HDR10_PLUS) .build()
Java
ApplicationMediaCapabilities mediaCapabilities = new ApplicationMediaCapabilities.Builder() .addSupportedVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC) .addUnsupportedHdrType(MediaFeature.HdrType.HDR10) .addUnsupportedHdrType(MediaFeature.HdrType.HDR10_PLUS) .build();
通过 ContentResolver#openTypedAssetFileDescriptor()
等方法访问媒体内容时,请使用此对象
Kotlin
val providerOptions = Bundle().apply { putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES, mediaCapabilities) } contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions) .use { fileDescriptor -> // Content will be transcoded based on values defined in the // ApplicationMediaCapabilities provided. }
Java
Bundle providerOptions = new Bundle(); providerOptions.putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES, mediaCapabilities); try (AssetFileDescriptor fileDescriptor = contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)) { // Content will be transcoded based on values defined in the // ApplicationMediaCapabilities provided. }
此方法允许对特定代码路径进行细粒度控制,例如仅在将视频文件传出设备时才调用转码。它优先于下面描述的方法。
在资源中声明能力
在资源中声明能力可以实现对转码的全面控制。此方法仅应在非常特殊的情况下使用。例如,如果您的应用只从其他应用接收视频文件(而不是直接打开),并将其上传到不支持现代视频编解码器的服务器(请参阅下面的场景示例 1)。
在并非绝对必要的情况下使用此方法可能会在意外场景中调用转码,例如在创建视频缩略图时,从而导致用户体验下降。
要使用此方法,请创建 media_capabilities.xml
资源文件
<?xml version="1.0" encoding="utf-8"?>
<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
<format android:name="HEVC" supported="true"/>
<format android:name="HDR10" supported="false"/>
<format android:name="HDR10Plus" supported="false"/>
</media-capabilities>
在此示例中,设备上录制的 HDR 视频被无缝转码为 AVC SDR(标准动态范围)视频,而 HEVC 视频则不会。
在 application
标签中使用 property
标签添加对媒体能力文件的引用。将这些属性添加到您的 AndroidManifest.xml
文件中
<property
android:name="android.media.PROPERTY_MEDIA_CAPABILITIES"
android:resource="@xml/media_capabilities" />
使用另一个应用的媒体能力打开视频文件
如果您的应用与其他应用共享视频文件,该视频文件可能需要在接收应用打开它之前进行转码。
您可以通过使用 openTypedAssetFileDescriptor
打开视频文件并指定接收应用的 UID 来处理这种情况,该 UID 可以通过 Binder.getCallingUid
获取。然后平台会使用接收应用的媒体能力来确定是否应该对视频文件进行转码。
Kotlin
val providerOptions = Bundle().apply { putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID, Binder.getCallingUid()) } contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions) .use { fileDescriptor -> // Content will be transcoded based on the media capabilities of the // calling app. }
Java
Bundle providerOptions = new Bundle(); providerOptions.putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID, Binder.getCallingUid()); try (AssetFileDescriptor fileDescriptor = contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)) { // Content will be transcoded based on the media capabilities of the // calling app. }
场景示例
以下图表演示了两种常见的用例。在这两种情况下,原始视频都以 HEVC 格式存储,并且视频共享应用不支持 HEVC。
示例 1。 转码由视频捕获应用发起。 视频共享应用在其媒体能力资源文件中声明不支持 HEVC。然后它从视频捕获应用请求一个视频。视频捕获应用处理该请求,并使用
openTypedAssetFileDescriptor
打开文件,并指定共享应用的 UID。这会启动转码过程。当转码后的视频收到后,它会提供给共享应用,共享应用将其上传到云服务器。
示例 2。 转码由视频共享应用发起。 视频捕获应用使用
MediaStore
URI 与视频共享应用共享视频。视频共享应用使用 openTypedAssetFileDescriptor
打开视频文件,并指定其媒体能力中不支持 HEVC。这会启动转码过程,完成后文件将上传到云服务器。
未声明的格式
兼容媒体转码对于所有声明为不支持的格式都启用,对于所有声明为支持的格式都禁用。对于其他未声明的格式,平台决定是否进行转码。在 Android 12 中,所有未声明的格式都禁用了转码。此行为未来可能会针对新格式发生变化。
开发者选项
您可以使用以下开发者选项来覆盖 Android 的默认转码行为
覆盖转码默认设置 此设置决定平台是否控制自动转码。启用覆盖时,平台默认设置将被忽略,并且启用转码设置控制自动转码。此选项默认禁用。
启用转码 此设置指定是否自动转码未声明的格式。它默认启用,但仅当覆盖转码默认设置也启用时才有效。
假设应用支持现代格式 此设置控制当应用尝试播放未声明的格式时会发生什么。这发生在清单未声明应用是否支持特定格式,或者 Google 未将应用添加到服务器端强制转码列表时。当此设置启用时,应用不会进行转码;当它禁用时,应用会进行转码。此选项默认启用。
显示转码通知 启用此选项后,当读取不支持的媒体文件触发转码时,应用会显示转码进度通知。此选项默认启用。
禁用转码缓存 如果启用,需要转码的应用将不使用转码缓存。这在开发过程中有助于轻松触发不支持媒体文件的转码,但可能会导致设备性能不佳。此选项默认禁用。