Jetpack Media3 Transformer מאפשר עריכה, המרה וייצוא של נכסי מדיה ב-Android. בדף הזה מוסבר איך להגדיר טרנספורמציות ליבה:
- טרנסקוד וטרנסמוקס: המרה של פורמטים של אודיו ווידאו, או דילוג על קידוד מחדש באמצעות העתקה של דוגמאות מאגר (טרנסמוקס).
- הסרת טראקים: הסרת טראקים של אודיו או וידאו ממדיה.
- חיתוך ואופטימיזציה: חיתוך של מדיה לפי חותמת זמן, עם אפשרויות לייצוא מהיר יותר באמצעות רשימות עריכה של MP4 ואופטימיזציה של החיתוך.
- אפקטים של וידאו: שינוי גודל, סיבוב או החלת אפקטים מותאמים אישית של OpenGL shader. אפשר גם לראות תצוגה מקדימה ב-ExoPlayer.
- קלט של תמונות: הופכים תמונות סטטיות לקליפים עם משך וקצב פריימים בהתאמה אישית.
- עיבוד אודיו: שרשור של מופעי
AudioProcessorכדי לשנות אודיו גולמי.
המרת קידוד בין פורמטים
כשיוצרים Transformer, אפשר לציין את פורמטי האודיו והווידאו שרוצים ליצור. לדוגמה, הקוד הבא מראה איך להגדיר את 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();
אם פורמט המדיה של קובץ הקלט כבר תואם להגדרות של האודיו או הסרטון, Transformer עובר אוטומטית להעברה של נתונים מפורמט אחד לפורמט אחר, כלומר, הוא מעתיק את הדגימות הדחוסות מהגורם המכיל של קובץ הקלט לגורם המכיל של קובץ הפלט ללא שינוי. כך נמנעת העלות החישובית ואובדן האיכות הפוטנציאלי של פענוח וקידוד מחדש באותו פורמט.
הסרת אודיו או סרטון
כדי להסיר אודיו או וידאו באמצעות 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( MediaItem.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();
רשימות עריכה בפורמט MP4
כדי לקצר את תהליך החיתוך, Transformer תומך ברשימות עריכה של MP4, וכך מאפשר עריכות יעילות יותר של חיתוך בלבד בלי קידוד מחדש של הסרטון כולו. השיטה הזו משתמשת בדגימות מקודדות קיימות ובמודעה לפני סרטון (pre-roll) ברשימת העריכה, שמורה לנגן להתחיל את ההפעלה בנקודה ספציפית, וכך למעשה מדלגת על הקטע הראשוני הלא רצוי.
כדי לבצע עריכות של חיתוך בלבד במהירות גבוהה יותר, מתקשרים אל experimentalSetMp4EditListTrimEnabled(true).
Kotlin
Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build()
Java
new Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).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 מקבל רשימה של אפקטים של אודיו ווידאו להחלה.
באופן פנימי, מסגרת האפקטים של Transformer ממירה את רשימת האפקטים של הסרטון לרצף של תוכניות GL Shader שמוחלות לפי הסדר. במקרים מסוימים, מסגרת האפקטים יכולה להחיל כמה אפקטים באמצעות תוכנית הצללה אחת.
לדוגמה, תוכנית הצללה אחת יכולה להחיל כמה טרנספורמציות מטריצה רצופות, וכך לשפר את היעילות והאיכות.
יש גם תמיכה באפקטים של סרטונים בתצוגה מקדימה ב-ExoPlayer, באמצעות ExoPlayer.setVideoEffects. כדי לראות דוגמה לשימוש ב-API הזה, אפשר לעיין באפליקציית ההדגמה של האפקט.
אפליקציית ההדגמה כוללת דוגמאות לאפקטים מותאמים אישית של וידאו.
קלט תמונה
מודל Transformer תומך בקלט של תמונות על ידי טיפול בהן כקליפים סטטיים. כדי להגדיר תמונה כמקור קלט, פועלים לפי השלבים הבאים:
יצירת
MediaItemבאמצעותMediaItem.Builder. מציינים את משך ההצגה של התמונה בסרטון הפלט באמצעות קריאה ל-setImageDurationMs.יוצרים
EditedMediaItemשעוטף אתMediaItem. מציינים את קצב הפריימים של הווידאו בסטרימינג שנוצר באמצעותEditedMediaItem.Builder#setFrameRate.
בדוגמה הבאה מוסבר איך להגדיר קלט של תמונה כדי ליצור סרטון באורך 5 שניות בקצב של 30 פריימים לשנייה:
Kotlin
val imageMediaItem = MediaItem.Builder() .setUri(imageUri) .setImageDurationMs(5000) // 5 seconds .build() val editedImageItem = EditedMediaItem.Builder(imageMediaItem) .setFrameRate(30) // 30 frames per second .build()
Java
MediaItem imageMediaItem = new MediaItem.Builder() .setUri(imageUri) .setImageDurationMs(5000) // 5 seconds .build(); new EditedMediaItem.Builder(imageMediaItem) .setFrameRate(30) // 30 frames per second .build();
עריכות אודיו
אפקטים קוליים מיושמים על ידי הפעלה של רצף של AudioProcessorמופעים על אודיו גולמי (PCM). ExoPlayer תומך בהעברת מעבדי אודיו אל DefaultAudioSink.Builder, מה שמאפשר לראות תצוגה מקדימה של עריכות אודיו.