إنشاء تطبيق دفق فيديو باستخدام Nuxt.js و Node و Express

نشرت: 2022-03-10
ملخص سريع ↬ في هذه المقالة ، سننشئ تطبيق دفق فيديو باستخدام Nuxt.js و Node.js. على وجه التحديد ، سننشئ تطبيق Node.js من جانب الخادم والذي سيتعامل مع جلب مقاطع الفيديو وبثها ، وإنشاء صور مصغرة لمقاطع الفيديو الخاصة بك ، وتقديم التسميات التوضيحية والترجمات.

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

هذه المقالة للمطورين الراغبين في تعلم تقنية جديدة من خلال بناء مشروع فعلي: تطبيق دفق فيديو مع Node.js كخلفية و Nuxt.js كعميل.

  • Node.js هو وقت تشغيل يُستخدم لإنشاء تطبيقات سريعة وقابلة للتطوير. سنستخدمه للتعامل مع جلب مقاطع الفيديو ودفقها ، وإنشاء صور مصغرة لمقاطع الفيديو ، وتقديم التسميات التوضيحية والترجمات المصاحبة لمقاطع الفيديو.
  • Nuxt.js هو إطار عمل Vue.js يساعدنا في إنشاء تطبيقات Vue.js التي يعرضها الخادم بسهولة. سنستهلك واجهة برمجة التطبيقات الخاصة بنا لمقاطع الفيديو وسيكون لهذا التطبيق طريقتان لعرض: قائمة بمقاطع الفيديو المتاحة وعرض مشغل لكل مقطع فيديو.

المتطلبات

  • فهم HTML و CSS و JavaScript و Node / Express و Vue.
  • محرر نصوص (مثل VS Code).
  • متصفح ويب (مثل Chrome و Firefox).
  • تثبيت FFmpeg على محطة العمل الخاصة بك.
  • Node.js. نيفم.
  • يمكنك الحصول على الكود المصدري على جيثب.

إعداد تطبيقنا

في هذا التطبيق ، سنبني المسارات لتقديم الطلبات من الواجهة الأمامية:

  • يتم توجيه videos للحصول على قائمة مقاطع الفيديو وبياناتها.
  • طريق لجلب مقطع فيديو واحد فقط من قائمة مقاطع الفيديو الخاصة بنا.
  • طريق streaming لدفق مقاطع الفيديو.
  • طريق captions التوضيحية لإضافة تسميات توضيحية إلى مقاطع الفيديو التي نقوم ببثها.

بعد إنشاء مساراتنا ، سنعمل على دعم واجهة Nuxt الأمامية ، حيث سننشئ Home وصفحة player الديناميكي. ثم نطلب مسار videos بنا لملء الصفحة الرئيسية ببيانات الفيديو ، وطلب آخر لدفق مقاطع الفيديو على صفحة player لدينا ، وأخيرًا طلب خدمة ملفات التسميات التوضيحية لاستخدامها بواسطة مقاطع الفيديو.

لإعداد تطبيقنا ، نقوم بإنشاء دليل مشروعنا ،

 mkdir streaming-app
المزيد بعد القفز! أكمل القراءة أدناه ↓

إعداد خادمنا

في دليل streaming-app ، نقوم بإنشاء مجلد باسم backend .

 cd streaming-app mkdir backend

في مجلد الخلفية ، نقوم بتهيئة ملف package.json لتخزين المعلومات حول مشروع الخادم الخاص بنا.

 cd backend npm init -y

نحتاج إلى تثبيت الحزم التالية لبناء تطبيقنا.

  • nodemon بإعادة تشغيل خادمنا تلقائيًا عندما نجري تغييرات.
  • يعطينا express واجهة لطيفة للتعامل مع المسارات.
  • سيتيح لنا cors تقديم طلبات عبر الأصل نظرًا لأن العميل والخادم الخاص بنا سيعملان على منافذ مختلفة.

