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

ג'ו מדלי
ג'ו מדלי

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

מהי QuotaExceededError?

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

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

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

חלון זמן לניצול מכסות.

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

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

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

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

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

המספר המדויק משתנה מדפדפן לדפדפן. אי אפשר לבדוק את הסכום לצירוף קבצים, ולכן עליכם לבדוק כמה אתם מוסיפים. לגבי במה כדאי לצפות, אלה הנתונים הטובים ביותר שהצלחתי לאסוף בזמן הכתיבה. ב-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, הדגל בעדכון שלו חייב להיות FALSE. אם לא, צריך לבצע קריאה ל-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);

להוריד את רזולוציית ההפעלה

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

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

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