חדשות על מוצרים

‫Media3 1.9.0 – מה חדש

משך הקריאה: 6 דקות
צפייה בפרופיל של Kristina Simakova
Kristina Simakova מנהל הנדסה

גרסה Media3 1.9.0 יצאה! בנוסף לתיקוני הבאגים ולשיפורי הביצועים הרגילים, הגרסה האחרונה כוללת גם ארבעה מודולים חדשים או מודולים שנכתבו מחדש במידה רבה:

  • media3-inspector – חילוץ מטא-נתונים ופריימים מחוץ להפעלה
  • media3-ui-compose-material3 – בניית ממשק משתמש בסיסי של Material3 Compose Media בכמה שלבים בלבד
  • media3-cast – טיפול אוטומטי במעברים בין Cast להפעלות מקומיות
  • media3-decoder-av1 – הפעלה עקבית של AV1 עם מפענח התוסף שנכתב מחדש על סמך ספריית dav1d

הוספנו גם שיפורים במטמון ובניהול הזיכרון ב-PreloadManager, וסיפקנו כמה שיפורים חדשים ב-ExoPlayer, ב-Transformer וב-MediaSession

בנוסף, בגרסה הזו תקבלו גישה ניסיונית ראשונה ל-CompositionPlayer כדי לראות תצוגה מקדימה של עריכות מדיה.  


בהמשך המאמר מפורט מידע נוסף, וכמו תמיד, מומלץ לעיין בהערות המלאות על הגרסה כדי לקבל סקירה מקיפה של השינויים בגרסה הזו.

חילוץ מטא-נתונים ומסגרות מחוץ להפעלה

יש הרבה מקרים שבהם רוצים לבדוק מדיה בלי להתחיל הפעלה. לדוגמה, יכול להיות שתרצו לזהות אילו פורמטים הוא מכיל או מה משך הזמן שלו, או לאחזר תמונות ממוזערות.

במודול החדש media3-inspector ריכזנו במקום אחד את כל כלי השירות לבדיקת מדיה בלי הפעלה:

  • MetadataRetriever כדי לקרוא את משך הזמן, הפורמט והמטא-נתונים הסטטיים מתוך MediaItem.
  • FrameExtractor כדי לקבל פריימים או תמונות ממוזערות מפריט.
  • MediaExtractorCompat כתחליף ישיר למחלקה MediaExtractor בפלטפורמת Android, כדי לקבל מידע מפורט על דוגמאות בקובץ.

MetadataRetriever ו-FrameExtractor פועלים לפי דפוס פשוט של AutoCloseable. לפרטים נוספים, אפשר לעיין בדפי המדריך החדשים.

suspend fun extractThumbnail(mediaItem: MediaItem) {

  FrameExtractor.Builder(context, mediaItem).build().use {

    val thumbnail = frameExtractor.getThumbnail().await()

  } 

}

יצירת ממשק משתמש בסיסי של Material3 Compose Media בכמה שלבים פשוטים

בגרסאות קודמות התחלנו לספק קוד מחבר בין רכיבי ממשק המשתמש של Compose לבין מופע הנגן שלכם. בגרסה Media3 1.9.0, הוספנו מודול חדש media3-ui-compose-material3 עם לחצנים ורכיבי תוכן בסגנון Material3. הם מאפשרים לכם ליצור ממשק משתמש של מדיה בכמה שלבים פשוטים, ועדיין מספקים את כל הגמישות להתאמה אישית של הסגנון. אם אתם מעדיפים ליצור סגנון משלכם לממשק המשתמש, אתם יכולים להשתמש באבני הבניין שמטפלות בכל הלוגיקה של העדכון והחיבור, כך שאתם צריכים להתרכז רק בעיצוב של רכיב ממשק המשתמש. כדאי לעיין בדפי המדריך המורחבים שלנו בנושא מודולים של ממשק המשתמש של Compose.

