تم تجاوز حصة التخزين المؤقت

جو ميدلي
جو ميدلي

إذا كنت تعمل مع إضافات مصدر الوسائط (MSE)، فهناك شيء آخر ستحتاج في النهاية إلى التعامل معه هو مورد احتياطي ممتلئ كليًا. عند حدوث ذلك، ستحصل على ما يسمّى QuotaExceededError. في هذه المقالة، سأتناول بعض طرق التعامل معها.

ما المقصود بـ CDedError؟

في الأساس، QuotaExceededError هو ما تحصل عليه إذا حاولت إضافة الكثير من البيانات إلى كائن SourceBuffer. (يمكن أن تؤدي إضافة المزيد من كائنات SourceBuffer إلى العنصر MediaSource الرئيسي إلى ظهور هذا الخطأ أيضًا. هذا خارج نطاق هذه المقالة). إذا احتوى SourceBuffer على الكثير من البيانات، سيؤدي استدعاء SourceBuffer.appendBuffer() إلى عرض الرسالة التالية في نافذة "وحدة تحكُّم Chrome".

حدث خطأ في وحدة التحكّم في الحصة.

هناك بعض الأشياء التي يجب ملاحظتها بشأن هذا الأمر. أولاً، لاحظ أن الاسم QuotaExceededError لا يظهر في أي مكان في الرسالة. لرؤية ذلك، قم بتعيين نقطة إيقاف في موقع يمكنك فيه اكتشاف الخطأ وفحصه في ساعتك أو نافذة النطاق. لقد أوضحنا ذلك أدناه.

نافذة مراقبة الحصة

ثانيًا، ما مِن طريقة مؤكدة لمعرفة مقدار البيانات التي يمكن لـ SourceBuffer معالجتها.

السلوك في المتصفّحات الأخرى

في وقت كتابة هذا التقرير، لا يطرح Safari علامة QuotaExceededError في العديد من إصداراته. بدلاً من ذلك، تزيل هذه الأداة اللقطات باستخدام خوارزمية من خطوتَين، وتتوقّف في حال كانت هناك مساحة كافية للتعامل مع appendBuffer(). أولاً، يحرر الإطارات الإطارات التي تتراوح بين 0 و30 ثانية قبل الوقت الحالي في أجزاء 30 ثانية. بعد ذلك، يحرر هذا الفلتر الإطارات في أجزاء مدتها 30 ثانية من مدة قديمة إلى 30 ثانية تقريبًا بعد currentTime. يمكنك الاطّلاع على المزيد من المعلومات عن هذا الأمر في مجموعة تغييرات Webkit من عام 2014.

لحسن الحظ، يحدث هذا الخطأ مع Chrome وEdge وFirefox. إذا كنت تستخدم متصفحًا آخر، عليك إجراء اختبارك الخاص. على الرغم من أنّ اختبار حد المخزن المؤقت للمصدر الذي أعدّه "فرانسوا بوفورت" ليس على الأقل الذي ستنشئه لمشغّل وسائط فعليّ، يتيح لك ذلك على الأقل ملاحظة السلوك.

ما مقدار البيانات التي يمكنني إلحاقها؟

يختلف العدد الدقيق من متصفح إلى آخر. نظرًا لأنه لا يمكنك الاستعلام عن مقدار البيانات الملحقة حاليًا، سيتعين عليك تتبع مقدار مقدار إلحاقه بنفسك. بالنسبة إلى ما يمكن مشاهدته، إليك أفضل البيانات التي يمكنني جمعها أثناء الكتابة. بالنسبة إلى Chrome، تكون هذه الأرقام حدودًا قصوى، مما يعني أنها قد تكون أصغر عندما يواجه النظام ضغطًا في الذاكرة.

Chrome Chromecast* Firefox برنامج المتصفح Safari Edge
حملة فيديو 150 ميغابايت 30 ميغابايت 100 ميغابايت 290 ميغابايت غير معروف
الصوت 12 ميغابايت 2 ميغابايت 15 ميغابايت 14 ميغابايت غير معروف
  • أو جهاز Chrome ذو ذاكرة محدودة أخرى.

إذًا، ماذا أفعل؟

وبما أنّ كمية البيانات المتوافقة تتفاوت إلى حدٍّ كبير ولا يمكنك العثور على مقدار البيانات في SourceBuffer، عليك الحصول عليها بشكل غير مباشر من خلال معالجة QuotaExceededError. لنلقِ نظرة الآن على بعض الطرق للقيام بذلك.

