Jetpack Media3 में मौजूद Transformer API को, मीडिया एडिटिंग को बेहतर और भरोसेमंद बनाने के लिए डिज़ाइन किया गया है. Transformer कई तरह के ऑपरेशन कर सकता है. जैसे:
- वीडियो को ट्रिम करना, उसका साइज़ बदलना, और उसे घुमाना
- ओवरले और फ़िल्टर जैसे इफ़ेक्ट जोड़ना
- एचडीआर और स्लो-मोशन वीडियो जैसे खास फ़ॉर्मैट को प्रोसेस करना
- बदलाव करने के बाद, मीडिया आइटम एक्सपोर्ट करना
इस पेज पर, Transformer के कुछ मुख्य इस्तेमाल के उदाहरण दिए गए हैं. ज़्यादा जानकारी के लिए, Media3 Transformer के बारे में हमारी पूरी गाइड देखें.
शुरू करें
शुरू करने के लिए, Jetpack Media3 के Transformer, Effect, और Common मॉड्यूल पर डिपेंडेंसी जोड़ें:
implementation "androidx.media3:media3-transformer:1.8.0" implementation "androidx.media3:media3-effect:1.8.0" implementation "androidx.media3:media3-common:1.8.0"
1.8.0
को अपनी पसंद के हिसाब से लाइब्रेरी के वर्शन से बदलना न भूलें. सबसे नया वर्शन देखने के लिए, रिलीज़ नोट देखें.
अहम क्लास
कक्षा | मकसद |
---|---|
Transformer |
डेटा ट्रांसफ़ॉर्मेशन शुरू और बंद करें. साथ ही, चल रहे डेटा ट्रांसफ़ॉर्मेशन की प्रोग्रेस अपडेट देखें. |
EditedMediaItem |
यह प्रोसेस किए जाने वाले मीडिया आइटम और उसमें किए जाने वाले बदलावों को दिखाता है. |
Effects |
ऑडियो और वीडियो इफ़ेक्ट का कलेक्शन. |
आउटपुट को कॉन्फ़िगर करना
Transformer.Builder
की मदद से, अब videoMimeType
और audioMimetype
डायरेक्ट्री सेट की जा सकती है. इसके लिए, TransformationRequest
ऑब्जेक्ट बनाने की ज़रूरत नहीं है.
अलग-अलग फ़ॉर्मैट में ट्रांसकोड करना
यहां दिए गए कोड में, H.265/AVC वीडियो और AAC ऑडियो को आउटपुट करने के लिए, Transformer
ऑब्जेक्ट को कॉन्फ़िगर करने का तरीका बताया गया है:
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();
अगर इनपुट मीडिया फ़ॉर्मैट, ऑडियो या वीडियो के लिए ट्रांसफ़ॉर्मेशन के अनुरोध से पहले से ही मेल खाता है, तो Transformer अपने-आप ट्रांसमक्सिंग पर स्विच हो जाता है. इसका मतलब है कि यह कंप्रेस किए गए सैंपल को इनपुट कंटेनर से आउटपुट कंटेनर में बिना किसी बदलाव के कॉपी करता है. इससे, एक ही फ़ॉर्मैट में डिकोड और री-एनकोड करने की कंप्यूटेशनल लागत से बचा जा सकता है. साथ ही, क्वालिटी में संभावित गिरावट को भी रोका जा सकता है.
एचडीआर मोड सेट करना
अगर इनपुट मीडिया फ़ाइल HDR फ़ॉर्मैट में है, तो आपके पास यह चुनने का विकल्प होता है कि Transformer, HDR जानकारी को कैसे प्रोसेस करे. इसके लिए, कुछ अलग-अलग मोड उपलब्ध हैं. आपको शायद 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 |
|
---|---|---|
ब्यौरा | एचडीआर डेटा को सुरक्षित रखना. इसका मतलब है कि एचडीआर आउटपुट फ़ॉर्मैट, एचडीआर इनपुट फ़ॉर्मैट के जैसा ही होता है. | OpenGL टोन-मैपर का इस्तेमाल करके, एचडीआर इनपुट को एसडीआर में टोनमैप करता है. इसका मतलब है कि आउटपुट एसडीआर फ़ॉर्मैट में होगा. |
सहायता | यह सुविधा, एपीआई लेवल 31 और इसके बाद के वर्शन पर काम करती है. साथ ही, यह उन डिवाइसों पर काम करती है जिनमें FEATURE_HdrEditing सुविधा वाला एनकोडर शामिल है. |
यह सुविधा, एपीआई लेवल 29 और इसके बाद के वर्शन पर काम करती है. |
गड़बड़ियां | अगर यह सुविधा काम नहीं करती है, तो HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL का इस्तेमाल करने की कोशिश करें. |
अगर यह सुविधा काम नहीं करती है, तो ExportException दिखता है. |
जिन डिवाइसों पर ज़रूरी एन्कोडिंग की सुविधाएं काम करती हैं और Android 13 (एपीआई लेवल 33) या उसके बाद का वर्शन चलता है उन पर Transformer
ऑब्जेक्ट की मदद से, एचडीआर वीडियो में बदलाव किया जा सकता है.
Composition
ऑब्जेक्ट बनाते समय, HDR_MODE_KEEP_HDR
डिफ़ॉल्ट मोड होता है. इसे यहां दिए गए कोड में दिखाया गया है:
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();
मीडिया आइटम तैयार करना
MediaItem
आपके ऐप्लिकेशन में मौजूद किसी ऑडियो या वीडियो आइटम को दिखाता है. EditedMediaItem
, MediaItem
को इकट्ठा करता है. साथ ही, इसमें MediaItem
पर लागू किए जाने वाले बदलावों की जानकारी भी होती है.
किसी वीडियो में काट-छांट करना
वीडियो के अनचाहे हिस्सों को हटाने के लिए, MediaItem
में ClippingConfiguration
जोड़कर, वीडियो के शुरू और खत्म होने की कस्टम पोज़िशन सेट की जा सकती हैं.
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();
पहले से मौजूद इफ़ेक्ट का इस्तेमाल करना
Media3 में, सामान्य बदलावों के लिए कई बिल्ट-इन वीडियो इफ़ेक्ट शामिल हैं. उदाहरण के लिए:
कक्षा | प्रभाव |
---|---|
Presentation |
रिज़ॉल्यूशन या आसपेक्ट रेशियो के हिसाब से मीडिया आइटम को स्केल करना |
ScaleAndRotateTransformation |
मीडिया आइटम का साइज़ बदलना और/या उसे घुमाना |
Crop |
मीडिया आइटम को छोटे या बड़े फ़्रेम में काटना |
OverlayEffect |
मीडिया आइटम के ऊपर टेक्स्ट या इमेज ओवरले जोड़ना |
ऑडियो इफ़ेक्ट के लिए, AudioProcessor
के इंस्टेंस का एक क्रम जोड़ा जा सकता है. इससे रॉ (पीसीएम) ऑडियो डेटा बदल जाएगा. उदाहरण के लिए, ऑडियो चैनलों को मिक्स और स्केल करने के लिए, ChannelMixingAudioProcessor
का इस्तेमाल किया जा सकता है.
इन इफ़ेक्ट का इस्तेमाल करने के लिए, इफ़ेक्ट या ऑडियो प्रोसेसर का एक इंस्टेंस बनाएं. इसके बाद, Effects
का एक इंस्टेंस बनाएं. इसमें वे ऑडियो और वीडियो इफ़ेक्ट शामिल करें जिन्हें आपको मीडिया आइटम पर लागू करना है. इसके बाद, Effects
ऑब्जेक्ट को 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();
कस्टम इफ़ेक्ट बनाना
Media3 में शामिल इफ़ेक्ट को बढ़ाकर, अपने इस्तेमाल के उदाहरणों के हिसाब से कस्टम इफ़ेक्ट बनाए जा सकते हैं. यहां दिए गए उदाहरण में, वीडियो को ज़ूम करके फ़्रेम में फ़िट करने के लिए, subclass
MatrixTransformation
का इस्तेमाल करें. ऐसा वीडियो के चलने के पहले सेकंड में किया जाता है:
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();
किसी इफ़ेक्ट के बिहेवियर को और ज़्यादा पसंद के मुताबिक बनाने के लिए, GlShaderProgram
लागू करें. queueInputFrame()
तरीके का इस्तेमाल, इनपुट फ़्रेम को प्रोसेस करने के लिए किया जाता है. उदाहरण के लिए, MediaPipe की मशीन लर्निंग की सुविधाओं का फ़ायदा पाने के लिए, MediaPipe FrameProcessor
का इस्तेमाल किया जा सकता है. इससे हर फ़्रेम को MediaPipe ग्राफ़ के ज़रिए भेजा जा सकता है. इसका उदाहरण, Transformer डेमो ऐप्लिकेशन में देखें.
इफ़ेक्ट की झलक देखना
ExoPlayer की मदद से, एक्सपोर्ट करने की प्रोसेस शुरू करने से पहले, किसी मीडिया आइटम में जोड़े गए इफ़ेक्ट की झलक देखी जा सकती है. EditedMediaItem
के लिए इस्तेमाल किए गए Effects
ऑब्जेक्ट का इस्तेमाल करके, अपने ExoPlayer इंस्टेंस पर setVideoEffects()
को कॉल करें.
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();
ExoPlayer की मदद से, ऑडियो इफ़ेक्ट की झलक भी देखी जा सकती है. अपना ExoPlayer
इंस्टेंस बनाते समय, एक कस्टम RenderersFactory
पास करें. यह RenderersFactory
, प्लेयर के ऑडियो रेंडरर को कॉन्फ़िगर करता है, ताकि वे AudioSink
को ऑडियो आउटपुट कर सकें. यह AudioSink
, आपकी AudioProcessor
सीक्वेंस का इस्तेमाल करता है. नीचे दिए गए उदाहरण में, हमने DefaultRenderersFactory
के buildAudioSink()
तरीके को बदलकर ऐसा किया है.
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();
ट्रांसफ़ॉर्मेशन शुरू करना
आखिर में, बदलाव लागू करने के लिए Transformer
बनाएं और नतीजे के तौर पर मिले मीडिया आइटम को एक्सपोर्ट करना शुरू करें.
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);
अगर आपको एक्सपोर्ट की प्रोसेस रद्द करनी है, तो Transformer.cancel()
पर क्लिक करें.
प्रोग्रेस से जुड़े अपडेट देखना
Transformer.start
तुरंत जवाब देता है और एसिंक्रोनस तरीके से काम करता है. डेटा ट्रांसफ़ॉर्मेशन की मौजूदा प्रोग्रेस के बारे में क्वेरी करने के लिए, Transformer.getProgress()
को कॉल करें.
यह तरीका ProgressHolder
लेता है. अगर प्रोग्रेस की स्थिति उपलब्ध है, यानी कि अगर यह तरीका PROGRESS_STATE_AVAILABLE
दिखाता है, तो दिए गए ProgressHolder
को प्रोग्रेस के मौजूदा प्रतिशत के साथ अपडेट किया जाएगा.
पूरा होने या गड़बड़ी वाले इवेंट की सूचना पाने के लिए, अपने Transformer
में लिसनर भी अटैच किया जा सकता है.