في دليل الواجهة الخلفية لدينا ، نقوم بإنشاء assets مجلد للاحتفاظ بمقاطع الفيديو الخاصة بنا للبث.

 mkdir assets

انسخ ملف .mp4 إلى مجلد الأصول ، وقم video1 . يمكنك استخدام نماذج فيديو قصيرة .mp4 يمكن العثور عليها في Github Repo.

قم بإنشاء ملف app.js وأضف الحزم الضرورية لتطبيقنا.

 const express = require('express'); const fs = require('fs'); const cors = require('cors'); const path = require('path'); const app = express(); app.use(cors())

تُستخدم وحدة fs للقراءة والكتابة في الملفات بسهولة على خادمنا ، بينما توفر وحدة path طريقة للعمل مع الدلائل ومسارات الملفات.

الآن نقوم بإنشاء مسار. ./video . عند الطلب ، سيرسل ملف فيديو إلى العميل مرة أخرى.

 // add after 'const app = express();' app.get('/video', (req, res) => { res.sendFile('assets/video1.mp4', { root: __dirname }); });

يخدم هذا المسار ملف الفيديو video1.mp4 عند الطلب. ثم نستمع إلى الخادم الخاص بنا في المنفذ 3000 .

 // add to end of app.js file app.listen(5000, () => { console.log('Listening on port 5000!') });

تمت إضافة نص برمجي في ملف package.json لبدء خادمنا باستخدام nodemon.

 "scripts": { "start": "nodemon app.js" },

ثم أثناء تشغيل المحطة:

 npm run start

إذا رأيت الرسالة Listening on port 3000! في المحطة ، فإن الخادم يعمل بشكل صحيح. انتقل إلى https: // localhost: 5000 / video في متصفحك وسترى تشغيل الفيديو.

الطلبات التي يتعين التعامل معها من قبل الواجهة

فيما يلي الطلبات التي سنقدمها إلى الواجهة الخلفية من الواجهة الأمامية لدينا والتي نحتاج إلى الخادم للتعامل معها.

  • /videos
    يقوم بإرجاع مجموعة من بيانات نموذج الفيديو التي سيتم استخدامها لملء قائمة مقاطع الفيديو على الصفحة Home في الواجهة الأمامية الخاصة بنا.
  • /video/:id/data
    إرجاع البيانات الوصفية لمقطع فيديو واحد. مستخدمة بواسطة صفحة Player في الواجهة الأمامية لدينا.
  • /video/:id
    لبث مقطع فيديو بمعرف معين. مستخدمة بواسطة صفحة Player .

لنقم بإنشاء الطرق.

إرجاع بيانات نموذج بالحجم الطبيعي لقائمة مقاطع الفيديو

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

في مجلد الواجهة الخلفية لدينا ، قم بإنشاء ملف mockdata.js وقم بتعبئته ببيانات وصفية لقائمة مقاطع الفيديو الخاصة بنا.

 const allVideos = [ { id: "tom and jerry", poster: 'https://image.tmdb.org/t/p/w500/fev8UFNFFYsD5q7AcYS8LyTzqwl.jpg', duration: '3 mins', name: 'Tom & Jerry' }, { id: "soul", poster: 'https://image.tmdb.org/t/p/w500/kf456ZqeC45XTvo6W9pW5clYKfQ.jpg', duration: '4 mins', name: 'Soul' }, { id: "outside the wire", poster: 'https://image.tmdb.org/t/p/w500/lOSdUkGQmbAl5JQ3QoHqBZUbZhC.jpg', duration: '2 mins', name: 'Outside the wire' }, ]; module.exports = allVideos

يمكننا أن نرى من فوق ، كل كائن يحتوي على معلومات حول الفيديو. لاحظ سمة poster التي تحتوي على رابط صورة ملصق الفيديو.

لنقم بإنشاء مسار videos نظرًا لأن كل طلباتنا التي يجب تقديمها بواسطة الواجهة الأمامية مُسبقة مسبقًا بـ /videos .

