إدارة مساحة تخزين الفيديوهات على الويب

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

تخزين الفيديو مؤقتًا من عامل الخدمة

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

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

self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request).then(function (response) {
      return response || fetch(event.request);
    }),
  );
});

ويمكن أن تكون إدارة ذلك لأنواع مختلفة من مواد العرض أو عناوين URL التي تتطلّب استراتيجيات تخزين مؤقت مختلفة عملية متكرّرة وعُرضة للأخطاء. توفّر Workbox مجموعة من الأدوات، بما في ذلك أدوات المساعدة في التوجيه واستراتيجيات التخزين المؤقت، التي تتيح لك كتابة رمز عامل الخدمة بطريقة أكثر تعريفية وقابلة لإعادة الاستخدام.

تُعرف الاستراتيجية السابقة باسم الذاكرة المؤقتة أولاً. لكتابة الشيء نفسه باستخدام Workbox، عليك تضمين ما يلي:

registerRoute(
  ({ request }) => request.destination === 'video',
  new CacheFirst()
);

توفّر Workbox وصفات مشابهة لاستراتيجيات التخزين المؤقت الأخرى ومهام مشغّل الخدمات الشائعة، بما في ذلك التكامل مع أدوات الإنشاء مثل Webpack وRollup.

بعد إعداد Workbox، عليك اختيار الوقت الذي سيتم فيه تخزين فيديوهاتك مؤقتًا. هناك طريقتان لتنفيذ ذلك: إما بشكل استباقي عند تحميل الصفحة، أو بشكل مؤجّل عند طلب الفيديو.

النهج الحريص

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

يمكن استخدام رمز Workbox التالي في عامل الخدمة لتخزين الملفات مؤقتًا:

import { addPlugins, precacheAndRoute } from 'workbox-precaching';
import { RangeRequestsPlugin } from 'workbox-range-requests';

addPlugins([new RangeRequestsPlugin()]);
precacheAndRoute(self.__WB_MANIFEST);
  • import(s): لتحميل عمليات الربط المطلوبة من وحدات Workbox ذات الصلة. بما أنّ عاملي الخدمة لا يتيحون استخدام ESModules على نطاق واسع حتى الآن، يجب تمرير عامل الخدمة المستند إلى Workbox من خلال أداة تجميع لكي يعمل في مرحلة الإنتاج.
  • RangeRequestsPlugin: يتيح تنفيذ طلب يتضمّن العنوان Range من خلال استجابة مخزّنة مؤقتًا. هذا الإجراء ضروري لأنّ المتصفّحات تستخدم عادةً عنوان Range لمحتوى الوسائط.
  • addPlugins: تتيح لك إضافة مكوّنات Workbox الإضافية إلى كل طلب من Workbox.
  • precacheAndRoute: يضيف إدخالات إلى قائمة التخزين المؤقت المسبق وينشئ مسارًا للتعامل مع طلبات الجلب المقابلة.
  • __WB_MANIFEST: عنصر نائب يستبدله Workbox CLI (أو مكوّنات إضافية لأداة الإنشاء) بملف البيان الخاص بالتخزين المؤقت المسبق.

مرِّر عامل الخدمة إلى واجهة سطر الأوامر في Workbox أو أداة الإنشاء التي تختارها، واضبط طريقة إنشاء التخزين المؤقت المسبق. سيخبر ملف workbox-config.js، مثل ما يلي، واجهة سطر الأوامر بكيفية عرض عامل الخدمة:

module.exports = {
  globDirectory: '.',
  globPatterns: ['**/*.{html,mp4}'],
  maximumFileSizeToCacheInBytes: 5000000,
  swSrc: 'sw.js',
  swDest: 'sw.js',
};
  • globDirectory: المجلد الجذر الذي سيتم بدء البحث عن ملفات التخزين المؤقت المسبق منه
  • globPatterns: أنماط الملفات ("globs") التي يجب تخزينها مؤقتًا مسبقًا
  • maximumFileSizeToCacheInBytes: الحد الأقصى لحجم الملف الذي يمكن تخزينه مؤقتًا مسبقًا، بالبايت.
  • swSrc: موقع الملف الذي سيتم استخدامه لإنشاء عامل الخدمة.
  • swDest: الوجهة الخاصة ببرنامج عامل الخدمة الذي تم إنشاؤه (يمكن أن تكون هي نفسها ملف المصدر، ولكن تأكَّد من توفُّر self.__WB_MANIFEST في كل عملية تشغيل).