אנחנו גם ממשיכים לעבוד על עוד רכיבים של Compose, כמו סרגל חיפוש מוכן מראש, תחליף מלא ומוכן לשימוש ל-PlayerView, וגם שילוב של כתוביות ומודעות.

@Composable
fun SimplePlayerUI(player: Player, modifier: Modifier = Modifier) {
  Column(modifier) {
    ContentFrame(player)  // Video surface and shutter logic
    Row (Modifier.align(Alignment.CenterHorizontally)) {                 
      SeekBackButton(player)   // Simple controls
      PlayPauseButton(player)
      SeekForwardButton(player)
    }
  }
}

 

image.png

ממשק משתמש פשוט של נגן Compose עם רכיבים מוכנים לשימוש

טיפול אוטומטי במעברים בין Cast להפעלות מקומיות

ה-CastPlayer במודול media3-cast נכתב מחדש כדי לטפל אוטומטית במעברים בין הפעלה מקומית (לדוגמה, באמצעות ExoPlayer) לבין הפעלה מרחוק באמצעות Cast.

כשמגדירים את MediaSession, פשוט יוצרים CastPlayer סביב ExoPlayer, מוסיפים MediaRouteButton לממשק המשתמש וזהו!

// MediaSession setup with CastPlayer 

val exoPlayer = ExoPlayer.Builder(context).build()

val castPlayer = CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build()

val session = MediaSession.Builder(context, castPlayer).build()

// MediaRouteButton in UI 

@Composable fun UIWithMediaRouteButton() {

  MediaRouteButton()

}
image.png

שילוב חדש של CastPlayer באפליקציית ההדגמה של סשן Media3

הפעלה עקבית של AV1 באמצעות התוסף שנכתב מחדש על סמך dav1d

גרסה 1.9.0 כוללת מודול הרחבה AV1 שנכתב מחדש לגמרי ומבוסס על הספרייה הפופולרית dav1d

כמו בכל מודולי הפענוח של התוספים, חשוב לזכור שנדרש בנייה ממקור כדי לארוז את קוד Native הרלוונטי בצורה נכונה. חבילת מפענח מספקת עקביות ותמיכה בפורמטים בכל המכשירים, אבל מכיוון שהיא מפעילה את הפענוח בתהליך שלכם, היא מתאימה במיוחד לתוכן שאתם יכולים לסמוך עליו. 

שילוב של שמירה במטמון וניהול זיכרון ב-PreloadManager

שיפרנו גם את PreloadManager. הוא כבר מאפשר לכם לטעון מראש מדיה לזיכרון מחוץ להפעלה, ואז להעביר אותה בצורה חלקה לנגן כשצריך. למרות שהביצועים היו טובים, עדיין היה צריך להיזהר שלא לחרוג ממגבלות הזיכרון בטעינה מראש של יותר מדי נתונים בטעות. לכן, בגרסה Media3 1.9.0 הוספנו שני מאפיינים שהופכים את התהליך הזה להרבה יותר קל ויציב:

  1. תמיכה בשמירת נתונים במטמון – כשמגדירים את טווח הטעינה מראש, אפשר עכשיו לבחור PreloadStatus.specifiedRangeCached(0, 5000) כמצב יעד לפריטים שנטענו מראש. הפעולה הזו תוסיף את הטווח שצוין למטמון בדיסק במקום לטעון את הנתונים לזיכרון. כך אפשר לספק טווח גדול יותר של פריטים לטעינה מראש, כי הפריטים שמרוחקים יותר מהפריט הנוכחי לא צריכים יותר לתפוס זיכרון. שימו לב: כדי לעשות זאת, צריך להגדיר Cache ב-DefaultPreloadManager.Builder.
  2. ניהול זיכרון אוטומטי – עדכנו גם את ממשק LoadControl כדי לטפל טוב יותר במקרה של טעינה מראש, כך שעכשיו אפשר להגדיר מגבלת זיכרון עליונה מפורשת לכל הפריטים שנטענו מראש בזיכרון. ברירת המחדל היא 144 MB, ואפשר להגדיר את המגבלה ב-DefaultLoadControl.Builder. הדפדפן DefaultPreloadManager יפסיק אוטומטית את הטעינה מראש כשהמגבלה תושג, וישחרר אוטומטית זיכרון של פריטים בעדיפות נמוכה יותר אם יהיה צורך בכך.

