عمليات التحويل

تحويل الترميز بين التنسيقات

يمكنك تحديد تنسيقات الإخراج الصوتي والفيديو التي تريد إنتاجها عند إنشاء Transformer. على سبيل المثال، يوضح الرمز التالي كيفية ضبط المحوّل لإخراج فيديو H.264/AVC وصوت AAC:

Kotlin

Transformer.Builder(context)
    .setVideoMimeType(MimeTypes.VIDEO_H264)
    .setAudioMimeType(MimeTypes.AUDIO_AAC)
    .build()

Java

new Transformer.Builder(context)
    .setVideoMimeType(MimeTypes.VIDEO_H264)
    .setAudioMimeType(MimeTypes.AUDIO_AAC)
    .build();

وإذا كان تنسيق وسائط الإدخال يتطابق مع إعدادات الصوت أو الفيديو، سيتم تبديل "المحوّل" تلقائيًا إلى تحويل الصوت إلى نص، أي نسخ العيّنات المضغوطة من حاوية الإدخال إلى حاوية الإخراج بدون تعديل. فهذا يتجنب التكلفة الحاسوبية وفقدان الجودة المحتمل لفك الترميز وإعادة الترميز بالتنسيق نفسه.

إزالة الصوت أو الفيديو

إزالة الصوت أو الفيديو باستخدام EditedMediaItem.Builder، على سبيل المثال:

Kotlin

EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()

Java

new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();

قطع مقطع

يمكنك إزالة أي وسائط خارج الطوابع الزمنية المحدّدة للبداية والنهاية من خلال ضبط إعدادات الاقتصاص على عنصر وسائط الإدخال. على سبيل المثال، لإنشاء مقطع يحتوي فقط على وسائط تتراوح مدّتها بين 10 ثوانٍ و20 ثانية:

Kotlin

val inputMediaItem = MediaItem.Builder()
    .setUri(uri)
    .setClippingConfiguration(
        ClippingConfiguration.Builder()
            .setStartPositionMs(10_000)
            .setEndPositionMs(20_000)
            .build())
    .build()

Java

MediaItem inputMediaItem =
    new MediaItem.Builder()
        .setUri(uri)
        .setClippingConfiguration(
            new MediaItem.ClippingConfiguration.Builder()
                .setStartPositionMs(10_000)
                .setEndPositionMs(20_000)
                .build())
        .build();

تحسين عمليات القطع

لتقليل وقت الاستجابة لقطع بداية الفيديو، يجب تفعيل ميزة تحسين القطع.

Kotlin

Transformer.Builder(context)
    .experimentalSetTrimOptimizationEnabled(true)
    .build()

Java

new Transformer.Builder(context)
    .experimentalSetTrimOptimizationEnabled(true)
    .build();

يؤدي ذلك إلى تسريع عملية التصدير من خلال فك الترميز وإعادة ترميز أقل قدر ممكن من محتوى الفيديو، ثم دمج البيانات المُعاد ترميزها مع باقي الفيديو الأصلي. يعتمد التحسين على إمكانية دمج جزء من ملف الإدخال باستخدام إخراج تم ترميزه حديثًا، ما يعني أنّ تنسيق الإخراج في برنامج الترميز وتنسيق الإدخال يجب أن يكونا متوافقَين. على سبيل المثال، إذا تم إنشاء الملف في الأصل على جهاز بتطبيق برنامج ترميز مختلف، من المرجح ألا تتمكن من تطبيق التحسين. لكي تنجح عملية التحسين، يجب أن يحتوي برنامج الترميز الذي يتم تقديمه إلى Transformer عبر EncoderFactory على مستوى وملف شخصي متوافقَين مع تنسيق الإدخال.

لا يعمل هذا التحسين إلا مع إدخالات MP4 لمادة عرض واحدة بدون أي تأثيرات، باستثناء أي تأثيرات فيديو تشغيلية وعمليات تدوير قابلة للقسمة على 90 درجة. إذا تعذّر التحسين، يعود Transformer تلقائيًا إلى التصدير العادي، ويُبلغ عن نتيجة التحسين في ExportResult.OptimizationResult.

نحن نتحقق من صحة هذه الوظيفة ونتوقع أن تصبح غير تجريبية في إصدار لاحق.

تعديلات الفيديوهات

EditedMediaItems لديه قوائم بمعالجات الصوت وتأثيرات الفيديو المطلوب تطبيقها بالترتيب. تتضمن المكتبة تنفيذ تأثيرات الفيديو لحالات الاستخدام الشائعة، أو يمكنك كتابة تأثيرات مخصّصة وتمريرها عند إنشاء عناصر وسائط معدَّلة.

يمكنك إعادة ضبط حجم الوسائط، ما يفيد في توفير موارد المعالجة أو معدّل نقل البيانات عند التعامل مع مدخلات ذات دقة عالية للغاية، مثل فيديو بدقة 4k أو 8K. على سبيل المثال، لضبط الحجم بالتناسب إلى ارتفاع 480 بكسل:

Kotlin

EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(Effects(
        /* audioProcessors= */ listOf(),
        /* videoEffects= */ listOf(Presentation.createForHeight(480))
    )).build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(new Effects(
        /* audioProcessors= */ ImmutableList.of(),
        /* videoEffects= */ ImmutableList.of(Presentation.createForHeight(480))))
    .build();

وبدلاً من ذلك، يمكنك القياس حسب عامل معيّن، على سبيل المثال، لخفض الحجم إلى النصف:

Kotlin

val editedMediaItem = EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(Effects(
        /* audioProcessors= */ listOf(),
        /* videoEffects= */ listOf(
            ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build())
    )).build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(new Effects(
        /* audioProcessors= */ ImmutableList.of(),
        /* videoEffects= */ ImmutableList.of(
            new ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build())))
    .build();

يمكنك ضبط التدوير بالطريقة نفسها:

Kotlin

EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(Effects(
        /* audioProcessors= */ listOf(),
        /* videoEffects= */ listOf(
            ScaleAndRotateTransformation.Builder()
                .setRotationDegrees(90f)
                .build())
    )).build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(new Effects(
        /* audioProcessors= */ ImmutableList.of(),
        /* videoEffects= */ ImmutableList.of(
            new ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build())))
    .build();

تأثيرات الفيديو المخصّصة

تقبل الدالة الإنشائية Effects قائمة بتأثيرات الصوت والفيديو لتطبيقها. داخليًا، يحوّل إطار عمل تأثيرات التحويل قائمة تأثيرات الفيديو إلى سلسلة من برامج تظليل GL التي يتم تطبيقها بالترتيب. في بعض الحالات، يمكن لإطار التأثيرات تطبيق تأثيرات متعددة باستخدام برنامج تظليل واحد. على سبيل المثال، يمكن لبرنامج مظلل واحد تطبيق عدة تحويلات متتالية في المصفوفات، مما يحسن الكفاءة والجودة.

يمكن أيضًا معاينة تأثيرات الفيديو في ExoPlayer باستخدام ExoPlayer.setVideoEffects.

يتضمّن تطبيق العرض التوضيحي أمثلة على تأثيرات الفيديو المخصّصة.

تعديلات الصوت

يتم تنفيذ التأثيرات الصوتية من خلال تطبيق سلسلة من مثيلات AudioProcessor على الصوت الأولي (PCM). يدعم ExoPlayer تمرير معالجات الصوت إلى DefaultAudioSink.Builder، ما يسمح بمعاينة تعديلات الصوت.