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

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

כשיוצרים 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, מה שמאפשר לראות תצוגה מקדימה של עריכות אודיו.