الخطوات الأولى

تتكون عملية بدء استخدام "Transformer" من الخطوات التالية:

  1. أضف Media3 Transformer كتبعية في مشروعك.
  2. أنشِئ EditedMediaItem يمثّل الوسائط التي ستعالجها وعدِّلها لتطبيقها عليها.
  3. أنشِئ Transformer يصف المخرجات المطلوبة ومستمعًا لأحداث الإكمال والأخطاء.
  4. ابدأ عملية التصدير، مع تمرير EditedMediaItem لتعديل مسار إخراج. أثناء التصدير، يمكنك الاستعلام عن مستوى التقدّم الحالي أو إلغاء العملية.
  5. عند انتهاء عملية التصدير، يمكنك معالجة الناتج حسب الحاجة. على سبيل المثال، يمكنك مشاركة الناتج مع تطبيق آخر أو تحميله على خادم.

يمكنك مواصلة القراءة لمعرفة المزيد من التفاصيل حول هذه الخطوات، والاطّلاع على TransformerActivity في تطبيق المحوِّل التجريبي للاطّلاع على مثال كامل.

إضافة Media3 Transformer كتبعية

أسهل طريقة لبدء استخدام Transformer هي إضافة تبعيات Gradle على المكتبة في ملف build.gradle في وحدة تطبيقك:

Kotlin

implementation("androidx.media3:media3-transformer:1.3.1")
implementation("androidx.media3:media3-effect:1.3.1")
implementation("androidx.media3:media3-common:1.3.1")

رائع

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

حيث يكون 1.3.1 هو الإصدار المفضل لديك. يمكن العثور على أحدث إصدار بالرجوع إلى ملاحظات الإصدار.

يمكن الاطّلاع على مزيد من المعلومات حول وحدات المكتبة المتاحة في صفحة Google Maven AndroidX Media3.

تشغيل دعم Java 8

إذا لم يكن مفعَّلاً، يجب تفعيل التوافق مع Java 8 في جميع ملفات build.gradle التي تعتمد على Transformer عن طريق إضافة ما يلي إلى القسم android:

compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}

بدء عملية تحويل

في ما يلي مثال على إنشاء EditedMediaItem لإزالة الصوت لملف إدخال، ثم إنشاء مثيل Transformer وضبطه لتصدير فيديو H.265/HEVC وإخراج النتيجة إلى outputPath.

Kotlin

val inputMediaItem = MediaItem.fromUri("path_to_input_file")
val editedMediaItem =
    EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()
val transformer = Transformer.Builder(context)
    .setVideoMimeType(MimeTypes.VIDEO_H265)
    .addListener(transformerListener)
    .build()
transformer.start(editedMediaItem, outputPath)

Java

MediaItem inputMediaItem = MediaItem.fromUri("path_to_input_file");
EditedMediaItem editedMediaItem =
    new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();
Transformer transformer =
    new Transformer.Builder(context)
        .setVideoMimeType(MimeTypes.VIDEO_H265)
        .addListener(transformerListener)
        .build();
transformer.start(editedMediaItem, outputPath);

للمزيد من المعلومات حول ملفات الوسائط، يمكنك الاطّلاع على صفحة عناصر وسائط ExoPlayer. يمكن أن يكون الإدخال تقدمًا أو بثًا تكيّفيًا، ولكن البث يكون دائمًا تدريجيًّا. بالنسبة للإدخالات التكيُّفية، يتم دائمًا اختيار المسارات الأعلى دقة لعملية التحويل. ويمكن أن يكون الإدخال بأي تنسيق حاوية متوافقًا مع ExoPlayer، إلا أنّ الناتج دائمًا هو ملف MP4.

يمكنك تنفيذ عمليات تصدير متعددة بشكل تسلسلي على مثيل Transformer نفسه، إلا أنّ عمليات التصدير المتزامنة مع المثيل نفسه غير متاحة.

ملاحظة حول سلاسل المحادثات

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

الاستماع إلى الأحداث

طريقة start غير متزامنة. يتم إرجاع الرسالة على الفور ويتم إبلاغ التطبيق بالأحداث من خلال المستمع الذي يتم تمريره إلى أداة إنشاء Transformer.

Kotlin

val transformerListener: Transformer.Listener =
    object : Transformer.Listener {
  override fun onCompleted(composition: Composition, result: ExportResult) {
    playOutput()
  }

  override fun onError(composition: Composition, result: ExportResult,
                       exception: ExportException) {
    displayError(exception)
  }
}

Java

Transformer.Listener transformerListener =
    new Transformer.Listener() {
      @Override
      public void onCompleted(Composition composition, ExportResult result) {
        playOutput();
      }

      @Override
      public void onError(Composition composition, ExportResult result,
          ExportException exception) {
        displayError(exception);
      }
    };

يتضمن ExportResult معلومات حول ملف الإخراج، بما في ذلك حجم الملف ومتوسط معدل نقل البيانات للصوت والفيديو، حسب الاقتضاء.

تلقّي آخر المعلومات بشأن مستوى التقدّم

استدعِ Transformer.getProgress للاستعلام عن التقدم الحالي في عملية تحويل. وتشير القيمة المعروضة إلى حالة التقدم. إذا كانت حالة التقدم هي PROGRESS_STATE_AVAILABLE، سيتم تحديث ProgressHolder المقدَّمة بالنسبة المئوية للتقدم الحالي. يوضّح المثال التالي كيفية إجراء طلب بحث دوريًا حول مدى تقدّم عملية تحويل، حيث يمكن تنفيذ طريقة updateProgressInUi لتعديل شريط التقدّم.

Kotlin

transformer.start(inputMediaItem, outputPath)
val progressHolder = ProgressHolder()
mainHandler.post(
    object : Runnable {
      override fun run() {
        val progressState: @ProgressState Int = transformer.getProgress(progressHolder)
        updateProgressInUi(progressState, progressHolder)
        if (progressState != Transformer.PROGRESS_STATE_NOT_STARTED) {
          mainHandler.postDelayed(/* r= */this,  /* delayMillis= */500)
        }
      }
    }
)

Java

transformer.start(inputMediaItem, outputPath);
ProgressHolder progressHolder = new ProgressHolder();
mainHandler.post(
    new Runnable() {
      @Override
      public void run() {
        @Transformer.ProgressState int progressState = transformer.getProgress(progressHolder);
        updateProgressInUi(progressState, progressHolder);
        if (progressState != PROGRESS_STATE_NOT_STARTED) {
          mainHandler.postDelayed(/* r= */ this, /* delayMillis= */ 500);
        }
      }
    });

إلغاء عملية تحويل

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