للقيام بذلك ، دعنا ننشئ مجلد routes ونضيف ملف Video.js /videos . في هذا الملف ، سنطلب express ونستخدم جهاز التوجيه السريع لإنشاء طريقنا.

 const express = require('express') const router = express.Router()

عندما ننتقل إلى مسار /videos ، نريد الحصول على قائمة مقاطع الفيديو الخاصة بنا ، لذلك دعونا نطلب ملف mockData.js في ملف Video.js بنا ونقدم طلبنا.

 const express = require('express') const router = express.Router() const videos = require('../mockData') // get list of videos router.get('/', (req,res)=>{ res.json(videos) }) module.exports = router;

تم الآن الإعلان عن مسار /videos ، احفظ الملف ويجب إعادة تشغيل الخادم تلقائيًا. بمجرد أن تبدأ ، انتقل إلى https: // localhost: 3000 / videos وسيتم إرجاع المصفوفة الخاصة بنا بتنسيق JSON.

إعادة البيانات لمقطع فيديو واحد

نريد أن نكون قادرين على تقديم طلب لمقطع فيديو معين في قائمة مقاطع الفيديو الخاصة بنا. يمكننا إحضار بيانات فيديو معينة في المصفوفة الخاصة بنا باستخدام id الذي قدمناه له. دعنا نقدم طلبًا ، ما زلنا في ملف Video.js بنا.

 // make request for a particular video router.get('/:id/data', (req,res)=> { const id = parseInt(req.params.id, 10) res.json(videos[id]) })

يحصل الكود أعلاه على id من معلمات المسار ويحوله إلى عدد صحيح. ثم نرسل الكائن الذي يطابق id من مجموعة videos إلى العميل.

دفق الفيديو

في ملف app.js بنا ، أنشأنا مسار /video يقدم مقطع فيديو إلى العميل. نريد من نقطة النهاية هذه إرسال أجزاء أصغر من الفيديو ، بدلاً من تقديم ملف فيديو كامل عند الطلب.

نريد أن نكون قادرين على تقديم أحد مقاطع الفيديو الثلاثة allVideos في مجموعة جميع مقاطع الفيديو ديناميكيًا ، ودفق مقاطع الفيديو في أجزاء ، لذلك:

احذف مسار /video من app.js

نحتاج إلى ثلاثة مقاطع فيديو ، لذا انسخ أمثلة مقاطع الفيديو من الكود المصدري للبرنامج التعليمي إلى assets/ الدليل الخاص بمشروع server الخاص بك. تأكد من أن أسماء ملفات مقاطع الفيديو مطابقة id في مجموعة videos :

