אם אתם עובדים עם תוספים של מקורות מדיה (MSE), תצטרכו לטפל בסופו של דבר במצב שבו מאגר הנתונים (buffer) מלא מדי. במקרה כזה, תקבלו QuotaExceededError
. במאמר הזה אסקור כמה מהדרכים להתמודד עם הבעיה.
מהי השגיאה QuotaExceededError?
בעיקרון, QuotaExceededError
הוא מה שמקבלים אם מנסים להוסיף יותר מדי נתונים לאובייקט SourceBuffer
. (הוספת עוד אובייקטים מסוג SourceBuffer
לאלמנט הורה מסוג MediaSource
עלולה גם לגרום לשגיאה הזו. זה לא נכלל במאמר הזה). אם יש ב-SourceBuffer
יותר מדי נתונים, הקריאה ל-SourceBuffer.appendBuffer()
תגרום להצגת ההודעה הבאה בחלון המסוף של Chrome.
![שגיאה במסוף המכסות.](https://developer.chrome.google.cn/static/blog/quotaexceedederror/image/quota-console-error-1898f4c0fdf15.png?hl=he)
יש כמה דברים שחשוב לזכור לגבי הנושא הזה. קודם כול, שימו לב שהשם QuotaExceededError
לא מופיע בשום מקום בהודעה. כדי לראות את זה, מגדירים נקודת עצירה במיקום שבו אפשר לזהות את השגיאה ולבדוק אותה בחלון המעקב או בחלון ההיקף. הבאתי את זה בהמשך.
![חלון מעקב אחר המכסות.](https://developer.chrome.google.cn/static/blog/quotaexceedederror/image/quota-watch-window-78bfbd50fe4e6.png?hl=he)
שנית, אין דרך ודאית לדעת כמה נתונים 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);
להקטין את רזולוציית ההפעלה
הפעולה הזו דומה להסרת נתונים מהזמן האחרון והוספה מחדש שלהם. למעשה, אפשר לבצע את שתי הפעולות יחד, אבל בדוגמה שבהמשך מוצגת רק הפעולה של הפחתת הרזולוציה.
יש כמה דברים שכדאי לזכור כשמשתמשים בשיטה הזו:
- צריך לצרף מקטע חדש של אתחול. צריך לעשות זאת בכל פעם שמבצעים שינוי בייצוגים. מקטע האתחול החדש צריך להיות עבור פלחי המדיה הבאים.
- חותמת הזמן של הצגת המדיה שנוספה צריכה להתאים ככל האפשר לחותמת הזמן של הנתונים במאגר, אבל לא לקפוץ קדימה. חפיפה של הנתונים שנשמרו במטמון עלולה לגרום להשהיה קצרה או לגמגום, בהתאם לדפדפן. לא משנה מה תצרפו, אל תצמיד את הקוד לסמן הווידאו כי זה יגרום לשגיאות.
- חיפוש מיקום בהפעלה עלול להפריע להפעלה. יכול להיות שתתפתתו לחפש מיקום ספציפי ולהמשיך את ההפעלה משם. חשוב לדעת שהפעולה הזו תגרום להפסקה של ההפעלה עד להשלמת הסריקה.