חריגה ממכסת האחסון הזמני

Joe Medley
Joe Medley

אם אתם עובדים עם תוספים של מקורות מדיה (MSE), תצטרכו לטפל בסופו של דבר במצב שבו מאגר הנתונים (buffer) מלא מדי. במקרה כזה, תקבלו QuotaExceededError. במאמר הזה אסקור כמה מהדרכים להתמודד עם הבעיה.

מהי השגיאה QuotaExceededError?

בעיקרון, QuotaExceededError הוא מה שמקבלים אם מנסים להוסיף יותר מדי נתונים לאובייקט SourceBuffer. (הוספת אובייקטים נוספים מסוג SourceBuffer לאלמנט הורה מסוג MediaSource עלולה גם לגרום לשגיאה הזו. זה לא נכלל במאמר הזה.) אם יש ב-SourceBuffer יותר מדי נתונים, קריאה ל-SourceBuffer.appendBuffer() תגרום להצגת ההודעה הבאה בחלון המסוף של Chrome.

שגיאה במסוף המכסות.

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

מכסה של חלון השעון.

שנית, אין דרך ודאית לברר כמה נתונים SourceBuffer יכול לטפל בהם.

ההתנהגות בדפדפנים אחרים

נכון למועד כתיבת המאמר, ב-Safari לא מתקבלת הודעת השגיאה QuotaExceededError בחלק גדול מהגרסאות ה-build שלו. במקום זאת, היא מסירה פריימים באמצעות אלגוריתם דו-שלבי, ונעצרת אם יש מספיק מקום לטפל ב-appendBuffer(). קודם כל, המערכת משחררת פריימים שנוצרו בין 0 ל-30 שניות לפני השעה הנוכחית, בקטעים של 30 שניות. לאחר מכן, הוא משחרר פריימים במקטעים של 30 שניות ממשך הזמן אחורה עד ל-30 שניות לאחר currentTime. מידע נוסף זמין בשינוי ב-Webkit משנת 2014.

למזל, בנוסף ל-Chrome, גם Edge ו-Firefox גורמים לשגיאה הזו. אם אתם משתמשים בדפדפן אחר, תצטרכו לבצע את הבדיקה בעצמכם. בדיקת מגבלת מאגר המקור של François Beaufort היא לא בדיוק מה שתיצרו לנגן מדיה בעולם האמיתי, אבל היא לפחות מאפשרת לכם לראות את ההתנהגות.

כמה נתונים אפשר לצרף?

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

Chrome Chromecast* Firefox Safari Edge
וידאו 150MB 30MB 100MB 290MB לא ידוע
אודיו 12MB 2MB 15MB 14MB לא ידוע
  • או מכשיר Chrome אחר עם זיכרון מוגבל.

אז מה עושים?

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

יש כמה גישות לטיפול ב-QuotaExceededError. בפועל, השילוב של גישה אחת או יותר הוא הפתרון הטוב ביותר. הגישה שלכם צריכה לבסס את העבודה על כמות השליפה והניסיון לצרף מעבר ל-HTMLMediaElement.currentTime ולשנות את הגודל על סמך QuotaExceededError. בנוסף, שימוש במניפסט מסוג כלשהו, כמו קובץ mpd (MPEG-DASH) או קובץ m3u8 (HLS), יכול לעזור לכם לעקוב אחרי הנתונים שאתם מוסיפים למאגר.

עכשיו נבחן כמה גישות לטיפול ב-QuotaExceededError.

  • מסירים נתונים מיותרים ומצרפים אותם מחדש.
  • הוספת קטעים קטנים יותר.
  • להקטין את רזולוציית ההפעלה.

אפשר להשתמש בהן בשילוב, אבל אדבר עליהן אחת אחרי השנייה.

הסרת נתונים לא נחוצים והוספה מחדש

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

הסרת נתונים מהזמן האחרון היא לא עניין פשוט של קריאה ל-SourceBuffer.remove(). כדי להסיר נתונים מה-SourceBuffer, דגל העדכון שלו צריך להיות שקר. אם הוא לא משויך, צריך להתקשר למספר SourceBuffer.abort() לפני שמסירים נתונים.

יש כמה דברים שכדאי לזכור כשקוראים ל-SourceBuffer.remove().

  • עלולה להיות לכך השפעה שלילית על ההפעלה. לדוגמה, אם אתם רוצים שהסרטון יופעל מחדש או יופעל בלופ בקרוב, מומלץ שלא להסיר את תחילת הסרטון. באופן דומה, אם אתם או המשתמש תבצעו דילוג לסרטון שבו הסרתם נתונים, תצטרכו לצרף את הנתונים האלה שוב כדי לעמוד בדילוג.
  • הסירו רק את מה שצריך. חשוב להיזהר ולהימנע מהסרה של קבוצת הפריימים שמופעלת כרגע, החל מפריים המפתח ב-currentTime או לפניו, כי הפעולה הזו עלולה לגרום להשהיית ההפעלה. יכול להיות שאפליקציית האינטרנט תצטרך לנתח מידע כזה מה-bytestream אם הוא לא זמין במניפסט. מניפסט מדיה או ידע באפליקציה לגבי מרווחי הפריימים המרכזיים במדיום יכולים לעזור לכם לבחור את טווחי ההסרה באפליקציה כדי למנוע הסרה של המדיה שמופעלת כרגע. בכל מקרה, אל תסירו את קבוצת התמונות המופעלת כרגע, או אפילו את התמונות הראשונות שמעבר לזה. באופן כללי, לא כדאי להסיר נתונים מעבר לזמן הנוכחי, אלא אם אתם בטוחים שאין לכם יותר צורך במדיה. אם תסירו את האצבע קרוב לסמן ההתקדמות, יכול להיות שהסרטון ייעצר.
  • ב-Safari 9 וב-Safari 10 אין הטמעה נכונה של SourceBuffer.abort(). למעשה, הן גורמות לשגיאות שגורמות להפסקת ההפעלה. למרבה המזל, יש מעקב אחר באגים פתוחים כאן וכאן. בינתיים, תצטרכו למצוא דרך לעקוף את הבעיה. Shaka Player עושה זאת על ידי החלפת פונקציית abort() ריקה בגרסאות האלה של Safari.

צירוף קטעים קטנים יותר

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

const pieces = new Uint8Array([data]);
(function appendFragments(pieces) {
    if (sourceBuffer.updating) {
    return;
    }
    pieces.forEach(piece => {
    try {
        sourceBuffer.appendBuffer(piece);
    }
    catch e {
        if (e.name !== 'QuotaExceededError') {
        throw e;
        }

        // Reduction schedule: 80%, 60%, 40%, 20%, 16%, 12%, 8%, 4%, fail.
        const reduction = pieces[0].byteLength * 0.8;
        if (reduction / data.byteLength < 0.04) {
        throw new Error('MediaSource threw QuotaExceededError too many times');
        }
        const newPieces = [
        pieces[0].slice(0, reduction),
        pieces[0].slice(reduction, pieces[0].byteLength)
        ];
        pieces.splice(0, 1, newPieces[0], newPieces[1]);
        appendBuffer(pieces);  
    }
    });
})(pieces);

הנמכה של רזולוציית ההפעלה

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

יש כמה דברים שכדאי לזכור כשמשתמשים בשיטה הזו:

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