Trasformazioni

Jetpack Media3 Transformer consente di modificare, convertire ed esportare asset multimediali su Android. Questa pagina spiega come configurare le trasformazioni principali:

  • Transcodifica e transmuxing: converti i formati audio e video o ignora la ricodifica tramite la copia di campioni di container (transmuxing).
  • Rimozione delle tracce: rimuovi le tracce audio o video dai contenuti multimediali.
  • Taglio e ottimizzazione: taglia i contenuti multimediali in base al timestamp, con opzioni per esportazioni più rapide utilizzando gli elenchi di modifica MP4 e l'ottimizzazione del taglio.
  • Effetti video: ridimensiona, ruota o applica effetti shader OpenGL personalizzati, visualizzabili in anteprima anche in ExoPlayer.
  • Input immagine: trasforma le immagini statiche in video clip con durate personalizzate e frame rate.
  • Elaborazione audio: concatena le istanze AudioProcessor per modificare l'audio non elaborato.

Transcodifica tra formati

Quando crei Transformer, puoi specificare i formati audio e video di output che vuoi produrre. Ad esempio, il seguente codice mostra come configurare Transformer per generare video H.264/AVC e audio AAC:

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

Se il formato dei contenuti multimediali di input corrisponde già alle configurazioni per audio o video, Transformer passa automaticamente al transmuxing, ovvero alla copia dei campioni compressi dal container di input al container di output senza modifiche. In questo modo, si evitano i costi di calcolo e la potenziale perdita di qualità della decodifica e della ricodifica nello stesso formato.

Rimuovi audio o video

Rimuovi audio o video utilizzando EditedMediaItem.Builder, ad esempio:

Kotlin

EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()

Java

new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();

Taglia un clip

Puoi rimuovere tutti i contenuti multimediali al di fuori dei timestamp di inizio e fine specificati impostando la configurazione di clipping sull'elemento multimediale di input. Ad esempio, per produrre un clip contenente solo i contenuti multimediali tra 10 e 20 secondi:

Kotlin

val inputMediaItem =
  MediaItem.Builder()
    .setUri(uri)
    .setClippingConfiguration(
      MediaItem.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();

Elenchi di modifica MP4

Per un taglio più rapido, Transformer supporta gli elenchi di modifica MP4, consentendo modifiche "solo taglio" più efficienti senza la ricodifica completa del video. Questo metodo utilizza i campioni codificati esistenti e un "pre-roll" all'interno dell'elenco di modifica, che indica al player di iniziare la riproduzione in un punto specifico, saltando di fatto il segmento iniziale indesiderato.

Per rendere le modifiche solo taglio molto più rapide, chiama experimentalSetMp4EditListTrimEnabled(true).

Kotlin

Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build()

Java

new Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build();
È importante notare che non tutti i player multimediali supportano una posizione "pre-roll". Ciò significa che quando viene utilizzato un player di questo tipo, la riproduzione del file inizierà dall'inizio assoluto del campione codificato, indipendentemente dalle informazioni dell'elenco di modifica che potrebbero specificare un punto di partenza diverso.

Ottimizzazione dei tagli

Per ridurre la latenza del taglio dell'inizio di un video, attiva l'ottimizzazione del taglio.

Kotlin

Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build()

Java

new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build();

In questo modo, l'esportazione viene velocizzata decodificando e ricodificando la minor parte possibile del video, quindi unendo i dati ricodificati con il resto del video originale. L'ottimizzazione si basa sulla possibilità di unire parte del file di input con l'output appena codificato, il che significa che il formato di output del codificatore e il formato di input devono essere compatibili. Ad esempio, se il file è stato originariamente prodotto su un dispositivo con un'implementazione del codificatore diversa, è probabile che non sia possibile applicare l'ottimizzazione. Affinché l'ottimizzazione vada a buon fine, il codificatore fornito a Transformer tramite EncoderFactory deve avere un livello e un profilo compatibili con il formato di input.

Questa ottimizzazione funziona solo con input MP4 a singolo asset senza effetti, ad eccezione degli effetti video no op e delle rotazioni divisibili per 90 gradi. Se l'ottimizzazione non riesce, Transformer torna automaticamente all'esportazione normale e segnala il risultato dell'ottimizzazione in ExportResult.OptimizationResult.

Stiamo convalidando questa funzionalità e prevediamo che diventerà non sperimentale in una release successiva.

Modifiche ai video

Gli EditedMediaItems hanno elenchi di processori audio ed effetti video da applicare in ordine. La libreria include implementazioni di effetti video per casi d'uso comuni oppure puoi scrivere effetti personalizzati e passarli durante la creazione di elementi multimediali modificati.

Puoi ridimensionare i contenuti multimediali, il che può essere utile per risparmiare risorse di elaborazione o larghezza di banda quando hai a che fare con input ad alta risoluzione, ad esempio video 4K o 8K. Ad esempio, per scalare proporzionalmente a 480 pixel di altezza:

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

In alternativa, puoi scalare in base a un fattore specifico, ad esempio per dimezzare le dimensioni:

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

Puoi configurare la rotazione nello stesso modo:

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

Effetti video personalizzati

Il costruttore Effects accetta un elenco di effetti audio e video da applicare. Internamente, il framework degli effetti di Transformer converte l'elenco degli effetti video in una sequenza di programmi shader GL che vengono applicati in ordine. In alcuni casi, il framework degli effetti è in grado di applicare più effetti con un programma shader. Ad esempio, un programma shader può applicare più trasformazioni di matrici consecutive, il che migliora l'efficienza e la qualità.

Gli effetti video sono supportati anche per l'anteprima in ExoPlayer, utilizzando ExoPlayer.setVideoEffects. Per un esempio di come utilizzare questa API, consulta l'app demo degli effetti.

L'app demo include esempi di effetti video personalizzati.

Input immagine

Transformer supporta gli input immagine trattandoli come video clip statici. Per configurare un'immagine come sorgente di ingresso, segui questi passaggi:

  • Crea un MediaItem utilizzando MediaItem.Builder. Specifica la durata di visualizzazione dell'immagine nel video di output chiamando setImageDurationMs.

  • Crea un EditedMediaItem che racchiude il MediaItem. Specifica la frequenza fotogrammi di destinazione per lo stream video generato utilizzando EditedMediaItem.Builder#setFrameRate.

L'esempio seguente mostra come configurare un input immagine per generare un video di 5 secondi a 30 frame al secondo:

Kotlin

val imageMediaItem =
  MediaItem.Builder()
    .setUri(imageUri)
    .setImageDurationMs(5000) // 5 seconds
    .build()

val editedImageItem =
  EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build()

Java

MediaItem imageMediaItem =
    new MediaItem.Builder()
        .setUri(imageUri)
        .setImageDurationMs(5000) // 5 seconds
        .build();
new EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build();

Modifiche audio

Gli effetti audio vengono implementati applicando una sequenza di istanze AudioProcessor all'audio non elaborato (PCM). ExoPlayer supporta il passaggio dei processori audio a DefaultAudioSink.Builder, il che consente di visualizzare in anteprima le modifiche audio.