Zwischen Formaten transcodieren
Sie können die Audio- und Videoausgabeformate angeben, die beim Erstellen von Transformer generiert werden sollen. Im folgenden Codebeispiel wird gezeigt, wie Transformer für die Ausgabe von H.264/AVC-Video und AAC-Audio konfiguriert wird:
Kotlin
Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H264) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build()
Java
new Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H264) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build();
Wenn das Eingabemedienformat bereits den Konfigurationen für Audio oder Video entspricht, wechselt Transformer automatisch zum Transmuxing. Dabei werden die komprimierten Samples aus dem Eingabecontainer ohne Änderungen in den Ausgabecontainer kopiert. So werden die Rechenkosten und der potenzielle Qualitätsverlust durch das Decodieren und erneute Codieren im selben Format vermieden.
Audio oder Video entfernen
Audio oder Video mit EditedMediaItem.Builder
entfernen, z. B.:
Kotlin
EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()
Java
new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();
Clip zuschneiden
Sie können alle Media außerhalb der angegebenen Start- und Endzeitstempel entfernen, indem Sie die Clipping-Konfiguration für das Eingabe-Media-Element festlegen. Wenn Sie beispielsweise einen Clip erstellen möchten, der nur die Media zwischen 10 und 20 Sekunden enthält:
Kotlin
val inputMediaItem = MediaItem.Builder() .setUri(uri) .setClippingConfiguration( ClippingConfiguration.Builder() .setStartPositionMs(10_000) .setEndPositionMs(20_000) .build()) .build()
Java
MediaItem inputMediaItem = new MediaItem.Builder() .setUri(uri) .setClippingConfiguration( new MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(10_000) .setEndPositionMs(20_000) .build()) .build();
MP4-Bearbeitungslisten
Für ein schnelleres Zuschneiden unterstützt Transformer MP4-Bearbeitungslisten, die effizientere „Nur zuschneiden“-Bearbeitungen ohne vollständige Videotranskodierung ermöglichen. Bei dieser Methode werden vorhandene codierte Samples und ein „Pre-Roll“ in der Bearbeitungsliste verwendet, wodurch der Player angewiesen wird, die Wiedergabe an einem bestimmten Punkt zu starten und so das unerwünschte Anfangssegment zu überspringen.
Wenn Sie nur Zuschnittbearbeitungen deutlich schneller vornehmen möchten, rufen Sie experimentalSetMp4EditListTrimEnabled(true)
auf.
Kotlin
Transformer.Builder(context) .experimentalSetMp4EditListTrimEnabled(true) .build()
Java
new Transformer.Builder(context) .experimentalSetMp4EditListTrimEnabled(true) .build();
Nicht alle Media-Player unterstützen die Position „Pre-Roll“. Wenn ein solcher Player verwendet wird, beginnt die Wiedergabe der Datei also immer am absoluten Anfang des codierten Samples, unabhängig von Informationen in der Bearbeitungsliste, die einen anderen Startpunkt angeben.
Trims optimieren
Wenn Sie die Latenz beim Zuschneiden des Anfangs eines Videos reduzieren möchten, aktivieren Sie die Zuschneideoptimierung.
Kotlin
Transformer.Builder(context) .experimentalSetTrimOptimizationEnabled(true) .build()
Java
new Transformer.Builder(context) .experimentalSetTrimOptimizationEnabled(true) .build();
Dadurch wird der Export beschleunigt, da so wenig wie möglich vom Video decodiert und neu codiert werden muss. Die neu codierten Daten werden dann mit dem Rest des Originalvideos zusammengefügt. Die Optimierung basiert darauf, dass ein Teil der Eingabedatei mit neu codierter Ausgabe zusammengefügt werden kann. Das bedeutet, dass das Ausgabeformat des Encoders und das Eingabeformat kompatibel sein müssen. Wenn die Datei beispielsweise ursprünglich auf einem Gerät mit einer anderen Encoder-Implementierung erstellt wurde, ist es wahrscheinlich, dass die Optimierung nicht angewendet werden kann.
Damit die Optimierung erfolgreich ist, muss der Encoder, der Transformer über EncoderFactory
bereitgestellt wird, ein mit dem Eingabeformat kompatibles Level und Profil haben.
Diese Optimierung funktioniert nur mit MP4-Eingaben mit einem einzelnen Asset ohne Effekte, mit Ausnahme von No-Op-Videoeffekten und Rotationen, die durch 90 Grad teilbar sind. Wenn die Optimierung fehlschlägt, wird automatisch der normale Export verwendet und das Ergebnis der Optimierung wird in ExportResult.OptimizationResult
gemeldet.
Wir prüfen diese Funktion und gehen davon aus, dass sie in einer späteren Version nicht mehr als experimentell gekennzeichnet sein wird.
Videobearbeitung
EditedMediaItems
haben Listen von Audio- und Videoprozessoren, die in der richtigen Reihenfolge angewendet werden müssen. Die Bibliothek enthält Implementierungen von Videoeffekten für gängige Anwendungsfälle. Sie können aber auch benutzerdefinierte Effekte schreiben und sie beim Erstellen bearbeiteter Media-Elemente übergeben.
Sie können Medien neu skalieren, was hilfreich sein kann, um Verarbeitungsressourcen oder Bandbreite zu sparen, wenn Sie es mit Eingaben in sehr hoher Auflösung wie 4K- oder 8K-Videos zu tun haben. Beispiel: So skalieren Sie proportional auf eine Höhe von 480 Pixeln:
Kotlin
EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf(Presentation.createForHeight(480)) )).build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of(Presentation.createForHeight(480)))) .build();
Alternativ können Sie die Größe auch mit einem bestimmten Faktor skalieren, z. B. um sie zu halbieren:
Kotlin
val editedMediaItem = EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf( ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build()) )).build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of( new ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build()))) .build();
Sie können die Rotation auf dieselbe Weise konfigurieren:
Kotlin
EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(Effects( /* audioProcessors= */ listOf(), /* videoEffects= */ listOf( ScaleAndRotateTransformation.Builder() .setRotationDegrees(90f) .build()) )).build()
Java
new EditedMediaItem.Builder(MediaItem.fromUri(uri)) .setEffects(new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ ImmutableList.of( new ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build()))) .build();
Benutzerdefinierte Videoeffekte
Der Effects
-Konstruktor akzeptiert eine Liste von Audio- und Videoeffekten, die angewendet werden sollen.
Intern wandelt das Effects-Framework von Transformer die Liste der Videoeffekte in eine Sequenz von GL-Shader-Programmen um, die in der Reihenfolge angewendet werden. In einigen Fällen kann das Effects-Framework mehrere Effekte mit einem Shader-Programm anwenden.
So kann ein Shader-Programm beispielsweise mehrere aufeinanderfolgende Matrix-Transformationen anwenden, was die Effizienz und Qualität verbessert.
Videoeffekte werden auch für die Vorschau in ExoPlayer unterstützt. Dazu wird ExoPlayer.setVideoEffects
verwendet. Ein Beispiel für die Verwendung dieser API finden Sie in der Demo-App für Effekte.
Die Demo-App enthält Beispiele für benutzerdefinierte Videoeffekte.
Audiobearbeitung
Audioeffekte werden durch Anwenden einer Sequenz von AudioProcessor
-Instanzen auf rohes (PCM-)Audio implementiert. ExoPlayer unterstützt die Übergabe von Audioprozessoren an DefaultAudioSink.Builder
, was die Vorschau von Audiobearbeitungen ermöglicht.