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