ثمة طرق متعددة للتعامل مع QuotaExceededError. في الواقع، أفضل استخدام مزيج من نهج واحد أو أكثر. ويجب أن يستند أسلوبك إلى مقدار ما تجلبه وتحاول إرفاقه بما يزيد عن HTMLMediaElement.currentTime، ومن ثم تعديل هذا الحجم استنادًا إلى QuotaExceededError. قد يساعدك أيضًا استخدام بيان من نوع ما، مثل ملف mpd (MPEG-DASH) أو ملف m3u8 (HLS) في تتبُّع البيانات التي تُلحقها بالمورد الاحتياطي.

لنلقِ نظرة الآن على عدة طرق للتعامل مع QuotaExceededError.

  • يمكنك إزالة البيانات غير الضرورية وإعادة إلحاقها.
  • إضافة أجزاء أصغر حجمًا
  • خفض درجة دقة التشغيل

على الرغم من أنه يمكن استخدامها معًا، إلا أنني سأتناولها واحدة تلو الأخرى.

إزالة البيانات غير الضرورية وإعادة إلحاقها

حقًا يجب تسمية هذا، "إزالة البيانات الأقل احتمالاً للاستخدام قريبًا، ثم إعادة محاولة إلحاق البيانات التي من المحتمل أن يتم استخدامها قريبًا". كان العنوان طويلاً جدًا. ستحتاج فقط إلى تذكر ما أعنيه حقًا.

إن إزالة البيانات الحديثة ليست سهلة مثل الاتصال برقم SourceBuffer.remove(). لإزالة البيانات من SourceBuffer، يجب أن تكون علامة التعديل "خطأ". إذا لم تكن كذلك، فاتصل بـ SourceBuffer.abort() قبل إزالة أي بيانات.

هناك بعض الأمور التي يجب تذكّرها عند الاتصال بـ SourceBuffer.remove().

  • قد يؤثّر ذلك سلبًا على عملية التشغيل. على سبيل المثال، إذا كنت تريد إعادة تشغيل الفيديو أو تكراره قريبًا، من الأفضل عدم إزالة بداية الفيديو. وبالمثل، إذا أردت أنت أو المستخدم الوصول إلى جزء من الفيديو أزلت فيه البيانات، عليك إلحاق تلك البيانات مجددًا لتلبية هذا الهدف.
  • أزل قدر الإمكان من الطرق. احذر إزالة مجموعة الإطارات التي يتم تشغيلها حاليًا من الإطار الرئيسي عند الساعة currentTime أو قبلها، لأنّ ذلك قد يؤدي إلى حدوث توقُّف في التشغيل. قد يحتاج تطبيق الويب إلى تحليل هذه المعلومات خارج مصدر البيانات إذا لم تكن متوفّرة في البيان. إنّ بيان الوسائط أو معرفة التطبيق بفترات زمنية للإطارات الرئيسية في الوسائط يمكن أن يساعد في توجيه اختيار تطبيقك لنطاقات الإزالة لمنع إزالة الوسائط التي يتم تشغيلها حاليًا. مهما كان ما تتم إزالته، يجب عدم إزالة مجموعة الصور التي يتم تشغيلها حاليًا أو حتى الصور القليلة الأولى التي بعد ذلك. بشكل عام، يُرجى عدم إزالة الوسائط بعد الوقت الحالي إلا إذا كنت متأكدًا من عدم الحاجة إلى الوسائط بعد الآن. إذا أزلت العنصر بالقرب من رأس التشغيل، قد يؤدي ذلك إلى حدوث عطل.
  • لا يستخدم 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);

خفض درجة دقة التشغيل

يشبه هذا إزالة البيانات الحديثة وإعادة الإلحاق. في الواقع، قد يتم الاثنين معًا، على الرغم من أن المثال أدناه يوضح فقط خفض درجة الدقة.

هناك بضعة أمور يجب وضعها في الاعتبار عند استخدام هذه التقنية:

  • يجب إلحاق شريحة إعداد جديدة. يجب عليك القيام بذلك في أي وقت تقوم فيه بتغيير الممثلين. يجب أن تكون شريحة الإعداد الجديدة مخصّصة لشرائح الوسائط التالية.
  • يجب أن يتطابق الطابع الزمني للعرض التقديمي للوسائط الملحقة مع الطابع الزمني للبيانات في المخزن المؤقت قدر الإمكان، ولكن يجب ألا يتم تقديم طلب سريع. قد يؤدي تداخل البيانات المخزنة مؤقتًا إلى حدوث تقطع أو عطل لفترة قصيرة، بناءً على المتصفح. بغض النظر عما تضيفه، لا تتداخل مع رأس التشغيل لأنّ ذلك سيؤدي إلى حدوث أخطاء.
  • قد يؤدي تقديم الطلب إلى إيقاف التشغيل. قد تميل إلى البحث إلى موقع معين واستئناف التشغيل من هناك. تذكّر أنّ هذا الإجراء سيؤدي إلى انقطاع التشغيل إلى أن تكتمل عملية البحث.