相容媒體轉碼

在 Android 12 (API 級別 31) 以上版本中,當不支援 HEVC 的應用程式開啟影片時,系統可將採用 HEVC (H.265) 格式錄製的影片自動轉換為 AVC (H.264)。這項功能可讓影片擷取應用程式針對裝置上錄製的影片使用更新型且高效儲存的編碼,同時兼顧與其他應用程式的相容性。

系統可以針對在裝置端建立的內容自動轉碼下列格式:

媒體格式 XML 屬性 MediaFormat MIME 類型
HEVC (H.265) HEVC 模式 MediaFormat.MIMETYPE_VIDEO_HEVC
HDR10HDR10 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 取得。平台隨後就會使用接收應用程式的媒體功能,判斷影片檔案是否應轉碼。

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:轉碼是由影片擷取應用程式啟動。 示例 1 影片分享應用程式宣告其媒體功能資源檔案中不支援 HEVC。接著,系統會從影片擷取應用程式要求影片。影片擷取應用程式會處理要求,並使用 openTypedAssetFileDescriptor 指定共用應用程式的 UID。這樣做會啟動轉碼程序。收到轉碼後的影片之後,系統會將其提供給分享應用程式,該應用程式則會上傳到雲端的伺服器。

範例 2:轉碼是由影片分享應用程式啟動。 示例 2 影片擷取應用程式會使用 MediaStore URI 與影片分享應用程式分享影片。影片分享應用程式會使用 openTypedAssetFileDescriptor 開啟影片檔案,並指定其媒體功能不支援 HEVC。這個動作會啟動轉碼程序,完成後,檔案會上傳到雲端的伺服器。

未宣告的格式

所有宣告不支援的格式都會啟用相容媒體轉碼,而且針對宣告的所有格式會停用此功能。至於其他未宣告的格式,平台會決定是否轉碼。在 Android 12 中,所有未宣告的格式都會停用轉碼功能。未來,新格式的行為可能會改變。

開發人員選項

您可以使用下列開發人員選項覆寫 Android 的預設轉碼行為:

  • 覆寫轉碼預設值:這項設定可決定平台是否控制自動轉碼。啟用覆寫功能時,系統會忽略平台預設值,而「啟用轉碼」設定則會控制自動轉碼。這個選項預設為停用。

  • 啟用轉碼這項設定可指定是否要自動轉碼未宣告的格式。此選項預設為啟用,但只有在同時啟用覆寫轉碼預設值時才會生效。

  • 假設應用程式支援新格式:這項設定可控制應用程式嘗試播放未宣告格式時的行為。如果資訊清單未宣告應用程式是否支援特定格式,或 Google 尚未將應用程式加入伺服器端的強制轉碼清單,就會發生這種情況。啟用這項設定時,應用程式不會轉碼。如果停用,應用程式就不會進行轉碼。這個選項預設為啟用。

  • 顯示轉碼通知:啟用這項功能後,當系統讀取不支援的媒體檔案並觸發轉碼時,應用程式會顯示轉碼進度通知。這個選項預設為啟用。

  • 停用轉碼快取:啟用後,需要轉碼的應用程式就不會使用轉碼快取。如要在開發期間輕鬆觸發不支援的媒體檔案轉碼,可能會導致裝置效能不佳。這個選項預設為停用。