O Jetpack Media3 Transformer permite editar, converter e exportar recursos de mídia no Android. Esta página explica como configurar transformações principais:
- Transcodificação e transmuxação: converta formatos de áudio e vídeo ou ignore a recodificação copiando amostras de contêiner (transmuxação).
- Remoção de faixas: remova faixas de áudio ou vídeo da mídia.
- Corte e otimização: recorte a mídia por carimbo de data/hora, com opções para exportações mais rápidas usando listas de edição de MP4 e otimização de corte.
- Efeitos de vídeo: dimensione, gire ou aplique efeitos de sombreador OpenGL personalizados, que também podem ser visualizados no ExoPlayer.
- Entrada de imagem: transforme imagens estáticas em clipes de vídeo com durações personalizadas e frame rates.
- Processamento de áudio: encadeie instâncias de
AudioProcessorpara modificar o áudio bruto.
Transcodificar entre formatos
É possível especificar os formatos de áudio e vídeo de saída que você quer produzir ao criar o Transformer. Por exemplo, o código a seguir mostra como configurar o Transformer para gerar vídeo H.264/AVC e áudio 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 o formato de mídia de entrada já corresponder às configurações de áudio ou vídeo, o Transformer vai mudar automaticamente para transmuxação, ou seja, copiar as amostras compactadas do contêiner de entrada para o contêiner de saída sem modificação. Isso evita o custo computacional e a possível perda de qualidade da decodificação e recodificação no mesmo formato.
Remover áudio ou vídeo
Remova áudio ou vídeo usando EditedMediaItem.Builder, por exemplo:
Kotlin
EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()
Java
new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();
Cortar um clipe
É possível remover qualquer mídia fora dos carimbos de data/hora de início e fim especificados definindo a configuração de recorte no item de mídia de entrada. Por exemplo, para produzir um clipe que contenha apenas a mídia entre 10 e 20 segundos:
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();
Listas de edição de MP4
Para um corte mais rápido, o Transformer oferece suporte a listas de edição de MP4, permitindo edições "somente de corte" mais eficientes sem a recodificação completa do vídeo. Esse método utiliza amostras codificadas e um "anúncio precedente" na lista de edição, que instrui o player a iniciar a reprodução em um ponto específico, ignorando o segmento inicial indesejado.
Para tornar as edições somente de corte significativamente mais rápidas, chame experimentalSetMp4EditListTrimEnabled(true).
Kotlin
Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build()
Java
new Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build();
Otimizar cortes
Para reduzir a latência do corte do início de um vídeo, ative a otimização de corte.
Kotlin
Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build()
Java
new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build();
Isso acelera a exportação decodificando e recodificando o mínimo possível do vídeo e, em seguida, unindo os dados recodificados com o restante do vídeo original. A otimização depende da capacidade de unir parte do arquivo de entrada com a saída recém-codificada, o que significa que o formato de saída do codificador e o formato de entrada precisam ser compatíveis. Portanto, por exemplo, se o arquivo foi produzido originalmente em um dispositivo com uma implementação de codificador diferente, é provável que não seja possível aplicar a otimização.
Para que a otimização seja bem-sucedida, o codificador fornecido ao Transformer pela EncoderFactory precisa ter um nível e um perfil compatíveis com o formato de entrada.
Essa otimização só funciona com entrada MP4 de recurso único sem efeitos, exceto efeitos de vídeo sem operação e rotações divisíveis por 90 graus. Se a otimização falhar, o Transformer vai voltar automaticamente para a exportação normal e informar o resultado da otimização em ExportResult.OptimizationResult.
Estamos validando essa funcionalidade e esperamos que ela deixe de ser experimental em uma versão posterior.
Edições de vídeo
Os EditedMediaItems têm listas de processadores de áudio e efeitos de vídeo a serem aplicados em ordem. A biblioteca inclui implementações de efeitos de vídeo para casos de uso comuns. Também é possível gravar efeitos personalizados e transmiti-los ao criar itens de mídia editados.
É possível redimensionar a mídia, o que pode ser útil para economizar recursos de processamento ou largura de banda ao lidar com entradas de alta resolução, como vídeos 4K ou 8K. Por exemplo, para dimensionar proporcionalmente a 480 pixels de altura:
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();
Como alternativa, é possível dimensionar por um determinado fator, por exemplo, para reduzir o tamanho pela metade:
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();
É possível configurar a rotação da mesma maneira:
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();
Efeitos de vídeo personalizados
O construtor Effects aceita uma lista de efeitos de áudio e vídeo a serem aplicados.
Internamente, a estrutura de efeitos do Transformer converte a lista de efeitos de vídeo em uma sequência de programas de sombreador GL que são aplicados em ordem. Em alguns casos, a estrutura de efeitos pode aplicar vários efeitos com um programa de sombreador.
Por exemplo, um programa de sombreador pode aplicar várias transformações de matriz consecutivas, o que melhora a eficiência e a qualidade.
Os efeitos de vídeo também são compatíveis com a visualização no ExoPlayer, usando ExoPlayer.setVideoEffects. Para um exemplo de como usar essa API, confira
o app de demonstração de efeitos.
O app de demonstração inclui exemplos de efeitos de vídeo personalizados.
Entrada de imagem
O Transformer oferece suporte a entradas de imagem tratando-as como clipes de vídeo estáticos. Para configurar uma imagem como uma origem da entrada, siga estas etapas:
Crie um
MediaItemusandoMediaItem.Builder. Especifique a duração da exibição da imagem no vídeo de saída chamandosetImageDurationMs.Construa um
EditedMediaItemque envolva oMediaItem. Especifique o frame rate de destino para o fluxo de vídeo gerado usandoEditedMediaItem.Builder#setFrameRate.
O exemplo a seguir demonstra como configurar uma entrada de imagem para gerar um vídeo de 5 segundos a 30 frames por segundo:
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();
Edições de áudio
Os efeitos de áudio são implementados aplicando uma sequência de instâncias de AudioProcessor ao áudio bruto (PCM). O ExoPlayer oferece suporte à transmissão de processadores de áudio para o DefaultAudioSink.Builder, que permite visualizar edições de áudio.