Media3 Transformer का इस्तेमाल करके वीडियो एडिटिंग के लिए एक बेसिक ऐप्लिकेशन बनाएं

Jetpack Media3 में मौजूद Transformer API को इस तरह से डिज़ाइन किया गया है कि यह मीडिया में बदलाव कर सके बेहतर और भरोसेमंद. ट्रांसफ़ॉर्मर कई कामों में मदद करता है. शामिल हैं:

  • ट्रिम, स्केल, और रोटेट करने की सुविधा के ज़रिए वीडियो में बदलाव करना
  • ओवरले और फ़िल्टर जैसे इफ़ेक्ट जोड़ना
  • एचडीआर और स्लो-मोशन वीडियो जैसे खास फ़ॉर्मैट को प्रोसेस करना
  • बदलाव लागू करने के बाद मीडिया आइटम को एक्सपोर्ट करना

इस पेज पर, आपको सेवा के इस्तेमाल के कुछ अहम उदाहरणों के बारे में बताया गया है. ट्रांसफ़ॉर्मर. ज़्यादा जानकारी के लिए, हमारी पूरी गाइड देखें Media3 ट्रांसफ़ॉर्मर.

शुरू करें

शुरू करने के लिए, ट्रांसफ़ॉर्मर, इफ़ेक्ट, और कॉमन मॉड्यूल पर डिपेंडेंसी जोड़ें Jetpack Media3 का कुल प्लान:

implementation "androidx.media3:media3-transformer:1.4.0"
implementation "androidx.media3:media3-effect:1.4.0"
implementation "androidx.media3:media3-common:1.4.0"

1.4.0 को, लाइब्रेरी. आप प्रॉडक्ट की जानकारी ताकि आप सबसे नया वर्शन देख सकें.

ज़रूरी क्लास

कक्षा मकसद
Transformer ट्रांसफ़ॉर्मेशन को शुरू और बंद करें. साथ ही, हो रहे ट्रांसफ़ॉर्मेशन की प्रोग्रेस से जुड़े अपडेट देखें.
EditedMediaItem यह प्रोसेस करने के लिए मीडिया आइटम और उस पर लागू किए जाने वाले बदलावों को दिखाता है.
Effects ऑडियो और वीडियो इफ़ेक्ट का कलेक्शन.

आउटपुट कॉन्फ़िगर करें

Transformer.Builder की मदद से, अब आप videoMimeType और audioMimetype डायरेक्ट्री को बनाने की ज़रूरत के बिना, फ़ंक्शन सेट करके TransformationRequest ऑब्जेक्ट.

अलग-अलग फ़ॉर्मैट के बीच ट्रांसकोड करें

यहां दिया गया कोड, Transformer ऑब्जेक्ट को कॉन्फ़िगर करने का तरीका बताता है H.265/AVC वीडियो और 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();

अगर इनपुट मीडिया फ़ॉर्मैट पहले से ही, ऑडियो के बदलाव के अनुरोध से मेल खाता है या वीडियो के लिए, ट्रांसफ़ॉर्मर अपने-आप ट्रांसमक्सिंग पर स्विच हो जाता है, यानी कि कॉपी करना इनपुट कंटेनर से आउटपुट कंटेनर में बिना कंप्रेस किए गए सैंपल बदलाव. इससे कंप्यूटेशनल लागत और क्वालिटी में होने वाले नुकसान से बचा जा सकता है उसी फ़ॉर्मैट में डीकोडिंग और री-एन्कोडिंग करते हैं.

एचडीआर मोड सेट करें

अगर इनपुट मीडिया फ़ाइल एचडीआर फ़ॉर्मैट में है, तो इनमें से कुछ में से किसी एक को चुना जा सकता है एचडीआर की जानकारी को प्रोसेस करने के लिए अलग-अलग मोड. आपने शायद 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 FrameProcessor का इस्तेमाल करें. इसका एक उदाहरण ट्रांसफ़ॉर्मर डेमो ऐप्लिकेशन.

इफ़ेक्ट की झलक

ExoPlayer पर, इफ़ेक्ट की झलक देखी जा सकती है एक्सपोर्ट करने की प्रोसेस शुरू करने से पहले, किसी मीडिया आइटम में जोड़ा जाता है. वही तरीका इस्तेमाल किया जा रहा है EditedMediaItem के लिए Effects ऑब्जेक्ट है, अपने इस नंबर पर setVideoEffects() को कॉल करें 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();

ExoPlayer की मदद से, ऑडियो इफ़ेक्ट की झलक भी देखी जा सकती है. अपनी ExoPlayer इंस्टेंस, कस्टम RenderersFactory में पास करें, जो प्लेयर के ऑडियो रेंडरर से, ऑडियो को उस 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 को भेजा जा सकता है.