API های Transformer در Jetpack Media3 به گونه ای طراحی شده اند که ویرایش رسانه را کارآمد و قابل اعتماد کنند. ترانسفورماتور از تعدادی عملیات پشتیبانی می کند، از جمله:
- اصلاح یک ویدیو با برش، مقیاسگذاری و چرخش
- افزودن افکتهایی مانند پوششها و فیلترها
- پردازش فرمت های خاص مانند HDR و ویدیوی حرکت آهسته
- صدور یک آیتم رسانه پس از اعمال ویرایش ها
این صفحه شما را با برخی از موارد استفاده کلیدی تحت پوشش Transformer آشنا می کند. برای جزئیات بیشتر می توانید به راهنمای کامل ما در Media3 Transformer مراجعه کنید.
شروع کنید
برای شروع، یک وابستگی به ماژول های Transformer، Effect و Common 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"
مطمئن شوید که 1.4.1
با نسخه دلخواه خود از کتابخانه جایگزین کنید. برای مشاهده آخرین نسخه می توانید به یادداشت های انتشار مراجعه کنید.
کلاس های مهم
کلاس | هدف |
---|---|
Transformer | تبدیل ها را شروع و متوقف کنید و به روز رسانی های پیشرفت را در یک تبدیل در حال اجرا بررسی کنید. |
EditedMediaItem | نشان دهنده یک آیتم رسانه برای پردازش و ویرایش هایی است که باید روی آن اعمال شود. |
Effects | مجموعه ای از جلوه های صوتی و تصویری. |
خروجی را پیکربندی کنید
با Transformer.Builder
، اکنون می توانید با تنظیم تابع بدون نیاز به ایجاد یک شی TransformationRequest
، فهرست videoMimeType
و audioMimetype
را مشخص کنید.
رمزگذاری بین فرمت ها
کد زیر نحوه پیکربندی یک شی Transformer
را برای خروجی ویدیو H.265/AVC و صدای AAC نشان میدهد:
کاتلین
val transformer = Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H265) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build()
جاوا
Transformer transformer = new Transformer.Builder(context) .setVideoMimeType(MimeTypes.VIDEO_H265) .setAudioMimeType(MimeTypes.AUDIO_AAC) .build();
اگر قالب رسانه ورودی از قبل با درخواست تبدیل برای صدا یا تصویر مطابقت داشته باشد، Transformer به طور خودکار به transmuxing تغییر می کند، یعنی نمونه های فشرده شده را از ظرف ورودی به محفظه خروجی بدون تغییر کپی می کند. این امر از هزینه محاسباتی و کاهش کیفیت بالقوه رمزگشایی و رمزگذاری مجدد در همان قالب جلوگیری می کند.
حالت HDR را تنظیم کنید
اگر فایل رسانه ورودی در فرمت HDR باشد، میتوانید از بین چند حالت مختلف برای نحوه پردازش اطلاعات HDR توسط Transformer انتخاب کنید. احتمالاً می خواهید از HDR_MODE_KEEP_HDR
یا HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL
استفاده کنید.
HDR_MODE_KEEP_HDR | HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL | |
---|---|---|
توضیحات | داده های HDR را حفظ کنید، به این معنی که فرمت خروجی HDR همان فرمت ورودی HDR است. | Tonemap ورودی HDR به SDR با استفاده از یک نقشهنگار تن OpenGL، به این معنی که فرمت خروجی در SDR خواهد بود. |
پشتیبانی کنید | در سطوح API 31+ برای دستگاههایی که دارای رمزگذار با قابلیت FEATURE_HdrEditing هستند پشتیبانی میشود. | در سطوح API 29+ پشتیبانی می شود. |
خطاها | اگر پشتیبانی نمیشود، سعی میکند به جای آن از HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL استفاده کند. | اگر پشتیبانی نمی شود، ExportException می اندازد. |
در دستگاههایی که از قابلیتهای رمزگذاری مورد نیاز پشتیبانی میکنند و Android 13 (سطح API 33) یا بالاتر را اجرا میکنند، اشیاء Transformer
به شما امکان میدهند ویدیوهای HDR را ویرایش کنید. HDR_MODE_KEEP_HDR
حالت پیش فرض هنگام ساخت شی Composition
است، همانطور که در کد زیر نشان داده شده است:
کاتلین
val composition = Composition.Builder( ImmutableList.of(videoSequence)) .setHdrMode(HDR_MODE_KEEP_HDR) .build()
جاوا
Composition composition = new Composition.Builder( ImmutableList.of(videoSequence)) .setHdrMode(Composition.HDR_MODE_KEEP_HDR) .build();
یک آیتم رسانه ای آماده کنید
MediaItem
یک مورد صوتی یا تصویری را در برنامه شما نشان می دهد. یک EditedMediaItem
یک MediaItem
به همراه تبدیلها جمعآوری میکند تا روی آن اعمال شود.
یک ویدیو را کوتاه کنید
برای حذف بخشهای ناخواسته یک ویدیو، میتوانید موقعیتهای شروع و پایان سفارشی را با افزودن یک ClippingConfiguration
به MediaItem
تنظیم کنید.
کاتلین
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()
جاوا
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();
از جلوه های داخلی استفاده کنید
Media3 شامل تعدادی جلوه های ویدئویی داخلی برای تبدیل های رایج است، به عنوان مثال:
کلاس | اثر |
---|---|
Presentation | مورد رسانه را بر اساس وضوح یا نسبت ابعاد مقیاس کنید |
ScaleAndRotateTransformation | مورد رسانه را با یک ضریب مقیاس کنید و/یا مورد رسانه را بچرخانید |
Crop | مورد رسانه را به یک قاب کوچکتر یا بزرگتر برش دهید |
OverlayEffect | یک پوشش متن یا تصویر در بالای مورد رسانه اضافه کنید |
برای جلوههای صوتی، میتوانید دنبالهای از نمونههای AudioProcessor
اضافه کنید که دادههای صوتی خام (PCM) را تغییر میدهند. به عنوان مثال، می توانید از یک ChannelMixingAudioProcessor
برای ترکیب و مقیاس بندی کانال های صوتی استفاده کنید.
برای استفاده از این افکتها، یک نمونه از افکت یا پردازشگر صوتی ایجاد کنید، یک نمونه از Effects
با جلوههای صوتی و تصویری که میخواهید روی آیتم رسانه اعمال کنید، بسازید، سپس شی Effects
به یک EditedMediaItem
اضافه کنید.
کاتلین
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()
جاوا
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();
ایجاد افکت های سفارشی
با گسترش افکت های موجود در Media3، می توانید افکت های سفارشی مخصوص موارد استفاده خود ایجاد کنید. در مثال زیر، از زیرکلاس MatrixTransformation
برای بزرگنمایی ویدیو به پر کردن فریم در ثانیه اول پخش استفاده کنید:
کاتلین
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()
جاوا
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();
برای سفارشی کردن بیشتر رفتار یک افکت، یک GlShaderProgram
را اجرا کنید. متد queueInputFrame()
برای پردازش فریم های ورودی استفاده می شود. برای مثال، برای استفاده از قابلیتهای یادگیری ماشین MediaPipe ، میتوانید از MediaPipe FrameProcessor
برای ارسال هر فریم از طریق یک نمودار MediaPipe استفاده کنید. نمونه ای از این را در برنامه نمایشی Transformer مشاهده کنید.
پیش نمایش افکت ها
با ExoPlayer ، میتوانید پیشنمایش افکتهای اضافهشده به یک آیتم رسانه را قبل از شروع فرآیند صادرات مشاهده کنید. با استفاده از همان شیء Effects
برای EditedMediaItem
، setVideoEffects()
را در نمونه ExoPlayer خود فراخوانی کنید.
کاتلین
val player = ExoPlayer.builder(context) .build() .also { exoPlayer -> exoPlayer.setMediaItem(inputMediaItem) exoPlayer.setVideoEffects(effects) exoPlayer.prepare() }
جاوا
ExoPlayer player = new ExoPlayer.builder(context).build(); player.setMediaItem(inputMediaItem); player.setVideoEffects(effects); exoPlayer.prepare();
همچنین میتوانید جلوههای صوتی را با ExoPlayer مشاهده کنید. هنگام ساختن نمونه ExoPlayer
خود، یک RenderersFactory
سفارشی را ارسال کنید که رندرهای صوتی پخش کننده را برای خروجی صدا به AudioSink
که از دنباله AudioProcessor
شما استفاده می کند، پیکربندی می کند. در مثال زیر، ما این کار را با نادیده گرفتن متد buildAudioSink()
یک DefaultRenderersFactory
انجام می دهیم.
کاتلین
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()
جاوا
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();
یک تحول را شروع کنید
در نهایت، یک Transformer
ایجاد کنید تا ویرایش های خود را اعمال کنید و شروع به صادر کردن آیتم رسانه ای کنید.
کاتلین
val transformer = Transformer.Builder(context) .addListener(listener) .build() transformer.start(editedMediaItem, outputPath)
جاوا
Transformer transformer = new Transformer.Builder(context) .addListener(listener) .build(); transformer.start(editedMediaItem, outputPath);
در صورت نیاز میتوانید فرآیند صادرات را با Transformer.cancel()
لغو کنید.
به روز رسانی پیشرفت را بررسی کنید
Transformer.start
بلافاصله برمی گردد و به صورت ناهمزمان اجرا می شود. برای پرس و جو از پیشرفت فعلی یک تبدیل، Transformer.getProgress()
را فراخوانی کنید. این متد یک ProgressHolder
می گیرد و اگر وضعیت پیشرفت موجود باشد، یعنی اگر متد PROGRESS_STATE_AVAILABLE
را برگرداند، آنگاه ProgressHolder
ارائه شده با درصد پیشرفت فعلی به روز می شود.
همچنین میتوانید شنوندهای را به Transformer
خود متصل کنید تا از اتمام یا رخدادهای خطا مطلع شود.