הסתמכות על התנהגויות ברירת מחדל חדשות ופשוטות יותר ב-ExoPlayer

כמו תמיד, הוספנו גם הרבה שיפורים מצטברים ל-ExoPlayer. כדי לתת כמה דוגמאות:

  • השתקה וביטול ההשתקה – כבר הייתה לנו שיטה setVolume, אבל עכשיו הוספנו את השיטות הנוחות mute ו-unmute כדי לשחזר בקלות את עוצמת הקול הקודמת בלי שתצטרכו לעקוב אחריה בעצמכם.
  • זיהוי נגן תקוע – במקרים נדירים, הנגן עלול להיתקע במצב של אחסון בזיכרון או הפעלה ללא התקדמות, למשל בגלל בעיות בקודק או הגדרות שגויות. המשתמשים שלכם יתעצבנו, אבל אתם לא תראו את הבעיות האלה בניתוח הנתונים. כדי להבהיר את זה, הנגן מדווח עכשיו על StuckPlayerException כשהוא מזהה מצב תקוע.
  • חסימת מצב שינה כברירת מחדל – בעבר, ניהול חסימת מצב שינה היה אופציונלי, ולכן היה קשה למצוא מקרים קיצוניים שבהם התקדמות ההפעלה יכולה להתעכב מאוד כשהיא מתבצעת ברקע. התכונה הזו היא עכשיו אופציונלית, כך שלא צריך לדאוג לגביה, ואפשר גם להסיר את כל הטיפול הידני בחסימת מצב שינה בזמן ההפעלה.
  • הגדרה פשוטה יותר ללוגיקה של לחצן הכתוביות – שינוי TrackSelectionParameters ל "הפעלה או השבתה של כתוביות" היה קשה באופן מפתיע, לכן הוספנו אפשרות פשוטה של ערך בוליאני selectTextByDefault לתרחיש השימוש הזה.

שינוי ההעדפות של כפתורי המדיה ב-MediaSession

עד עכשיו, כדי להגדיר אילו כפתורים יוצגו במגירת ההתראות על מדיה ב-Android Auto או ב-WearOS, היה צריך להגדיר פקודות וכפתורים בהתאמה אישית, גם אם רציתם רק להפעיל שיטה רגילה של נגן.

ב-Media3 1.9.0 יש פונקציונליות חדשה שהופכת את התהליך הזה להרבה יותר פשוט – עכשיו אפשר להגדיר את ההעדפות של כפתורי המדיה באמצעות פקודה רגילה של נגן, בלי שנדרש טיפול בפקודות בהתאמה אישית.

session.setMediaButtonPreferences(listOf(
    CommandButton.Builder(CommandButton.ICON_FAST_FORWARD) // choose an icon
      .setDisplayName(R.string.skip_forward)
      .setPlayerCommand(Player.COMMAND_SEEK_FORWARD) // choose an action 
      .build()
))
image.png

העדפות של כפתורי מדיה עם כפתור להעברה מהירה

‫CompositionPlayer לתצוגה מקדימה בזמן אמת

בגרסה 1.9.0 מוצג CompositionPlayer עם ההערה החדשה @ExperimentalApi. ההערה מציינת שהתכונה זמינה לניסויים, אבל היא עדיין נמצאת בפיתוח. 

CompositionPlayer הוא רכיב חדש בממשקי ה-API לעריכה של Media3, שנועד לתצוגה מקדימה בזמן אמת של עריכות במדיה. ‫Player ממשק Media3 המוכר, CompositionPlayer מאפשר למשתמשים לראות את השינויים בפעולה לפני שהם מתחייבים לתהליך הייצוא. הוא משתמש באותו אובייקט Composition שמעבירים אל Transformer לייצוא, וכך מייעל את תהליך העריכה על ידי איחוד מודל הנתונים לתצוגה מקדימה ולייצוא.

