Transformer API trong Jetpack Media3 được thiết kế để giúp việc chỉnh sửa nội dung nghe nhìn có hiệu quả và đáng tin cậy. Transformer hỗ trợ một số toán tử, bao gồm:
- Sửa đổi video bằng tính năng cắt, điều chỉnh theo tỷ lệ và xoay
- Thêm hiệu ứng như lớp phủ và bộ lọc
- Xử lý các định dạng đặc biệt như video HDR và video chuyển động chậm
- Xuất mục nội dung nghe nhìn sau khi áp dụng các nội dung chỉnh sửa
Trang này hướng dẫn bạn một số trường hợp sử dụng chính mà Transformer đề cập. Để biết thêm thông tin, bạn có thể xem hướng dẫn đầy đủ của chúng tôi về Media3 Transformer.
Bắt đầu
Để bắt đầu, hãy thêm phần phụ thuộc vào các mô-đun Transformer, Effect và Common (Phổ biến) của 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"
Hãy nhớ thay thế 1.3.1
bằng phiên bản thư viện bạn muốn. Bạn có thể tham khảo ghi chú phát hành để xem phiên bản mới nhất.
Các lớp quan trọng
Lớp | Mục đích |
---|---|
Transformer |
Bắt đầu và dừng các quy tắc chuyển đổi, đồng thời kiểm tra cập nhật tiến trình của một phép biến đổi đang chạy. |
EditedMediaItem |
Biểu thị một mục nội dung đa phương tiện cần xử lý và các nội dung chỉnh sửa cần áp dụng cho mục đó. |
Effects |
Bộ sưu tập hiệu ứng âm thanh và video. |
Định cấu hình dữ liệu đầu ra
Với Transformer.Builder
, giờ đây, bạn có thể chỉ định thư mục videoMimeType
và audioMimetype
bằng cách đặt hàm mà không cần tạo đối tượng TransformationRequest
.
Chuyển mã giữa các định dạng
Mã sau đây cho biết cách định cấu hình một đối tượng Transformer
để xuất video H.265/AVC và âm thanh 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();
Nếu định dạng nội dung nghe nhìn đầu vào đã khớp với yêu cầu chuyển đổi cho âm thanh hoặc video, Transformer sẽ tự động chuyển sang chế độ truyền tải, tức là sao chép các mẫu nén từ vùng chứa đầu vào sang vùng chứa đầu ra mà không cần sửa đổi. Điều này giúp tránh chi phí tính toán và giảm chất lượng có thể xảy ra khi giải mã và mã hoá lại ở cùng một định dạng.
Đặt chế độ HDR
Nếu tệp nội dung nghe nhìn đầu vào ở định dạng HDR, bạn có thể chọn trong số một vài chế độ để Transformer xử lý thông tin HDR. Bạn có thể muốn sử dụng HDR_MODE_KEEP_HDR
hoặc HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL
.
HDR_MODE_KEEP_HDR |
HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL |
|
---|---|---|
Nội dung mô tả | Giữ nguyên dữ liệu HDR, nghĩa là định dạng đầu ra HDR giống với định dạng đầu vào HDR. | Tông màu đầu vào HDR ánh xạ đầu vào SDR bằng cách sử dụng công cụ liên kết tông OpenGL, nghĩa là định dạng đầu ra sẽ ở SDR. |
Hỗ trợ | Được hỗ trợ trên API cấp 31 trở lên đối với các thiết bị có bộ mã hoá có tính năng FEATURE_HdrEditing . |
Được hỗ trợ trên API cấp 29 trở lên. |
Lỗi | Nếu tính năng này không được hỗ trợ, hãy thử dùng HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL . |
Nếu không được hỗ trợ, hệ thống sẽ gửi một ExportException . |
Trên các thiết bị hỗ trợ khả năng mã hoá cần thiết và chạy Android 13 (API cấp 33) trở lên, các đối tượng Transformer
cho phép bạn chỉnh sửa video HDR.
HDR_MODE_KEEP_HDR
là chế độ mặc định khi tạo đối tượng Composition
, như trong mã sau:
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();
Chuẩn bị một mục nội dung đa phương tiện
MediaItem
đại diện cho một mục âm thanh hoặc video trong ứng dụng. EditedMediaItem
thu thập MediaItem
cùng với các phép biến đổi để áp dụng cho mục đó.
Cắt ngắn video
Để xoá các phần không mong muốn của video, bạn có thể đặt vị trí bắt đầu và kết thúc tuỳ chỉnh
bằng cách thêm ClippingConfiguration
vào 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();
Dùng hiệu ứng tích hợp
Media3 bao gồm một số hiệu ứng video tích hợp sẵn cho các phép biến đổi phổ biến, chẳng hạn như:
Lớp | Hiệu ứng |
---|---|
Presentation |
Điều chỉnh tỷ lệ mục nội dung nghe nhìn theo độ phân giải hoặc tỷ lệ khung hình |
ScaleAndRotateTransformation |
Điều chỉnh mục nội dung nghe nhìn theo tỷ lệ theo hệ số và/hoặc xoay mục nội dung nghe nhìn |
Crop |
Cắt mục nội dung nghe nhìn thành khung nhỏ hơn hoặc lớn hơn |
OverlayEffect |
Thêm lớp phủ văn bản hoặc hình ảnh lên trên mục nội dung đa phương tiện |
Đối với hiệu ứng âm thanh, bạn có thể thêm một chuỗi các thực thể AudioProcessor
sẽ chuyển đổi dữ liệu âm thanh thô (PCM). Ví dụ: bạn có thể sử dụng ChannelMixingAudioProcessor
để trộn và mở rộng quy mô kênh âm thanh.
Để sử dụng các hiệu ứng này, hãy tạo một thực thể của hiệu ứng hoặc trình xử lý âm thanh, tạo một thực thể của Effects
có hiệu ứng âm thanh và video bạn muốn áp dụng cho mục nội dung đa phương tiện, sau đó thêm đối tượng Effects
vào 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();
Tạo hiệu ứng tuỳ chỉnh
Bằng cách mở rộng các hiệu ứng có trong Media3, bạn có thể tạo các hiệu ứng tuỳ chỉnh dành riêng cho các trường hợp sử dụng của mình. Trong ví dụ sau, sử dụng lớp con MatrixTransformation
để phóng to video vào khung hình trong giây đầu tiên phát:
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();
Để tuỳ chỉnh thêm hành vi của một hiệu ứng, hãy triển khai
GlShaderProgram
. Phương thức queueInputFrame()
được dùng để xử lý khung đầu vào. Ví dụ: để tận dụng các tính năng học máy của MediaPipe, bạn có thể sử dụng MediaPipe FrameProcessor
để gửi từng khung thông qua một biểu đồ MediaPipe. Hãy xem ví dụ về trường hợp này trong Ứng dụng minh hoạ Transformer.
Xem trước hiệu ứng
Với ExoPlayer, bạn có thể xem trước các hiệu ứng được thêm vào mục nội dung đa phương tiện trước khi bắt đầu quá trình xuất. Sử dụng cùng một đối tượng Effects
như đối với EditedMediaItem
, gọi setVideoEffects()
trên thực thể ExoPlayer của bạn.
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();
Bạn cũng có thể xem trước các hiệu ứng âm thanh bằng ExoPlayer. Khi tạo thực thể ExoPlayer
, hãy truyền một RenderersFactory
tuỳ chỉnh giúp định cấu hình trình kết xuất âm thanh của người chơi để xuất âm thanh sang AudioSink
sử dụng trình tự AudioProcessor
. Trong ví dụ bên dưới, chúng tôi thực hiện việc này bằng cách ghi đè phương thức
buildAudioSink()
của 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();
Bắt đầu hành động biến đổi
Cuối cùng, hãy tạo một Transformer
để áp dụng các nội dung chỉnh sửa và bắt đầu xuất mục nội dung nghe nhìn thu được.
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);
Tương tự, bạn có thể huỷ quá trình xuất dữ liệu nếu cần bằng Transformer.cancel()
.
Kiểm tra xem có thông tin cập nhật về tiến trình hay không
Transformer.start
trả về ngay lập tức và chạy không đồng bộ. Để truy vấn tiến trình hiện tại của một phép biến đổi, hãy gọi Transformer.getProgress()
.
Phương thức này nhận một ProgressHolder
và nếu trạng thái tiến trình có sẵn, nghĩa là nếu phương thức này trả về PROGRESS_STATE_AVAILABLE
, thì ProgressHolder
đã cung cấp sẽ được cập nhật với tỷ lệ phần trăm tiến trình hiện tại.
Bạn cũng có thể đính kèm trình nghe vào Transformer
để được thông báo về các sự kiện lỗi hoặc hoàn thành.