Jetpack Media3 में मौजूद Transformer API, मीडिया एडिट करने की प्रोसेस को बेहतर और भरोसेमंद बनाने के लिए डिज़ाइन किए गए हैं. ट्रांसफ़ॉर्मर में कई तरह के काम किए जा सकते हैं. इनमें ये काम शामिल हैं:
- वीडियो में काट-छांट करके, उसे स्केल करके, और घुमाकर बदलाव करना
- ओवरले और फ़िल्टर जैसे इफ़ेक्ट जोड़ना
- एचडीआर और स्लो-मोशन वीडियो जैसे खास फ़ॉर्मैट को प्रोसेस करना
- बदलाव करने के बाद मीडिया आइटम को एक्सपोर्ट करना
इस पेज पर, Transformer के कुछ मुख्य इस्तेमाल के उदाहरणों के बारे में बताया गया है. ज़्यादा जानकारी के लिए, Media3 ट्रांसफ़ॉर्मर के बारे में पूरी जानकारी देने वाली हमारी गाइड देखें.
शुरू करें
शुरू करने के लिए, 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
की मदद से, अब फ़ंक्शन सेट करके 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();
अगर इनपुट मीडिया फ़ॉर्मैट, ऑडियो या वीडियो के लिए ट्रांसफ़ॉर्मेशन के अनुरोध से पहले से मेल खाता है, तो ट्रांसफ़ॉर्मर अपने-आप ट्रांसम्यूक्सिंग पर स्विच हो जाता है. इसका मतलब है कि कॉम्प्रेस किए गए सैंपल को इनपुट कंटेनर से आउटपुट कंटेनर में बिना किसी बदलाव के कॉपी किया जाता है. इससे, एक ही फ़ॉर्मैट में डिकोड करने और फिर से कोड में बदलने की कंप्यूटेशनल लागत और क्वालिटी में होने वाले संभावित नुकसान से बचा जाता है.
एचडीआर मोड सेट करना
अगर इनपुट मीडिया फ़ाइल 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
में 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 में शामिल इफ़ेक्ट को बढ़ाकर, अपने इस्तेमाल के उदाहरणों के हिसाब से कस्टम इफ़ेक्ट बनाए जा सकते हैं. यहां दिए गए उदाहरण में, वीडियो को ज़ूम करके ज़ूम करने के लिए, सब-क्लास 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 ग्राफ़ के ज़रिए हर फ़्रेम को भेजने के लिए, MediaPipe FrameProcessor
का इस्तेमाल किया जा सकता है. ट्रांसफ़ॉर्मर डेमो ऐप्लिकेशन में इसका एक उदाहरण देखें.
इफ़ेक्ट की झलक देखना
ExoPlayer की मदद से, एक्सपोर्ट की प्रोसेस शुरू करने से पहले, मीडिया आइटम में जोड़े गए इफ़ेक्ट की झलक देखी जा सकती है. उसी Effects
ऑब्जेक्ट का इस्तेमाल करके जिसे EditedMediaItem
के लिए इस्तेमाल किया गया है, अपने 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
को पूरा होने या गड़बड़ी वाले इवेंट के बारे में सूचना पाने के लिए, उसमें लिसनर भी जोड़ा जा सकता है.