מומלץ להתחיל להשתמש ב-CompositionPlayer ולשתף איתנו משוב. פרטים נוספים יפורסמו בהמשך בפוסטים ובעדכונים של המסמכים.

‫InAppMuxer כברירת מחדל של Muxer ב-Transformer

‫Transformer משתמש עכשיו ב-InAppMp4Muxer כברירת המחדל למיקסר לכתיבת קובצי קונטיינר של מדיה. באופן פנימי, InAppMp4Muxer מסתמך על מודול Media3 Muxer, ומספק התנהגות עקבית בכל גרסאות ה-API. 

שימו לב: למרות שאפליקציית Transformer לא משתמשת יותר ב-MediaMuxer של פלטפורמת Android כברירת מחדל, אתם עדיין יכולים לספק FrameworkMuxer.Factory באמצעות setMuxerFactory אם זה נדרש לתרחיש השימוש שלכם.

ממשקי API חדשים לשינוי מהירות

בגרסה 1.9.0 פישטנו את ממשקי ה-API להתאמת מהירות לעריכת מדיה. הוספנו שיטות חדשות ישירות ב-EditedMediaItem.Builder כדי לשלוט במהירות, וכך הפכנו את ה-API לאינטואיטיבי יותר. עכשיו אפשר לשנות את המהירות של קליפ באמצעות קריאה ל-setSpeed(SpeedProvider provider) ב-EditedMediaItem.Builder:

val speedProvider = object : SpeedProvider {
    override fun getSpeed(presentationTimeUs: Long): Float {
        return speed
    }

    override fun getNextSpeedChangeTimeUs(timeUs: Long): Long {
        return C.TIME_UNSET
    }
}

EditedMediaItem speedEffectItem = EditedMediaItem.Builder(mediaItem)
    .setSpeed(speedProvider)
    .build()

הגישה החדשה הזו מחליפה את השיטה הקודמת של שימוש ב-Effects#createExperimentalSpeedChangingEffects(), שהוצאה משימוש ותוסר בגרסה עתידית.

חדש: סוגי טראקים לרכיב EditedMediaItemSequence 

בגרסה 1.9.0, EditedMediaItemSequence מחייב לציין את סוגי המסלולים הרצויים של הפלט במהלך יצירת הרצף. השינוי הזה מבטיח שהטיפול ברצועות יהיה מפורש ואמין יותר בכל הקומפוזיציה. 

הפעולה הזו מתבצעת באמצעות constructor חדש של EditedMediaItemSequence.Builder שמקבל קבוצה של סוגי טראקים (לדוגמה, C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO). 

כדי לפשט את תהליך היצירה, הוספנו שיטות סטטיות חדשות ונוחות:

  • EditedMediaItemSequence.withAudioFrom(List<EditedMediaItem>)
  • EditedMediaItemSequence.withVideoFrom(List<EditedMediaItem>)
  • EditedMediaItemSequence.withAudioAndVideoFrom(List<EditedMediaItem>)

מומלץ לעבור אל הקונסטרוקטור החדש או אל שיטות הנוחות כדי להגדיר רצפים בצורה ברורה ואמינה יותר.

דוגמה ליצירת רצף של מודעות וידאו בלבד:

EditedMediaItemSequence videoOnlySequence =
    EditedMediaItemSequence.Builder(setOf(C.TRACK_TYPE_VIDEO))
        .addItem(editedMediaItem)
        .build()

אם נתקלתם בבאגים, או אם יש לכם שאלות או בקשות להוספת תכונות, אתם מוזמנים לפנות אלינו דרך כלי המעקב אחר בעיות ב-Media3. נשמח לשמוע ממך.

נכתב על ידי:
להמשך קריאה