כדי להתחיל להשתמש ב-Transformer, צריך לבצע את השלבים הבאים:
- מוסיפים את Media3 Transformer כתלות בפרויקט.
- יוצרים
EditedMediaItemשמייצג את המדיה לעיבוד ואת העריכות שרוצים לבצע. - יוצרים
Transformer, מתארים את הפלט הנדרש ומאזין לאירועי השלמה ושגיאה. - מפעילים את פעולת הייצוא, מעבירים את
EditedMediaItemלעריכה ואת נתיב הפלט. במהלך הייצוא, אפשר לשלוח שאילתה לגבי ההתקדמות הנוכחית או לבטל את הפעולה. - כשייצוא הנתונים מסתיים, מטפלים בפלט לפי הצורך. לדוגמה, אפשר לשתף את הפלט עם אפליקציה אחרת או להעלות אותו לשרת.
בהמשך המאמר מפורטים השלבים האלה, ובTransformerActivity באפליקציית ההדגמה של הכלי לשינוי הגדרות אפשר לראות דוגמה מלאה.
הוספת Media3 Transformer כתלות
הדרך הקלה ביותר להתחיל להשתמש ב-Transformer היא להוסיף תלויות של Gradle בספרייה בקובץ build.gradle של מודול האפליקציה:
Kotlin
implementation("androidx.media3:media3-transformer:1.8.0") implementation("androidx.media3:media3-effect:1.8.0") implementation("androidx.media3:media3-common:1.8.0")
גרוב
implementation "androidx.media3:media3-transformer:1.8.0" implementation "androidx.media3:media3-effect:1.8.0" implementation "androidx.media3:media3-common:1.8.0"
כאשר 1.8.0 היא הגרסה המועדפת. כדי לדעת מהי הגרסה העדכנית, אפשר לעיין בהערות לגבי הגרסה.
מידע נוסף על מודולי הספרייה שזמינים מופיע בדף 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 של וידאו בחומרה הם מוגבלים, במיוחד במכשירים ברמה נמוכה, ולכן חשוב לעשות את זה כדי לפנות משאבים אם לא צריך את הפלט.