مدیریت فضای ذخیره‌سازی ویدیو در وب

مدیریت ویدیو یک دارایی دشوار است؛ پخش آنلاین پهنای باند زیادی را مصرف می‌کند و ذخیره‌سازی (caching) آن ساده نیست. این مشکلات زمانی که ویدیوها به صورت حلقه‌ای، مانند نمایشگر کیوسک، پخش می‌شوند، تشدید می‌شوند. به عنوان مثال، اگر یک شرکت صدها دستگاه داشته باشد که هر روز 30 ویدیو را به طور مکرر پخش می‌کنند، می‌تواند به سرعت شبکه آنها را تحت الشعاع قرار دهد. با ارائه ویدیوها از حافظه پنهان به جای پخش آنلاین، شما فقط یک بار هزینه دانلود را متحمل می‌شوید، پخش‌های بعدی را سریع‌تر انجام می‌دهید و آنها را برای پخش آفلاین در دسترس قرار می‌دهید. برای انجام این کار، می‌توانید از قابلیت‌های ذخیره‌سازی مرورگر استفاده کنید، که از بین آنها API ذخیره‌سازی Cache و IndexedDB مناسب‌ترین گزینه‌ها برای ذخیره فایل‌های ویدیویی هستند. در حالی که هر دو گزینه خوبی هستند، ما بر روی API ذخیره‌سازی Cache برای ادغام آن با کتابخانه محبوب service worker یعنی Workbox تمرکز خواهیم کرد.

ذخیره ویدیو از یک سرویس ورکر

از آنجا که دانلود و ذخیره‌سازی فایل‌های بزرگ مانند ویدیوها می‌تواند یک کار زمان‌بر و پردازنده‌محور باشد، باید آن را در پس‌زمینه و خارج از نخ اصلی انجام دهید. سرویس ورکرها به ویژه برای تخلیه وظایف ذخیره‌سازی مفید هستند. آن‌ها به عنوان یک پروکسی بین صفحه و شبکه عمل می‌کنند و به شبکه اجازه می‌دهند تا درخواست‌ها را رهگیری کرده و منطق اضافی را به پاسخ شبکه اعمال کند، به عنوان مثال، یک استراتژی ذخیره‌سازی .

استراتژی‌های ذخیره‌سازی مختلفی وجود دارد و هر یک از آنها برای کمک به موارد استفاده‌ی متفاوتی طراحی شده‌اند. به عنوان مثال، برای ارائه یک فایل از حافظه‌ی پنهان در صورت وجود، یا بازگشت به شبکه در صورت عدم وجود، می‌توانید کد زیر را بنویسید.

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

مدیریت این مورد برای انواع مختلف دارایی‌ها یا URLهایی که به استراتژی‌های ذخیره‌سازی متفاوتی نیاز دارند، می‌تواند یک فرآیند تکراری و مستعد خطا باشد. Workbox مجموعه‌ای از ابزارها، از جمله کمک‌کننده‌های مسیریابی و استراتژی‌های ذخیره‌سازی را ارائه می‌دهد که به شما امکان می‌دهد کد سرویس ورکرها را به روشی اعلانی‌تر و قابل استفاده مجددتر بنویسید.

استراتژی قبلی، cache first نام دارد. برای نوشتن همان چیز با استفاده از Workbox، موارد زیر را باید وارد کنید:

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

Workbox دستورالعمل‌های مشابهی را برای سایر استراتژی‌های ذخیره‌سازی و وظایف رایج سرویس ورکرها ارائه می‌دهد، از جمله ادغام با ابزارهای ساخت مانند Webpack و Rollup .

با تنظیم Workbox، باید انتخاب کنید که چه زمانی می‌خواهید ویدیوهای خود را کش کنید. در اینجا، دو رویکرد وجود دارد: بارگذاری مشتاقانه در صفحه، یا بارگذاری تنبلانه در هنگام درخواست ویدیو.

رویکرد مشتاقانه

پیش‌ذخیره‌سازی (Precaching) تکنیکی است که در آن فایل‌ها در حین نصب سرویس ورکرها در حافظه پنهان (cache) ذخیره می‌شوند و به محض اتمام کار سرویس، در دسترس قرار می‌گیرند. ورک‌باکس می‌تواند به طور خودکار پیش‌ذخیره‌سازی را برای فایل‌هایی که می‌تواند در طول فرآیند ساخت به آنها دسترسی داشته باشد، تنظیم کند.

کد Workbox زیر می‌تواند در سرویس ورکر شما برای پیش‌ذخیره‌سازی فایل‌ها استفاده شود:

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

addPlugins([new RangeRequestsPlugin()]);
precacheAndRoute(self.__WB_MANIFEST);
  • import (s) - اتصالات مورد نیاز را از ماژول‌های Workbox مربوطه بارگذاری می‌کند. از آنجا که service workerها هنوز به طور جهانی از ESModuleها پشتیبانی نمی‌کنند، service worker مبتنی بر Workbox شما برای کار در محیط عملیاتی باید از یک bundler عبور داده شود.
  • RangeRequestsPlugin - امکانی را فراهم می‌کند که یک درخواست با سرآیند Range توسط یک پاسخ ذخیره‌شده در حافظه‌ی نهان (cache) انجام شود. این امر ضروری است زیرا مرورگرها معمولاً از سرآیند Range برای محتوای رسانه استفاده می‌کنند.
  • addPlugins - به شما امکان می‌دهد افزونه‌های Workbox را به هر درخواست Workbox اضافه کنید.
  • precacheAndRoute - ورودی‌ها را به لیست precache اضافه می‌کند و مسیری برای مدیریت درخواست‌های واکشی مربوطه ایجاد می‌کند.
  • __WB_MANIFEST - یک متغیر که رابط خط فرمان (CLI) محیط کار (یا افزونه‌های ابزار ساخت) آن را با مانیفست پیش‌ذخیره‌سازی جایگزین می‌کند.

