Transcodierung in kompatibles Medienformat

Unter Android 12 (API-Level 31) und höher kann das System Videos, die in Formaten wie HEVC (H.265) aufgenommen wurden, automatisch in AVC (H.264) konvertieren, wenn die Videos in einer App geöffnet werden, die HEVC nicht unterstützt. Mit dieser Funktion können Apps zur Videoaufnahme eine modernere, speichereffizientere Codierung für auf dem Gerät aufgenommene Videos verwenden, ohne die Kompatibilität mit anderen Apps zu beeinträchtigen.

Die folgenden Formate können für auf dem Gerät erstellte Inhalte automatisch transcodiert werden:

Medienformat XML-Attribut MIME-Typ von MediaFormat
HEVC (H.265) HEVC MediaFormat.MIMETYPE_VIDEO_HEVC
HDR10HDR10 MediaFeature.HdrType.HDR10
HDR10+ HDR10Plus MediaFeature.HdrType.HDR10_PLUS

Android geht davon aus, dass Apps die Wiedergabe aller Medienformate unterstützen. Daher ist die Transcodierung kompatibler Medien standardmäßig deaktiviert.

Wann sollte Transcodierung verwendet werden?

Die Transcodierung ist ein rechenintensiver Vorgang und führt zu einer erheblichen Verzögerung beim Öffnen einer Videodatei. Beispiel: Die Transkodierung einer HEVC-Videodatei mit einer Länge von einer Minute in AVC dauert auf einem Pixel 3 etwa 20 Sekunden. Aus diesem Grund sollten Sie eine Videodatei nur dann transkodieren, wenn Sie sie vom Gerät senden. Das ist beispielsweise der Fall, wenn Sie eine Videodatei für andere Nutzer derselben App oder für einen Cloud-Server freigeben, der moderne Videoformate nicht unterstützt.

Verwenden Sie die Transcodierung nicht, wenn Sie Videodateien für die Wiedergabe auf dem Gerät oder zum Erstellen von Miniaturansichten öffnen.

Transcodierung konfigurieren

Apps können ihr Transcodierungsverhalten steuern, indem sie ihre Medienfunktionen angeben. Es gibt zwei Möglichkeiten, diese Funktionen zu deklarieren: im Code oder in einer Ressource.

Funktionen im Code deklarieren

Sie können Medienfunktionen im Code deklarieren, indem Sie mit einem Builder eine Instanz eines ApplicationMediaCapabilities-Objekts erstellen:

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();

Verwende dieses Objekt, wenn du über Methoden wie die folgenden auf Medieninhalte zugreifst: 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.
}

Mit dieser Methode lässt sich die Verarbeitung bestimmter Codepfade genau steuern, z. B. das Transcodieren nur bei der Übertragung einer Videodatei außerhalb des Geräts. Sie hat Vorrang vor der unten beschriebenen Methode.

Funktionen in einer Ressource angeben

Wenn du Funktionen in einer Ressource deklarierst, kannst du die Transcodierung umfassend steuern. Diese Methode sollte nur in ganz bestimmten Fällen verwendet werden. Das ist beispielsweise der Fall, wenn Ihre App Videodateien nur von anderen Apps empfängt (anstatt sie direkt zu öffnen) und sie auf einen Server hochlädt, der keine modernen Videocodecs unterstützt (siehe Beispielszenario 1 unten).

Wenn du diese Methode nicht unbedingt verwendest, kann es zu unerwünschten Transcodierungsszenarien kommen, z. B. beim Erstellen von Video-Thumbnails. Das beeinträchtigt die Nutzerfreundlichkeit.

Wenn Sie diese Methode verwenden möchten, erstellen Sie eine media_capabilities.xml-Ressourcendatei:

<?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>

In diesem Beispiel werden auf dem Gerät aufgenommene HDR-Videos nahtlos in AVC-SDR-Videos (Standard Dynamic Range) transkodiert, HEVC-Videos hingegen nicht.

Verwende ein property-Tag innerhalb des application-Tags, um einen Verweis auf die Datei mit den Medienfunktionen hinzuzufügen. Fügen Sie der Datei AndroidManifest.xml die folgenden Attribute hinzu:

<property
    android:name="android.media.PROPERTY_MEDIA_CAPABILITIES"
    android:resource="@xml/media_capabilities" />

Videodateien mit den Medienfunktionen einer anderen App öffnen

Wenn Ihre App eine Videodatei für eine andere App freigibt, muss die Videodatei möglicherweise transkodiert werden, bevor die Empfänger-App sie öffnen kann.