بالعودة إلى ملف Video.js بنا ، أنشئ مسارًا لبث مقاطع الفيديو.

 router.get('/video/:id', (req, res) => { const videoPath = `assets/${req.params.id}.mp4`; const videoStat = fs.statSync(videoPath); const fileSize = videoStat.size; const videoRange = req.headers.range; if (videoRange) { const parts = videoRange.replace(/bytes=/, "").split("-"); const start = parseInt(parts[0], 10); const end = parts[1] ? parseInt(parts[1], 10) : fileSize-1; const chunksize = (end-start) + 1; const file = fs.createReadStream(videoPath, {start, end}); const head = { 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/mp4', }; res.writeHead(206, head); file.pipe(res); } else { const head = { 'Content-Length': fileSize, 'Content-Type': 'video/mp4', }; res.writeHead(200, head); fs.createReadStream(videoPath).pipe(res); } });

إذا انتقلنا إلى https: // localhost: 5000 / videos / video / outside-the-wire في متصفحنا ، يمكننا مشاهدة تدفق الفيديو.

كيف يعمل طريق دفق الفيديو

يوجد جزء لا بأس به من التعليمات البرمجية المكتوبة في مسار بث الفيديو الخاص بنا ، لذلك دعونا ننظر إليه سطراً بسطر.

 const videoPath = `assets/${req.params.id}.mp4`; const videoStat = fs.statSync(videoPath); const fileSize = videoStat.size; const videoRange = req.headers.range;

أولاً ، بناءً على طلبنا ، نحصل على id من المسار باستخدام req.params.id لإنشاء videoPath الفيديو إلى الفيديو. ثم fileSize الملف باستخدام نظام الملفات fs الذي قمنا باستيراده. بالنسبة لمقاطع الفيديو ، سيرسل متصفح المستخدم معلمة range في الطلب. يتيح ذلك للخادم معرفة جزء الفيديو الذي سيتم إرساله مرة أخرى إلى العميل.

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

 else { const head = { 'Content-Length': fileSize, 'Content-Type': 'video/mp4', }; res.writeHead(200, head); fs.createReadStream(path).pipe(res); }

سنتعامل مع الطلبات اللاحقة بما في ذلك النطاق في كتلة if .

 if (videoRange) { const parts = videoRange.replace(/bytes=/, "").split("-"); const start = parseInt(parts[0], 10); const end = parts[1] ? parseInt(parts[1], 10) : fileSize-1; const chunksize = (end-start) + 1; const file = fs.createReadStream(videoPath, {start, end}); const head = { 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/mp4', }; res.writeHead(206, head); file.pipe(res); }

ينشئ هذا الرمز أعلاه دفق قراءة باستخدام قيم start end للنطاق. قم بتعيين Content-Length لرؤوس الاستجابة إلى حجم المقطع الذي يتم حسابه من قيم start end . نستخدم أيضًا رمز HTTP 206 ، للإشارة إلى أن الاستجابة تحتوي على محتوى جزئي. هذا يعني أن المتصفح سيستمر في تقديم الطلبات حتى يتم جلب جميع أجزاء الفيديو.

ماذا يحدث عند التوصيلات غير المستقرة

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

 const start = parseInt(parts[0], 10); const end = parts[1] ? parseInt(parts[1], 10) : fileSize-1; const chunksize = (end-start) + 1; const file = fs.createReadStream(videoPath, {start, end});

يمكننا أن نرى أعلاه أنه يتم إنشاء ReadStream ويخدم مقطع الفيديو قطعة تلو الأخرى.

 const head = { 'Content-Range': `bytes ${start}-${end}/${fileSize}`, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/mp4', }; res.writeHead(206, head); file.pipe(res);

يحتوي رأس الطلب على Content-Range ، وهو تغيير البداية والنهاية للحصول على الجزء التالي من الفيديو ليتم بثه إلى الواجهة الأمامية ، content-length هو جزء الفيديو الذي تم إرساله. نحدد أيضًا نوع المحتوى الذي نقوم ببثه وهو mp4 . تم تعيين رأس الكتابة لـ 206 للاستجابة مع التدفقات التي تم إنشاؤها حديثًا فقط.

إنشاء ملف تسمية توضيحية لمقاطع الفيديو الخاصة بنا

هذا ما يبدو عليه ملف التسمية التوضيحية .vtt .

 WEBVTT 00:00:00.200 --> 00:00:01.000 Creating a tutorial can be very 00:00:01.500 --> 00:00:04.300 fun to do.

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

لنقم بإنشاء مسار جديد للتعامل مع طلب التسمية التوضيحية:

 router.get('/video/:id/caption', (req, res) => res.sendFile(`assets/captions/${req.params.id}.vtt`, { root: __dirname }));

بناء واجهتنا

للبدء في الجزء المرئي من نظامنا ، سيتعين علينا بناء سقالة أمامية.

ملاحظة : أنت بحاجة إلى vue-cli لإنشاء تطبيقنا. إذا لم يكن مثبتًا لديك على جهاز الكمبيوتر الخاص بك ، فيمكنك تشغيل npm install -g @vue/cli لتثبيته.

تثبيت

في جذر مشروعنا ، لنقم بإنشاء مجلد الواجهة الأمامية:

 mkdir frontend cd frontend

وفيه نقوم بتهيئة ملف package.json الخاص بنا ، ونسخ ولصق ما يلي فيه:

 { "name": "my-app", "scripts": { "dev": "nuxt", "build": "nuxt build", "generate": "nuxt generate", "start": "nuxt start" } }

ثم قم بتثبيت nuxt :

 npm add nuxt

وقم بتنفيذ الأمر التالي لتشغيل تطبيق Nuxt.js:

 npm run dev

هيكل ملف Nuxt الخاص بنا

الآن بعد أن قمنا بتثبيت Nuxt ، يمكننا البدء في وضع الواجهة الأمامية.

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

 mkdir layouts cd layouts touch default.vue

ثم مجلد components لإنشاء جميع مكوناتنا. سنحتاج فقط إلى مكونين ، شريط NavBar ومكون video . لذلك في المجلد الجذر الخاص بنا للواجهة الأمامية ، نقوم بما يلي:

 mkdir components cd components touch NavBar.vue touch Video.vue

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

 mkdir pages cd pages touch index.vue mkdir player cd player touch _name.vue

يبدو دليل الواجهة الأمامية الآن كما يلي:

 |-frontend |-components |-NavBar.vue |-Video.vue |-layouts |-default.vue |-pages |-index.vue |-player |-_name.vue |-package.json |-yarn.lock

مكون نافبار

يبدو NavBar.vue كما يلي:

 <template> <div class="navbar"> <h1>Streaming App</h1> </div> </template> <style scoped> .navbar { display: flex; background-color: #161616; justify-content: center; align-items: center; } h1{ color:#a33327; } </style>

يحتوي NavBar على علامة h1 تعرض تطبيق البث ، مع بعض التصميم البسيط.

دعنا نستورد NavBar إلى تخطيط default.vue الخاص بنا.

 // default.vue <template> <div> <NavBar /> <nuxt /> </div> </template> <script> import NavBar from "@/components/NavBar.vue" export default { components: { NavBar, } } </script>

يحتوي تخطيط default.vue الآن على مكون NavBar الخاص بنا <nuxt /> التي تليها تشير إلى المكان الذي سيتم فيه عرض أي صفحة نقوم بإنشائها.

في index.vue بنا (وهي صفحتنا الرئيسية) ، دعنا نطلب https://localhost:5000/videos للحصول على جميع مقاطع الفيديو من خادمنا. تمرير البيانات كعنصر أساسي إلى مكون video.vue الذي سننشئه لاحقًا. لكن في الوقت الحالي ، قمنا باستيراده بالفعل.

 <template> <div> <Video :videoList="videos"/> </div> </template> <script> import Video from "@/components/Video.vue" export default { components: { Video }, head: { title: "Home" }, data() { return { videos: [] } }, async fetch() { this.videos = await fetch( 'https://localhost:5000/videos' ).then(res => res.json()) } } </script>

مكون الفيديو

أدناه ، نعلن أولاً عن دعائمنا. نظرًا لأن بيانات الفيديو متاحة الآن في المكون ، باستخدام Vue's v-for فإننا نكرر جميع البيانات المستلمة ولكل منها ، نعرض المعلومات. يمكننا استخدام التوجيه v-for للتكرار خلال البيانات وعرضها كقائمة. تمت إضافة بعض التصميم الأساسي أيضًا.

 <template> <div> <div class="container"> <div v-for="(video, id) in videoList" :key="id" class="vid-con" > <NuxtLink :to="`/player/${video.id}`"> <div : class="vid" ></div> <div class="movie-info"> <div class="details"> <h2>{{video.name}}</h2> <p>{{video.duration}}</p> </div> </div> </NuxtLink> </div> </div> </div> </template> <script> export default { props:['videoList'], } </script> <style scoped> .container { display: flex; justify-content: center; align-items: center; margin-top: 2rem; } .vid-con { display: flex; flex-direction: column; flex-shrink: 0; justify-content: center; width: 50%; max-width: 16rem; margin: auto 2em; } .vid { height: 15rem; width: 100%; background-position: center; background-size: cover; } .movie-info { background: black; color: white; width: 100%; } .details { padding: 16px 20px; } </style>

نلاحظ أيضًا أن NuxtLink له مسار ديناميكي ، وهو التوجيه إلى /player/video.id .

الوظيفة التي نريدها هي عندما ينقر المستخدم على أي من مقاطع الفيديو ، يبدأ البث. لتحقيق ذلك ، نستفيد من الطبيعة الديناميكية لمسار _name.vue .

في ذلك ، نقوم بإنشاء مشغل فيديو وتعيين المصدر إلى نقطة النهاية الخاصة بنا لدفق الفيديو ، لكننا this.$route.params.name .

 <template> <div class="player"> <video controls muted autoPlay> <source :src="`https://localhost:5000/videos/video/${vidName}`" type="video/mp4"> </video> </div> </template> <script> export default { data() { return { vidName: '' } }, mounted(){ this.vidName = this.$route.params.name } } </script> <style scoped> .player { display: flex; justify-content: center; align-items: center; margin-top: 2em; } </style>

عندما نضغط على أي مقطع فيديو نحصل على:

النتيجة النهائية لتطبيق Nuxt Video Streaming
يبدأ دفق الفيديو عندما ينقر المستخدم على الصورة المصغرة. (معاينة كبيرة)

إضافة ملف التسمية التوضيحية لدينا

لإضافة ملف المسار الخاص بنا ، نتأكد من أن جميع ملفات .vtt في مجلد التسميات التوضيحية تحمل نفس اسم id . قم بتحديث عنصر الفيديو الخاص بنا بالمسار ، مع تقديم طلب للحصول على التسميات التوضيحية.

 <template> <div class="player"> <video controls muted autoPlay crossOrigin="anonymous"> <source :src="`https://localhost:5000/videos/video/${vidName}`" type="video/mp4"> <track label="English" kind="captions" srcLang="en" :src="`https://localhost:5000/videos/video/${vidName}/caption`" default> </video> </div> </template>

لقد أضفنا crossOrigin="anonymous" إلى عنصر الفيديو ؛ وإلا ، فسيفشل طلب التسميات التوضيحية. قم بالتحديث الآن وسترى تمت إضافة التسميات التوضيحية بنجاح.

ما يجب مراعاته عند بناء دفق فيديو مرن.

عند إنشاء تطبيقات دفق مثل Twitch أو Hulu أو Netflix ، هناك عدد من الأشياء التي يتم وضعها في الاعتبار:

  • خط أنابيب معالجة بيانات الفيديو
    يمكن أن يكون هذا تحديًا تقنيًا حيث يلزم وجود خوادم عالية الأداء لخدمة ملايين مقاطع الفيديو للمستخدمين. يجب تجنب الكمون الكبير أو التعطل بأي ثمن.
  • التخزين المؤقت
    يجب استخدام آليات التخزين المؤقت عند إنشاء هذا النوع من التطبيقات مثل Cassandra و Amazon S3 و AWS SimpleDB.
  • جغرافيا المستخدمين
    يجب التفكير في التوزيع الجغرافي لمستخدميك.

خاتمة

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

على عكس الأطر الأخرى ، فإن إنشاء تطبيق باستخدام Nuxt.js و Express.js سهل وسريع للغاية. الجزء الرائع في Nuxt.js هو الطريقة التي يدير بها مساراتك ويجعلك تقوم ببناء تطبيقاتك بشكل أفضل.

  • يمكنك الحصول على مزيد من المعلومات حول Nuxt.js هنا.
  • يمكنك الحصول على الكود المصدري على جيثب.

موارد

  • "إضافة تسميات توضيحية وترجمات إلى فيديو HTML5 ،" MDN Web Docs
  • "فهم التسميات التوضيحية والترجمات" ، Screenfont.ca