טרנספורמציות

המרת קידוד בין פורמטים

כשיוצרים טרנספורמציה, אפשר לציין את פורמטי האודיו והווידאו של הפלט שרוצים ליצור. לדוגמה, הקוד הבא מראה איך להגדיר את 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 עובר אוטומטית לשינוי פורמט (transmuxing), כלומר, הוא מעתיק את הדגימות הדחוסות מהקונטיינר של הקלט לקונטיינר של הפלט בלי לבצע שינויים. כך נמנעת עלות החישוב ואובדן האיכות הפוטנציאליים של פענוח וקידוד מחדש באותו פורמט. ## הסרת אודיו או סרטון {: #remove-audio-video} כדי להסיר אודיו או סרטון, משתמשים ב-`EditedMediaItem.Builder`, לדוגמה:

Kotlin

EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()

Java

new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();
## חיתוך קליפ {: #trim } אפשר להסיר מדיה שלא נכללת בטווח של חותמות זמן ספציפיות של התחלה וסיום, על ידי הגדרת החיתוך בפריט המדיה של הקלט. לדוגמה, כדי ליצור קליפ שמכיל רק את המדיה בין 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 {: #mp4-edit-lists } כדי לבצע חיתוך מהיר יותר, Transformer תומך ברשימות עריכה של MP4, ומאפשר עריכות יעילות יותר של חיתוך בלבד ללא המרת קידוד מלאה של הסרטון. השיטה הזו משתמשת בדגימות מקודדות קיימות וב'פרסומת לפני הסרטון' ברשימת העריכה, שמורה לנגן להתחיל את ההפעלה בנקודה ספציפית, וכך למעשה מדלגת על הפלח הראשוני הלא רצוי. כדי לבצע עריכות של חיתוך בלבד במהירות גבוהה משמעותית, צריך להפעיל את הפונקציה `experimentalSetMp4EditListTrimEnabled(true)`.

Kotlin

Transformer.Builder(context)
    .experimentalSetMp4EditListTrimEnabled(true)
    .build()

Java

new Transformer.Builder(context)
    .experimentalSetMp4EditListTrimEnabled(true)
    .build();
חשוב לציין שלא כל נגני המדיה תומכים במיקום 'לפני הסרטון'. המשמעות היא שכאשר משתמשים בנגן כזה, ההפעלה של הקובץ תתחיל מההתחלה המוחלטת של הדגימה המקודדת, ללא קשר למידע ברשימת העריכה שאולי מציין נקודת התחלה שונה. זהירות: חיתוך סרטון לרוב מרמז על הסרה סופית של קטעים לא רצויים. עם זאת, שימוש ברשימות עריכה יוצר סיכון לפרטיות: יכול להיות שמשתמשים ישתפו בלי לדעת מידע רגיש שנמחק, שמוסתר במיקום של הפרסומת שלפני הסרטון. ## אופטימיזציה של חיתוך {: #trim-optimization } כדי לצמצם את זמן האחזור של חיתוך ההתחלה של סרטון, מפעילים אופטימיזציה של חיתוך.

Kotlin

Transformer.Builder(context)
    .experimentalSetTrimOptimizationEnabled(true)
    .build()

Java

new Transformer.Builder(context)
    .experimentalSetTrimOptimizationEnabled(true)
    .build();
כך הייצוא מהיר יותר כי המערכת מפענחת ומקודדת מחדש כמה שפחות מהסרטון, ואז משלבת את הנתונים המקודדים מחדש עם שאר הסרטון המקורי. האופטימיזציה מתבססת על היכולת לחבר חלק מקובץ הקלט עם פלט חדש ומקודד, כלומר פורמט הפלט של המקודד ופורמט הקלט חייבים להיות תואמים. לכן, לדוגמה, אם הקובץ נוצר במקור במכשיר עם הטמעה שונה של מקודד, סביר להניח שלא תהיה אפשרות להחיל את האופטימיזציה. כדי שהאופטימיזציה תצליח, למקודד שמועבר ל-Transformer דרך ‎`EncoderFactory` ‎ צריכות להיות רמה ופרופיל שתואמים לפורמט הקלט. האופטימיזציה הזו פועלת רק עם קלט MP4 של נכס יחיד ללא אפקטים, למעט אפקטים של וידאו ללא פעולה וסיבובים שמתחלקים ב-90 מעלות. אם האופטימיזציה נכשלת, Transformer חוזר אוטומטית לייצוא רגיל ומדווח על התוצאה של האופטימיזציה ב-ExportResult.OptimizationResult. אנחנו בודקים את הפונקציונליות הזו, ואנחנו צופים שהיא תהפוך ללא ניסיונית בגרסה מאוחרת יותר. ## עריכות של סרטונים {: #video-edits } ב-`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();
### אפקטים מותאמים אישית לווידאו {: #custom-video } הקונסטרוקטור `Effects` מקבל רשימה של אפקטים של אודיו ווידאו להחלה. באופן פנימי, מסגרת האפקטים של Transformer ממירה את רשימת האפקטים של הסרטון לרצף של תוכניות GL Shader שמוחלות לפי הסדר. במקרים מסוימים, מסגרת האפקטים יכולה להחיל כמה אפקטים באמצעות תוכנית הצללה אחת. לדוגמה, תוכנית הצללה אחת יכולה להחיל כמה טרנספורמציות של מטריצות ברצף, מה שמשפר את היעילות והאיכות. יש גם תמיכה באפקטים של וידאו בתצוגה מקדימה ב-ExoPlayer, באמצעות ‏`ExoPlayer.setVideoEffects`. כדי לראות דוגמה לשימוש ב-API הזה, אפשר לעיין ב[אפליקציית ההדגמה של האפקטים][effect-demo-app]. [אפליקציית ההדגמה](demo-application) כוללת דוגמאות לאפקטים מותאמים אישית בסרטונים. ## קלט של תמונות {: #image-input } הכלי 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();

EditedMediaItem editedImageItem = new EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build();

עריכות אודיו

אפקטים של אודיו מיושמים על ידי הפעלה של רצף של AudioProcessor מופעים על אודיו גולמי (PCM). ‫ExoPlayer תומך בהעברת מעבדי אודיו אל DefaultAudioSink.Builder, מה שמאפשר לראות תצוגה מקדימה של עריכות אודיו.