Öffnen Sie dazu eine Videodatei mit openTypedAssetFileDescriptor und geben Sie die UID der empfangenden App an. Diese können Sie mit Binder.getCallingUid abrufen. Die Plattform verwendet dann die Medienfunktionen der empfangenden App, um zu bestimmen, ob die Videodatei transkodiert werden soll.

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.
}

Beispielszenarien

Die folgenden Diagramme veranschaulichen die beiden gängigen Anwendungsfälle. In beiden Fällen wird das Originalvideo im HEVC-Format gespeichert und die Video-Sharing-App unterstützt HEVC nicht.

Beispiel 1 Das Transcodieren wird von der Videoaufnahme-App initiiert. Beispiel 1 Die Video-Sharing-App gibt in ihrer Ressourcendatei für Medienfunktionen an, dass sie HEVC nicht unterstützt. Die App fordert dann ein Video von der Videoaufzeichnungs-App an. Die Videoaufzeichnungs-App verarbeitet die Anfrage und öffnet die Datei mit openTypedAssetFileDescriptor, wobei die UID der App für die Freigabe angegeben wird. Dadurch wird der Transcodierungsvorgang gestartet. Nach dem Empfang wird das transcodierte Video an die Freigabe-App gesendet, die es auf einen Server in der Cloud hochlädt.

Beispiel 2 Das Transcodieren wird von der Video-Sharing-App initiiert. Beispiel 2 Die Videoaufzeichnungs-App teilt ein Video über einen MediaStore-URI mit der Video-Sharing-App. Die Video-Sharing-App öffnet die Videodatei mit openTypedAssetFileDescriptor und gibt an, dass sie HEVC nicht in ihren Medienfunktionen unterstützt. Dadurch wird der Transcodierungsprozess gestartet. Nach Abschluss wird die Datei auf einen Server in der Cloud hochgeladen.

Nicht deklarierte Formate

Die kompatible Medientranscodierung ist für alle Formate aktiviert, die als nicht unterstützt deklariert sind, und für alle Formate deaktiviert, die als unterstützt deklariert sind. Bei anderen nicht deklarierten Formaten entscheidet die Plattform, ob eine Transcodierung durchgeführt wird. In Android 12 ist die Transcodierung für alle nicht deklarierten Formate deaktiviert. Dieses Verhalten kann sich für neue Formate in Zukunft ändern.

Entwickleroptionen

Mit den folgenden Entwickleroptionen können Sie das Standardtranscodierungsverhalten von Android überschreiben:

  • Standardeinstellungen für Transcodierung überschreiben: Mit dieser Einstellung legen Sie fest, ob die automatische Transcodierung von der Plattform gesteuert wird. Wenn die Überschreibung aktiviert ist, werden die Standardeinstellungen der Plattform ignoriert und die automatische Transcodierung wird über die Einstellung Transcodierung aktivieren gesteuert. Diese Option ist standardmäßig deaktiviert.

  • Transcodierung aktivieren: Diese Einstellung gibt an, ob nicht deklarierte Formate automatisch transcodiert werden. Sie ist standardmäßig aktiviert, hat aber nur dann eine Auswirkung, wenn auch Transcodierungsstandardwerte überschreiben aktiviert ist.

  • Annehmen, dass Apps moderne Formate unterstützen: Mit dieser Einstellung wird festgelegt, was passiert, wenn die App versucht, ein nicht deklariertes Format abzuspielen. Das passiert, wenn im Manifest nicht angegeben ist, ob die App ein bestimmtes Format unterstützt, oder wenn Google die App nicht der Liste der serverseitigen erzwungenen Transcodierung hinzugefügt hat. Wenn die Einstellung aktiviert ist, wird in der App nicht transkodiert. Ist sie deaktiviert, erfolgt eine Transkodierung. Diese Option ist standardmäßig aktiviert.

  • Benachrichtigungen zur Transcodierung anzeigen: Wenn diese Option aktiviert ist, wird in der App eine Benachrichtigung zum Transcodierungsfortschritt angezeigt, wenn die Transcodierung durch das Lesen einer nicht unterstützten Mediendatei ausgelöst wird. Diese Option ist standardmäßig aktiviert.

  • Cache für Transcodierung deaktivieren: Wenn diese Option aktiviert ist, wird der Cache für Transcodierung nicht von Apps verwendet, für die eine Transcodierung erforderlich ist. Das kann während der Entwicklung hilfreich sein, um die Transcodierung einer nicht unterstützten Mediendatei ganz einfach auszulösen. Es kann jedoch zu einer schlechten Geräteleistung führen. Diese Option ist standardmäßig deaktiviert.