כדי להתחיל להשתמש ב-Transformer
, צריך לבצע את השלבים הבאים:
- מוסיפים את Media3 Transformer כתלות בפרויקט.
- יוצרים
EditedMediaItem
שמייצג את המדיה לעיבוד ואת העריכות שרוצים להחיל עליה. - יוצרים
Transformer
, מתארים את הפלט הנדרש ומאזין לאירועי השלמה ושגיאה. - מפעילים את פעולת הייצוא, מעבירים את
EditedMediaItem
לעריכה ואת נתיב הפלט. במהלך הייצוא, אפשר לשלוח שאילתה לגבי ההתקדמות הנוכחית או לבטל את הפעולה. - כשייצוא הנתונים מסתיים, מטפלים בפלט לפי הצורך. לדוגמה, אפשר לשתף את הפלט עם אפליקציה אחרת או להעלות אותו לשרת.
בהמשך המאמר מפורטים השלבים האלה, וב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")
מגניב
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 לא מופעלת, צריך להפעיל אותה בכל הקבצים שתלויים ב-Transformer. לשם כך, מוסיפים את השורה הבאה לקטע: android
build.gradle
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 משרשור יחיד של אפליקציה, והשיטות של listener נקראות באותו שרשור. ברוב המקרים, שרשור הבקשה יכול להיות פשוט השרשור הראשי של האפליקציה. באופן פנימי, רכיב Transformer פועל ברקע ומפרסם את הקריאות שלו לשיטות של listener בשרשור האפליקציה.
האזנה לאירועים
השיטה start
היא אסינכרונית. הפונקציה מחזירה ערך באופן מיידי והאפליקציה מקבלת הודעה על אירועים דרך ה-listener שמועבר אל Transformer
builder.
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
. משאבים כמו רכיבי codec של וידאו בחומרה הם מוגבלים, במיוחד במכשירים ברמה נמוכה, ולכן חשוב לעשות את זה כדי לפנות משאבים אם לא צריך את הפלט.