عند تنفيذ عملية الإنشاء، يتم إنشاء إصدار جديد من برنامج عامل الخدمة، ويتم استبدال self.__WB_MANIFEST بقائمة من الملفات، يحتوي كل منها على تجزئة للإشارة إلى مراجعته:

precacheAndRoute([
  {
    revision: '524ac4b453c83f76eb9caeec11854ca5',
    url: 'ny.mp4',
  },
]);

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

النهج الكسول

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

تخزين الملفات مؤقتًا

يمكن إنشاء ذاكرات التخزين المؤقت باستخدام Cache.open()، ثم يمكن إضافة الملفات إلى ذاكرة التخزين المؤقت باستخدام Cache.add() أو Cache.addAll(). إذا تلقّى تطبيقك قائمة JSON بالفيديوهات التي سيتم تخزينها مؤقتًا، يمكن إضافتها إلى ذاكرة تخزين مؤقت للفيديوهات على النحو التالي:

// Open video cache
const cache = await caches.open('video-cache');
// Fetch list of videos
const videos = await (await fetch('/video-list.json')).json();
// Add videos to cache
await cache.addAll(videos);

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

عرض ملفات الفيديو المخزّنة مؤقتًا

يمكن بعد ذلك استخدام استراتيجية التخزين المؤقت أثناء وقت التشغيل في عامل الخدمة، مثل التخزين المؤقت أولاً لعرض ملفات الفيديو التي تم تخزينها مؤقتًا سابقًا:

import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { RangeRequestsPlugin } from 'workbox-range-requests';

registerRoute(
  ({ request }) => request.destination === 'video',
  new CacheFirst({
    cacheName: 'video-cache',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [200],
      }),
      new RangeRequestsPlugin(),
    ],
  }),
);
  • import(s): يتم تحميل عمليات الربط المطلوبة من وحدات workbox ذات الصلة.
  • registerRoute: توجّه الطلبات إلى الدوال (استراتيجيات التخزين المؤقت والمكوّنات الإضافية) التي تقدّم الردود.
  • CacheFirst: استراتيجية التخزين المؤقت التي تنفِّذ الطلب من ذاكرة التخزين المؤقت، إذا كان متاحًا، وإلا فإنّها تجلبه من الشبكة وتعدِّل ذاكرة التخزين المؤقت.
  • CacheableResponsePlugin: تُستخدَم للإشارة إلى العناوين التي يجب أن تكون متوفّرة لكي تكون الاستجابة قابلة للتخزين مؤقتًا. احرص على تضمين 200 حالة فقط في ذاكرة التخزين المؤقت للفيديوهات في المسارات لتجنُّب تخزين الردود على المحتوى الجزئي (206) مؤقتًا أثناء بث الفيديوهات.
  • RangeRequestsPlugin: إضافة تتيح تلبية طلب يتضمّن العنوان Range من خلال استجابة مخزّنة مؤقتًا. هذا الإجراء ضروري لأنّ المتصفّحات تستخدم عادةً عنوان Range لمحتوى الوسائط.

يُعدّ تحسين تحميل الفيديو مهمة أساسية للتطبيقات التي تتطلّب بثًا مكثفًا. من خلال الاستفادة من واجهة برمجة التطبيقات Cache storage API في المتصفح وWorkbox، يمكنك تسهيل هذه المهمة الصعبة، ما يؤدي إلى توفير معدل نقل البيانات للمستخدمين وتقليل حمل الخادم وتحقيق تشغيل أسرع للفيديو والسماح بتشغيل الفيديوهات حتى في حال عدم الاتصال بالإنترنت.