البدء

يتضمّن البدء في استخدام 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.7.1")
implementation("androidx.media3:media3-effect:1.7.1")
implementation("androidx.media3:media3-common:1.7.1")

Groovy

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

حيث 1.7.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. تكون الموارد، مثل برامج الترميز والفيديو للأجهزة، محدودة، خاصةً على الأجهزة المنخفضة المواصفات، لذا من المهم إجراء ذلك لإتاحة الموارد إذا لم تكن هناك حاجة إلى الإخراج.