Le API Transformer in Jetpack Media3 sono progettate per offrire un servizio di editing multimediale efficiente e affidabile. Transformer supporta diverse operazioni, tra cui:
- Modifica di un video mediante taglio, ridimensionamento e rotazione
- Aggiunta di effetti come overlay e filtri.
- Elaborazione di formati speciali come HDR e video in slow motion
- Esportazione di un elemento multimediale dopo l'applicazione delle modifiche
Questa pagina illustra alcuni dei casi d'uso principali trattati da Transformer. Per ulteriori dettagli, puoi consultare le nostre guide complete su Media3 Transformer.
Inizia
Per iniziare, aggiungi una dipendenza ai moduli Transformer, Effect e Common di Jetpack Media3:
implementation "androidx.media3:media3-transformer:1.3.1" implementation "androidx.media3:media3-effect:1.3.1" implementation "androidx.media3:media3-common:1.3.1"
Assicurati di sostituire 1.3.1
con la tua versione preferita della libreria. Puoi consultare le note di rilascio per conoscere la versione più recente.
Corsi importanti
Classe | Finalità |
---|---|
Transformer |
Avvia e interrompi le trasformazioni e verifica la presenza di aggiornamenti sull'avanzamento di una trasformazione in esecuzione. |
EditedMediaItem |
Rappresenta un elemento multimediale da elaborare e le modifiche da applicare. |
Effects |
Una raccolta di effetti audio e video. |
Configura l'output
Con Transformer.Builder
, ora puoi specificare le directory videoMimeType
e audioMimetype
impostando la funzione senza dover creare un oggetto TransformationRequest
.
Transcodifica tra formati
Il seguente codice mostra come configurare un oggetto Transformer
per l'output di video H.265/AVC e audio AAC:
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();
Se il formato multimediale di input corrisponde già alla richiesta di trasformazione per audio o video, Transformer passa automaticamente al transmuxing, ovvero copiando i campioni compressi dal container di input al container di output senza modifiche. Ciò evita i costi di calcolo e la potenziale perdita di qualità dovuta alla decodifica e alla ricodifica nello stesso formato.
Imposta modalità HDR
Se il file multimediale di input è in formato HDR, puoi scegliere tra diverse
modalità per l'elaborazione delle informazioni HDR da parte di Transformer. Probabilmente vorrai utilizzare HDR_MODE_KEEP_HDR
o HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL
.
HDR_MODE_KEEP_HDR |
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL |
|
---|---|---|
Descrizione | Consente di conservare i dati HDR, il che significa che il formato di output HDR è lo stesso del formato di input HDR. | Input Tonemap HDR in SDR utilizzando un mappatore di toni OpenGL, il che significa che il formato di output sarà SDR. |
Assistenza | Funzionalità supportata sui livelli API 31 e versioni successive per i dispositivi che includono un codificatore con la funzionalità FEATURE_HdrEditing . |
Funzionalità supportata per i livelli API 29+. |
Errori | Se non è supportato, prova a utilizzare invece HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL . |
Se non è supportato, genera un elemento ExportException . |
Sui dispositivi che supportano le funzionalità di codifica richieste e eseguono Android 13 (livello API 33) o versioni successive, gli oggetti Transformer
ti consentono di modificare i video HDR.
HDR_MODE_KEEP_HDR
è la modalità predefinita durante la creazione dell'oggetto Composition
, come mostrato nel codice seguente:
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();
Preparare un elemento multimediale
Un elemento MediaItem
rappresenta un elemento audio
o video nell'app. Un elemento EditedMediaItem
raccoglie un MediaItem
insieme alle
trasformazioni da applicare.
Tagliare un video
Per rimuovere parti indesiderate di un video, puoi impostare posizioni di inizio e fine personalizzate
aggiungendo un elemento ClippingConfiguration
a MediaItem
.
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();
Utilizzare gli effetti integrati
Media3 include una serie di effetti video integrati per le trasformazioni più comuni, ad esempio:
Classe | Effetto |
---|---|
Presentation |
Scala l'elemento multimediale in base alla risoluzione o alle proporzioni |
ScaleAndRotateTransformation |
Scalare l'elemento multimediale di un moltiplicatore e/o ruotarlo |
Crop |
Ritaglia l'elemento multimediale in una cornice più piccola o più grande |
OverlayEffect |
Aggiungi un overlay di testo o immagine sulla parte superiore dell'elemento multimediale |
Per gli effetti audio, puoi aggiungere una sequenza di istanze AudioProcessor
che trasformeranno i dati audio non elaborati (PCM). Ad esempio, puoi utilizzare
una ChannelMixingAudioProcessor
per mixare e scalare i canali audio.
Per utilizzare questi effetti, crea un'istanza dell'effetto o del processore audio, crea un'istanza di Effects
con gli effetti audio e video che vuoi applicare all'elemento multimediale, quindi aggiungi l'oggetto Effects
a un EditedMediaItem
.
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();
Creare effetti personalizzati
Se estendi gli effetti inclusi in Media3, puoi creare effetti personalizzati
specifici per i tuoi casi d'uso. Nell'esempio seguente, utilizza la sottoclasse MatrixTransformation
per aumentare lo zoom del video e riempire l'inquadratura durante il primo secondo di riproduzione:
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();
Per personalizzare ulteriormente il comportamento di un effetto, implementa GlShaderProgram
. Il metodo queueInputFrame()
viene utilizzato per elaborare i frame di input. Ad esempio, per sfruttare le funzionalità di machine learning di MediaPipe, puoi utilizzare un MediaPipe FrameProcessor
per inviare ogni frame tramite un grafico MediaPipe. Guarda un esempio nell'app demo Transformer.
Anteprima effetti
Con ExoPlayer puoi visualizzare l'anteprima degli effetti aggiunti a un elemento multimediale prima di avviare il processo di esportazione. Utilizzando lo stesso oggetto Effects
di EditedMediaItem
, chiama setVideoEffects()
sulla tua istanza ExoPlayer.
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();
Con ExoPlayer puoi anche visualizzare l'anteprima degli effetti audio. Quando crei la tua istanza ExoPlayer
, inserisci un RenderersFactory
personalizzato che configura i renderer audio del player per l'output dell'audio in un file AudioSink
che utilizza la sequenza AudioProcessor
. Nell'esempio riportato di seguito, eseguiamo questa operazione sostituendo il metodo buildAudioSink()
di un 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();
Avvia una trasformazione
Infine, crea un Transformer
per applicare le modifiche e iniziare a esportare
l'elemento multimediale risultante.
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);
In modo simile, puoi annullare il processo di esportazione, se necessario, con
Transformer.cancel()
.
Verifica la disponibilità di aggiornamenti sui progressi
Transformer.start
restituisce immediatamente ed esegue l'esecuzione in modo asincrono. Per eseguire query sull'avanzamento attuale di una trasformazione, chiama Transformer.getProgress()
.
Questo metodo richiede un ProgressHolder
e, se lo stato di avanzamento è disponibile, ovvero se il metodo restituisce PROGRESS_STATE_AVAILABLE
, il valore ProgressHolder
fornito verrà aggiornato con la percentuale di avanzamento attuale.
Puoi anche allegare un
ascoltatore
a Transformer
per ricevere notifiche relative a eventi di completamento o di errore.