سرویس ورکر خود را به رابط خط فرمان Workbox یا ابزار ساخت دلخواه خود منتقل کنید و نحوه تولید precache خود را پیکربندی کنید؛ یک فایل workbox-config.js ، مانند فایل زیر، به CLI می‌گوید که چگونه باید سرویس ورکر شما را رندر کند:

module.exports = {
  globDirectory: '.',
  globPatterns: ['**/*.{html,mp4}'],
  maximumFileSizeToCacheInBytes: 5000000,
  swSrc: 'sw.js',
  swDest: 'sw.js',
};
  • globDirectory - پوشه ریشه برای شروع جستجوی فایل‌های precache
  • globPatterns - الگوهای فایل ( "globs" ) که باید از قبل ذخیره شوند.
  • maximumFileSizeToCacheInBytes - حداکثر اندازه‌ای که یک فایل می‌تواند از قبل در حافظه پنهان قرار گیرد، بر حسب بایت.
  • swSrc - محل فایلی که برای تولید سرویس ورکر شما استفاده خواهد شد.
  • swDest - مقصد برای سرویس ورکر تولید شده (می‌تواند همان فایل منبع باشد، اما مطمئن شوید که self.__WB_MANIFEST برای هر اجرا وجود دارد).

وقتی فرآیند ساخت اجرا می‌شود، یک نسخه جدید از سرویس ورکر تولید می‌شود و self.__WB_MANIFEST با لیستی از فایل‌ها جایگزین می‌شود که هر کدام دارای یک هش برای نشان دادن ویرایش خود هستند:

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

هر بار که فرآیند ساخت اجرا می‌شود، این لیست با مجموعه فعلی فایل‌های منطبق و هش‌های ویرایش فعلی آنها بازنویسی می‌شود. این تضمین می‌کند که هر زمان که یک فایل اضافه، حذف یا تغییر داده شود، سرویس ورکر در نصب بعدی خود، حافظه پنهان را به‌روزرسانی می‌کند.

رویکرد تنبلانه

وقتی همه ویدیوها را در زمان ساخت در دسترس ندارید، یا فقط می‌خواهید ویدیوها را در مواقع نیاز ذخیره کنید، باید از رویکرد تنبلی استفاده کنید. این رویکرد مستلزم جدا کردن ذخیره و ارائه است؛ از آنجا که فقط بخشی از محتوا در هنگام پخش ویدیو از شبکه دریافت می‌شود، ذخیره فایل‌ها هنگام پخش آنها کار نخواهد کرد.

ذخیره سازی فایل ها

حافظه‌های پنهان (cache) را می‌توان با استفاده از 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);

مزیت این رویکرد این است که می‌توانید مرحله ذخیره‌سازی را مستقل از چرخه حیات سرویس ورکر ، حتی از سایر وب ورکرها ، کنترل کنید. نکته منفی این است که بخش مدیریت ذخیره‌سازی به توسعه‌دهنده بستگی دارد: شما باید الگوریتم خودتان را برای ردیابی تغییرات فایل، ردیابی فایل‌های ذخیره‌شده فعلی در مرورگر و مدیریت به‌روزرسانی‌های فایل بنویسید تا مطمئن شوید که فقط فایل‌های تغییر یافته به‌روزرسانی می‌شوند.

ارائه فایل‌های ویدیویی ذخیره شده

یک استراتژی ذخیره‌سازی زمان اجرای سرویس ورکر، مانند cache first، می‌تواند برای ارائه فایل‌های ویدیویی که قبلاً ذخیره‌سازی شده‌اند، استفاده شود:

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) - اتصالات مورد نیاز را از ماژول‌های مربوط به جعبه کار بارگذاری می‌کند.
  • registerRoute - درخواست‌ها را به توابعی (استراتژی‌های ذخیره‌سازی و افزونه‌ها) که پاسخ‌ها را ارائه می‌دهند، هدایت می‌کند.
  • CacheFirst - استراتژی ذخیره‌سازی که در صورت وجود، درخواست را از حافظه پنهان انجام می‌دهد، در غیر این صورت آن را از شبکه دریافت کرده و حافظه پنهان را به‌روزرسانی می‌کند.
  • CacheableResponsePlugin - برای مشخص کردن اینکه چه هدرهایی باید وجود داشته باشند تا پاسخ قابل ذخیره باشد، استفاده می‌شود. مطمئن شوید که فقط ۲۰۰ وضعیت برای مسیرهایی که ویدیو را ذخیره می‌کنند، در نظر گرفته‌اید تا از ذخیره شدن پاسخ‌های جزئی (۲۰۶) هنگام پخش ویدیوها جلوگیری شود.
  • RangeRequestsPlugin - افزونه‌ای که امکان می‌دهد درخواستی با سرآیند Range توسط یک پاسخ ذخیره‌شده در حافظه‌ی نهان انجام شود. این امر ضروری است زیرا مرورگرها معمولاً از سرآیند Range برای محتوای رسانه استفاده می‌کنند.

بهینه‌سازی بارگذاری ویدیو برای برنامه‌هایی که پخش فشرده انجام می‌دهند، یک کار مهم است. با بهره‌گیری از API ذخیره‌سازی Cache مرورگر و Workbox، می‌توانید این کار دشوار را قابل مدیریت کنید، در پهنای باند کاربران خود صرفه‌جویی کنید، بار سرور را کاهش دهید، پخش ویدیو سریع‌تری داشته باشید و به ویدیوهای خود اجازه دهید حتی در حالت آفلاین نیز اجرا شوند.