兼容的媒体转码
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
在 Android 12(API 级别 31)及更高版本中,当以 HEVC (H.265) 等格式录制的视频由不支持 HEVC 格式的应用打开时,系统可以自动将其转换为 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 假定应用可以支持播放所有媒体格式,因此兼容的媒体转码在默认情况下处于关闭状态。
何时使用转码
转码是一项计算开销很大的操作,会在打开视频文件时大幅增加延迟。例如,时长为一分钟的 HEVC 视频文件大约需要 20 秒才能在 Pixel 3 手机上转码为 AVC。因此,只有在您要将视频文件从设备上发送出去时,才应对其进行转码。例如,在与同一应用的其他用户或不支持现代视频格式的云服务器共享视频文件时。
打开视频文件以便在设备上播放或创建缩略图时,不要进行转码。
配置转码
应用可以通过声明其媒体功能来控制其转码行为。声明这些功能的方式有两种:在代码中或在资源中。
在代码中声明功能
您可以使用构建器构造 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(可以使用 Binder.getCallingUid
获取该 UID)来处理这种情况。然后,平台会使用接收方应用的媒体功能来确定是否应对视频文件进行转码。
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 尚未将应用添加到服务器端强制转码列表中,就会发生这种情况。启用此设置后,应用不会执行转码操作;停用后,应用会执行转码操作。此选项在默认情况下处于启用状态。
显示转码通知:启用此选项后,因读取不受支持的媒体文件而触发转码时,应用会显示转码进度通知。此选项在默认情况下处于启用状态。
停用转码缓存:如果启用了此选项,则要求转码的应用不使用转码缓存。这在开发过程中会很有用,可以很容易地对不受支持的媒体文件触发转码,但可能会导致设备性能不佳。此选项在默认情况下处于停用状态。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-08-27。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-08-27。"],[],[],null,["On Android 12 (API level 31) and higher, the system can automatically convert\nvideos recorded in formats such as HEVC (H.265) to AVC (H.264) when the videos\nare opened by an app that does not support HEVC. This feature allows video\ncapture apps to utilize more modern, storage-efficient encoding for videos\nrecorded on the device without sacrificing compatibility with other apps.\n\nThe following formats can be automatically transcoded for content that's\ncreated on-device:\n\n| Media format | XML Attribute | MediaFormat mime type |\n|--------------|---------------|---------------------------------|\n| HEVC (H.265) | HEVC | MediaFormat.MIMETYPE_VIDEO_HEVC |\n| HDR10 | HDR10 | MediaFeature.HdrType.HDR10 |\n| HDR10+ | HDR10Plus | MediaFeature.HdrType.HDR10_PLUS |\n\nAndroid assumes that apps can support playback of all media formats, so\ncompatible media transcoding is off by default.\n\nWhen to use transcoding\n\nTranscoding is a computationally expensive operation and adds a significant\ndelay when opening a video file. For example, a one minute HEVC video file takes\nroughly 20 seconds to transcode into AVC on a Pixel 3 phone. For this reason,\nyou should transcode a video file only when you are sending it off the\ndevice. For example, when sharing a video file with other users of the same\napp, or a cloud server which does not support modern video\nformats.\n\nDo not transcode when opening video files for on-device playback or for creating thumbnail images.\n\nConfiguring transcoding\n\nApps can control their transcoding behavior by declaring their media\ncapabilities. There are two ways to declare these capabilities: in code,\nor in a resource.\n\nDeclare capabilities in code\n\nYou can declare media capabilities in code by constructing an instance of an\n`ApplicationMediaCapabilities` object using a builder: \n\nKotlin \n\n```kotlin\nval mediaCapabilities = ApplicationMediaCapabilities.Builder()\n .addSupportedVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC)\n .addUnsupportedHdrType(MediaFeature.HdrType.HDR10)\n .addUnsupportedHdrType(MediaFeature.HdrType.HDR10_PLUS)\n .build()\n```\n\nJava \n\n```java\nApplicationMediaCapabilities mediaCapabilities = new ApplicationMediaCapabilities.Builder()\n .addSupportedVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC)\n .addUnsupportedHdrType(MediaFeature.HdrType.HDR10)\n .addUnsupportedHdrType(MediaFeature.HdrType.HDR10_PLUS)\n .build();\n```\n\nUse this object when accessing media content via methods such as\n`ContentResolver#openTypedAssetFileDescriptor()`: \n\nKotlin \n\n```kotlin\nval providerOptions = Bundle().apply {\n putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES, mediaCapabilities)\n}\ncontentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)\n .use { fileDescriptor -\u003e\n // Content will be transcoded based on values defined in the\n // ApplicationMediaCapabilities provided.\n }\n```\n\nJava \n\n```java\nBundle providerOptions = new Bundle();\nproviderOptions.putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES, mediaCapabilities);\ntry (AssetFileDescriptor fileDescriptor = contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)) {\n // Content will be transcoded based on values defined in the\n // ApplicationMediaCapabilities provided.\n}\n```\n\nThis method allows granular control for particular code paths, such\nas invoking transcoding only when transferring a video file off-device. It takes precedence over the method described below.\n\nDeclare capabilities in a resource\n\nDeclaring capabilities in a resource allows blanket control over transcoding.\nThis method should only be used in very specific cases. For example, if your app\nonly receives video files from other apps (rather than opening them directly)\nand uploads them to a server which does not support modern video codecs (see\nexample scenario 1 below).\n\nUsing this method when not absolutely necessary might invoke transcoding in unintended scenarios, such as when thumbnailing videos, resulting in a degraded user experience.\n\nTo use this method, create a `media_capabilities.xml` resource file: \n\n \u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n \u003cmedia-capabilities xmlns:android=\"http://schemas.android.com/apk/res/android\"\u003e\n \u003cformat android:name=\"HEVC\" supported=\"true\"/\u003e\n \u003cformat android:name=\"HDR10\" supported=\"false\"/\u003e\n \u003cformat android:name=\"HDR10Plus\" supported=\"false\"/\u003e\n \u003c/media-capabilities\u003e\n\nIn this example, HDR videos recorded on the device are seamlessly transcoded to\nAVC SDR (standard dynamic range) video, while HEVC videos are not.\n\nUse a `property` tag within the `application` tag to add a reference to the media\ncapabilities file. Add these properties to your `AndroidManifest.xml` file: \n\n \u003cproperty\n android:name=\"android.media.PROPERTY_MEDIA_CAPABILITIES\"\n android:resource=\"@xml/media_capabilities\" /\u003e\n\nUsing another app's media capabilities to open a video file\n\nIf your app shares a video file with another app, the video file might need to\nbe transcoded before the receiving app can open it.\n\nYou can handle this case by opening a video file using [`openTypedAssetFileDescriptor`](https://developer.android.com/reference/android/content/ContentResolver#openTypedAssetFileDescriptor(android.net.Uri,%20java.lang.String,%20android.os.Bundle))\nand specifying the UID of the receiving app, which can be obtained using [`Binder.getCallingUid`](https://developer.android.com/reference/android/os/Binder#getCallingUid()).\nThe platform then uses the receiving app's media capabilities to determine\nwhether the video file should be transcoded. \n\nKotlin \n\n```kotlin\nval providerOptions = Bundle().apply {\n putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID, Binder.getCallingUid())\n}\ncontentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)\n .use { fileDescriptor -\u003e\n // Content will be transcoded based on the media capabilities of the\n // calling app.\n }\n```\n\nJava \n\n```java\nBundle providerOptions = new Bundle();\nproviderOptions.putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID, Binder.getCallingUid());\ntry (AssetFileDescriptor fileDescriptor = contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)) {\n // Content will be transcoded based on the media capabilities of the\n // calling app.\n}\n```\n\nExample scenarios\n\nThe following diagrams demonstrate the two common use cases. In both cases the original video is stored in HEVC format and the video sharing app does not\nsupport HEVC.\n\n**Example 1.** Transcoding is initiated by video capture app.\n\nThe video sharing app declares that it does not support HEVC in its media\ncapabilities resource file. It then requests a video from the video capture app. The video capture\napp handles the request and opens the file using [`openTypedAssetFileDescriptor`](https://developer.android.com/reference/android/content/ContentResolver#openTypedAssetFileDescriptor(android.net.Uri,%20java.lang.String,%20android.os.Bundle)), specifying the sharing app's UID. This initiates the transcoding process.\nWhen the transcoded video is received it is supplied to the sharing app, which uploads it to a server in the cloud.\n\n**Example 2.** Transcoding is initiated by video sharing app.\n\nThe video capture app shares a video with the video sharing app using a\n`MediaStore` URI. The video sharing app opens the video file using [`openTypedAssetFileDescriptor`](https://developer.android.com/reference/android/content/ContentResolver#openTypedAssetFileDescriptor(android.net.Uri,%20java.lang.String,%20android.os.Bundle)), specifying that it does not support HEVC in its media capabilities. This\ninitiates the transcoding process, and once complete, the file is uploaded to\na server in the cloud.\n\nUndeclared formats\n\nCompatible media transcoding is enabled for all formats that are declared\nunsupported, and is disabled for all formats that are declared supported. For\nother formats that are not declared, the platform decides whether to transcode\nor not. In Android 12 transcoding is disabled\nfor all undeclared formats. This behavior might change for new formats in the\nfuture.\n\nDeveloper options\n\nYou can use the following developer options to override Android's default\ntranscoding behavior:\n\n- **Override transcoding defaults** This setting determines whether or not\n the platform controls automatic transcoding. When override\n is enabled, the platform defaults are ignored and the **enable\n transcoding** setting controls automatic transcoding. This option is disabled by\n default.\n\n- **Enable transcoding** This setting specifies whether or not undeclared\n formats are automatically transcoded. It is enabled by default, but it only\n has an effect if **override transcoding defaults** is also enabled.\n\n- **Assume apps support modern formats** This setting controls what happens when\n the app tries to play an undeclared format. This happens when the manifest does\n not declare whether or not the app supports a particular format, or Google\n hasn't added the app to the server-side force-transcode list. When the setting\n is enabled, the app does not transcode, when it's disabled, the app does\n transcode. This option is enabled by default.\n\n- **Show transcoding notifications** When enabled, the app displays a\n transcoding progress notification when transcoding is triggered by reading an\n unsupported media file. This option is enabled by default.\n\n- **Disable transcoding cache** If enabled, apps that require transcoding do not\n use the transcoding cache. This can be helpful during development to easily\n trigger transcoding on an unsupported media file, but can cause poor device\n performance. This option is disabled by default."]]