Die Transformer-APIs in Jetpack Media3 ermöglichen die Bearbeitung von Medien und zuverlässig sind. Transformer unterstützt eine Reihe von Vorgängen, einschließlich:
- Videos durch Zuschneiden, Skalieren und Drehen bearbeiten
- Effekte wie Overlays und Filter hinzufügen
- Verarbeitung von Spezialformaten wie HDR und Zeitlupenvideo
- Medienelement nach dem Übernehmen von Änderungen exportieren
Auf dieser Seite werden einige der wichtigsten Anwendungsfälle Transformator. Weitere Informationen finden Sie in unseren vollständigen Leitfäden Media3 Transformer:
Erste Schritte
Fügen Sie zuerst eine Abhängigkeit für die Module Transformer, Effect und Common hinzu von Jetpack Media3:
implementation "androidx.media3:media3-transformer:1.4.1" implementation "androidx.media3:media3-effect:1.4.1" implementation "androidx.media3:media3-common:1.4.1"
Ersetzen Sie 1.4.1
durch Ihre bevorzugte Version des
Bibliothek. Weitere Informationen finden Sie in den
Versionshinweise
um die neueste Version zu sehen.
Wichtige Kurse
Klasse | Zweck |
---|---|
Transformer |
Transformationen starten und stoppen und Statusaktualisierungen für eine laufende Transformation prüfen. |
EditedMediaItem |
Stellt ein zu verarbeitendes Medienelement und die darauf anzuwendenden Änderungen dar. |
Effects |
Eine Sammlung von Audio- und Videoeffekten. |
Ausgabe konfigurieren
Mit Transformer.Builder
können Sie jetzt videoMimeType
und
audioMimetype
erstellen, indem Sie die Funktion festlegen, ohne ein
TransformationRequest
-Objekt.
Zwischen Formaten transcodieren
Der folgende Code zeigt, wie ein Transformer
-Objekt konfiguriert wird, um
H.265/AVC-Video und AAC-Audio:
Kotlin
val transformer = Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H265) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build()
Java
Transformer transformer = new Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H265) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build();
Wenn das Eingabemedienformat bereits mit der Transformationsanfrage für Audio übereinstimmt oder Videos übertragen, wechselt Transformer automatisch zu Transmuxing, d. h. vom Eingabecontainer in den Ausgabecontainer, Änderung. Dadurch werden Computing-Kosten und potenzielle Qualitätsverluste die Decodierung und Neucodierung im selben Format.
HDR-Modus festlegen
Liegt die Eingabemediendatei in einem HDR-Format vor, kannst du zwischen verschiedenen
verschiedene Modi an, wie Transformer die HDR-Informationen verarbeitet. Wahrscheinlich
HDR_MODE_KEEP_HDR
oder
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL
.
HDR_MODE_KEEP_HDR |
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL |
|
---|---|---|
Beschreibung | Behalten Sie die HDR-Daten bei, das heißt, das HDR-Ausgabeformat entspricht dem HDR-Eingabeformat. | Tonemap-HDR-Eingabe für SDR mit einem OpenGL Tonemapper, d. h. das Ausgabeformat ist SDR. |
Support | Wird auf API-Levels 31 und höher für Geräte mit einem Encoder mit FEATURE_HdrEditing -Funktion unterstützt. |
Wird auf API-Ebenen ab 29 unterstützt. |
Fehler | Wenn die Funktion nicht unterstützt wird, wird versucht, stattdessen HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL zu verwenden. |
Wenn sie nicht unterstützt wird, wird ein ExportException ausgelöst. |
Auf Geräten, die die erforderlichen Codierungsfunktionen unterstützen und auf denen Android 13 ausgeführt wird
(API-Level 33) oder höher können mit Transformer
Objekten HDR-Videos bearbeitet werden.
HDR_MODE_KEEP_HDR
ist der Standardmodus beim Erstellen des Composition
-Objekts.
Dies wird im folgenden Code dargestellt:
Kotlin
val composition = Composition.Builder( ImmutableList.of(videoSequence)) .setHdrMode(HDR_MODE_KEEP_HDR) .build()
Java
Composition composition = new Composition.Builder( ImmutableList.of(videoSequence)) .setHdrMode(Composition.HDR_MODE_KEEP_HDR) .build();
Medienelement vorbereiten
MediaItem
steht für eine Audiodatei.
oder Videoelement in Ihrer App. Ein EditedMediaItem
sammelt MediaItem
entlang
mit den Transformationen, die darauf angewendet werden sollen.
Video zuschneiden
Wenn du unerwünschte Teile aus einem Video entfernen möchtest, kannst du Start und Ende selbst festlegen
Positionen hinzu, indem Sie dem MediaItem
einen ClippingConfiguration
hinzufügen.
Kotlin
val clippingConfiguration = MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(10_000) // start at 10 seconds .setEndPositionMs(20_000) // end at 20 seconds .build() val mediaItem = MediaItem.Builder() .setUri(videoUri) .setClippingConfiguration(clippingConfiguration) .build()
Java
ClippingConfiguration clippingConfiguration = new MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(10_000) // start at 10 seconds .setEndPositionMs(20_000) // end at 20 seconds .build(); MediaItem mediaItem = new MediaItem.Builder() .setUri(videoUri) .setClippingConfiguration(clippingConfiguration) .build();
Integrierte Effekte verwenden
Media3 bietet eine Reihe von Videoeffekten für gängige Transformationen. Beispiel:
Klasse | Effekt |
---|---|
Presentation |
Medienelement nach Auflösung oder Seitenverhältnis skalieren |
ScaleAndRotateTransformation |
Medienelement mit einem Multiplikator skalieren und/oder drehen |
Crop |
Medienelement auf einen kleineren oder größeren Frame zuschneiden |
OverlayEffect |
Füge ein Text- oder Bild-Overlay über dem Medienelement hinzu. |
Für Audioeffekte kannst du eine Reihe von
AudioProcessor
Instanzen, die die Rohaudiodaten (PCM) transformieren. So können Sie beispielsweise
ChannelMixingAudioProcessor
zum Mischen und Skalieren von Audiokanälen.
Um diese Effekte zu verwenden, erstelle eine Instanz des Effekts oder des Audioprozessors, erstelle eine
Eine Instanz von Effects
mit den Audio- und Videoeffekten, auf die du sie anwenden möchtest
das Medienelement und fügen Sie dann das Effects
-Objekt zu einem EditedMediaItem
hinzu.
Kotlin
val channelMixingProcessor = ChannelMixingAudioProcessor() val rotateEffect = ScaleAndRotateTransformation.Builder().setRotationDegrees(60f).build() val cropEffect = Crop(-0.5f, 0.5f, -0.5f, 0.5f) val effects = Effects(listOf(channelMixingProcessor), listOf(rotateEffect, cropEffect)) val editedMediaItem = EditedMediaItem.Builder(mediaItem) .setEffects(effects) .build()
Java
ChannelMixingAudioProcessor channelMixingProcessor = new ChannelMixingAudioProcessor(); ScaleAndRotateTransformation rotateEffect = new ScaleAndRotateTransformation.Builder() .setRotationDegrees(60f) .build(); Crop cropEffect = new Crop(-0.5f, 0.5f, -0.5f, 0.5f); Effects effects = new Effects( ImmutableList.of(channelMixingProcessor), ImmutableList.of(rotateEffect, cropEffect) ); EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(mediaItem) .setEffects(effects) .build();
Benutzerdefinierte Effekte erstellen
Wenn du die in Media3 enthaltenen Effekte erweiterst, kannst du benutzerdefinierte Effekte erstellen
die für Ihre Anwendungsfälle spezifisch sind. Verwenden Sie im folgenden Beispiel eine abgeleitete Klasse
MatrixTransformation
, um das Video so weit zu vergrößern, dass der Frame über dem ersten Frame ausgefüllt wird
Sekunde der Wiedergabe:
Kotlin
val zoomEffect = MatrixTransformation { presentationTimeUs -> val transformationMatrix = Matrix() // Set the scaling factor based on the playback position val scale = min(1f, presentationTimeUs / 1_000f) transformationMatrix.postScale(/* x */ scale, /* y */ scale) transformationMatrix } val editedMediaItem = EditedMediaItem.Builder(inputMediaItem) .setEffects(Effects(listOf(), listOf(zoomEffect)) .build()
Java
MatrixTransformation zoomEffect = presentationTimeUs -> { Matrix transformationMatrix = new Matrix(); // Set the scaling factor based on the playback position float scale = min(1f, presentationTimeUs / 1_000f); transformationMatrix.postScale(/* x */ scale, /* y */ scale); return transformationMatrix; }; EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(inputMediaItem) .setEffects(new Effects(ImmutableList.of(), ImmutableList.of(zoomEffect))) .build();
Sie können das Verhalten eines Effekts weiter anpassen, indem Sie ein
GlShaderProgram
Die
Die Methode queueInputFrame()
wird zum Verarbeiten von Eingabeframes verwendet. Zum Beispiel
dass Sie die ML-Funktionen Ihrer
MediaPipe verwenden, können Sie
MediaPipe FrameProcessor
um jeden Frame über ein MediaPipe-Diagramm zu senden. Ein Beispiel hierzu finden Sie in der
Transformer-Demo-App
Effektvorschau ansehen
Mit ExoPlayer kannst du dir eine Vorschau der Effekte ansehen
einem Medienelement hinzugefügt werden,
bevor der Exportvorgang gestartet wird. Mit denselben
Effects
-Objekt wie für EditedMediaItem
, rufen Sie setVideoEffects()
auf Ihrem
ExoPlayer-Instanz.
Kotlin
val player = ExoPlayer.builder(context) .build() .also { exoPlayer -> exoPlayer.setMediaItem(inputMediaItem) exoPlayer.setVideoEffects(effects) exoPlayer.prepare() }
Java
ExoPlayer player = new ExoPlayer.builder(context).build(); player.setMediaItem(inputMediaItem); player.setVideoEffects(effects); exoPlayer.prepare();
Mit ExoPlayer können Sie Audioeffekte auch in der Vorschau ansehen. Bei der Erstellung eines
ExoPlayer
-Instanz übergeben Sie eine benutzerdefinierte RenderersFactory
, die den
Audio-Renderer des Players, um Audio an AudioSink
auszugeben, die deine
AudioProcessor
-Sequenz. Im folgenden Beispiel überschreiben wir den Parameter
buildAudioSink()
-Methode einer DefaultRenderersFactory
.
Kotlin
val player = ExoPlayer.Builder(context, object : DefaultRenderersFactory(context) { override fun buildAudioSink( context: Context, enableFloatOutput: Boolean, enableAudioTrackPlaybackParams: Boolean, enableOffload: Boolean ): AudioSink? { return DefaultAudioSink.Builder(context) .setEnableFloatOutput(enableFloatOutput) .setEnableAudioTrackPlaybackParams(enableAudioTrackPlaybackParams) .setOffloadMode(if (enableOffload) { DefaultAudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED } else { DefaultAudioSink.OFFLOAD_MODE_DISABLED }) .setAudioProcessors(arrayOf(channelMixingProcessor)) .build() } }).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context, new DefaultRenderersFactory(context) { @Nullable @Override protected AudioSink buildAudioSink( Context context, boolean enableFloatOutput, boolean enableAudioTrackPlaybackParams, boolean enableOffload ) { return new DefaultAudioSink.Builder(context) .setEnableFloatOutput(enableFloatOutput) .setEnableAudioTrackPlaybackParams(enableAudioTrackPlaybackParams) .setOffloadMode( enableOffload ? DefaultAudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED : DefaultAudioSink.OFFLOAD_MODE_DISABLED) .setAudioProcessors(new AudioProcessor[]{channelMixingProcessor}) .build(); } }).build();
Transformation starten
Erstellen Sie abschließend eine Transformer
, um die Änderungen zu übernehmen und mit dem Exportieren der
das resultierende Medienelement.
Kotlin
val transformer = Transformer.Builder(context) .addListener(listener) .build() transformer.start(editedMediaItem, outputPath)
Java
Transformer transformer = new Transformer.Builder(context) .addListener(listener) .build(); transformer.start(editedMediaItem, outputPath);
Entsprechend können Sie den Exportvorgang bei Bedarf mit
Transformer.cancel()
Nach Updates suchen
Transformer.start
wird sofort zurückgegeben und wird asynchron ausgeführt. Für die Abfrage der
aktuellen Fortschritt einer Transformation, rufen Sie
Transformer.getProgress()
Diese Methode verwendet einen ProgressHolder
. Wenn der Fortschrittsstatus verfügbar ist,
Wenn die Methode also PROGRESS_STATE_AVAILABLE
zurückgibt, ist der angegebene Wert
ProgressHolder
wird mit dem aktuellen Fortschrittsprozentsatz aktualisiert.
Sie können auch eine
Listener
an Transformer
, um über Abschluss- oder Fehlerereignisse benachrichtigt zu werden.