호환 미디어 트랜스코딩

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에서는 앱이 모든 미디어 형식의 재생을 지원할 수 있다고 가정하므로 호환 미디어 트랜스코딩이 기본적으로 사용 중지되어 있습니다.

트랜스코딩을 사용해야 하는 경우

트랜스코딩은 계산 비용이 많이 드는 작업이며 동영상 파일을 열 때 상당한 지연이 추가됩니다. 예를 들어 1분 HEVC 동영상 파일은 Pixel 3 휴대전화에서 AVC로 트랜스코딩하는 데 약 20초가 걸립니다. 따라서 기기 외부로 전송할 때만 동영상 파일을 트랜스코딩해야 합니다. 예를 들어 동영상 파일을 같은 앱의 다른 사용자나 최신 동영상 형식을 지원하지 않는 클라우드 서버와 공유하는 경우입니다.

기기에서 재생하거나 썸네일 이미지를 만들려고 동영상 파일을 열 때 트랜스코딩하지 마세요.

트랜스코딩 구성

앱은 미디어 기능을 선언하여 트랜스코딩 동작을 제어할 수 있습니다. 이러한 기능은 두 가지 방법(코드에서 또는 리소스에서)으로 선언할 수 있습니다.

코드에서 기능 선언

빌더를 사용하여 ApplicationMediaCapabilities 객체의 인스턴스를 생성함으로써 코드에서 미디어 기능을 선언할 수 있습니다.

Kotlin

val mediaCapabilities = ApplicationMediaCapabilities.Builder()
    .addSupportedVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC)
    .addUnsupportedHdrType(MediaFeature.HdrType.HDR10)
    .addUnsupportedHdrType(MediaFeature.HdrType.HDR10_PLUS)
    .build()

자바

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를 사용하여 동영상 파일을 열고 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: 동영상 캡처 앱에서 시작된 트랜스코딩예 1 동영상 공유 앱은 미디어 기능 리소스 파일에서 HEVC를 지원하지 않는다고 선언합니다. 그런 다음 동영상 캡처 앱에서 동영상을 요청합니다. 동영상 캡처 앱은 요청을 처리하고 공유 앱의 UID를 지정하는 openTypedAssetFileDescriptor를 사용하여 파일을 엽니다. 그러면 트랜스코딩 프로세스가 시작됩니다. 트랜스코딩된 동영상이 수신되면 공유 앱에 제공되고 앱은 클라우드 서버에 업로드합니다.

예 2: 동영상 공유 앱에서 시작된 트랜스코딩 예 2 동영상 캡처 앱은 MediaStore URI를 사용하여 동영상을 동영상 공유 앱과 공유합니다. 동영상 공유 앱은 미디어 기능에서 HEVC를 지원하지 않는다고 지정하는 openTypedAssetFileDescriptor를 사용하여 동영상 파일을 엽니다. 그러면 트랜스코딩 프로세스가 시작되고 파일이 클라우드 서버에 업로드됩니다.

선언되지 않은 형식

호환 미디어 트랜스코딩은 지원되지 않음으로 선언된 모든 형식에서 사용 설정되고 지원됨으로 선언된 모든 형식에서 사용 중지됩니다. 선언되지 않은 기타 형식의 경우 플랫폼이 트랜스코딩 여부를 판단합니다. Android 12에서 트랜스코딩은 선언되지 않은 모든 형식에서 사용 중지됩니다. 이 동작은 이후 새로운 형식에서 변경될 수 있습니다.

개발자 옵션

다음 개발자 옵션을 사용하여 Android의 기본 트랜스코딩 동작을 재정의할 수 있습니다.

  • 트랜스코딩 기본값 재정의: 이 설정은 플랫폼이 자동 트랜스코딩을 제어하는지 여부를 결정합니다. 재정의를 사용 설정하면 플랫폼 기본값이 무시되고 트랜스코딩 사용 설정 설정이 자동 트랜스코딩을 제어합니다. 이 옵션은 기본적으로 사용 중지되어 있습니다.

  • 트랜스코딩 사용 설정: 이 설정은 선언되지 않은 형식이 자동으로 트랜스코딩되는지 여부를 지정합니다. 기본적으로 사용 설정되어 있지만 트랜스코딩 기본값 재정의도 사용 설정된 경우에만 효과가 있습니다.

  • 앱이 최신 형식을 지원한다고 가정: 이 설정은 앱이 선언되지 않은 형식을 재생하려고 할 때 발생하는 일을 제어합니다. 이는 매니페스트에서 앱이 특정 형식을 지원하는지 여부를 선언하지 않거나 Google에서 서버 측 강제 트랜스코딩 목록에 앱을 추가하지 않은 경우에 발생합니다. 이 설정을 사용 설정하면 앱은 트랜스코딩되지 않고 사용 중지하면 앱이 트랜스코딩됩니다. 이 옵션은 기본적으로 사용 설정됩니다.

  • 트랜스코딩 알림 표시: 이 옵션을 사용 설정하면 지원되지 않는 미디어 파일을 읽어 트랜스코딩이 트리거될 때 앱에 트랜스코딩 진행률 알림이 표시됩니다. 이 옵션은 기본적으로 사용 설정됩니다.

  • 트랜스코딩 캐시 사용 중지: 이 옵션을 사용 설정하면 트랜스코딩이 필요한 앱에서 트랜스코딩 캐시를 사용하지 않습니다. 개발 중에 지원되지 않는 미디어 파일에서 트랜스코딩을 쉽게 트리거하는 데 유용할 수 있지만 기기 성능이 저하될 수 있습니다. 이 옵션은 기본적으로 사용 중지되어 있습니다.