สร้างแอปสตรีมวิดีโอด้วย 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 ที่แสดงผลบนเซิร์ฟเวอร์ได้อย่างง่ายดาย เราจะใช้ API ของเราสำหรับวิดีโอและแอปพลิเคชันนี้จะมีมุมมองสองแบบ: รายการของวิดีโอที่มีอยู่และการดูของผู้เล่นสำหรับแต่ละวิดีโอ

ข้อกำหนดเบื้องต้น

  • ความเข้าใจเกี่ยวกับ HTML, CSS, JavaScript, Node/Express และ Vue
  • โปรแกรมแก้ไขข้อความ (เช่น VS Code)
  • เว็บเบราว์เซอร์ (เช่น Chrome, Firefox)
  • ติดตั้ง FFmpeg บนเวิร์กสเตชันของคุณแล้ว
  • โหนด.js เอ็นวีเอ็ม
  • คุณสามารถรับซอร์สโค้ดบน GitHub

การตั้งค่าแอปพลิเคชันของเรา

ในแอปพลิเคชันนี้ เราจะสร้างเส้นทางเพื่อส่งคำขอจากส่วนหน้า:

  • เส้นทาง 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 ในเบราว์เซอร์ของคุณและคุณจะเห็นวิดีโอที่เล่นอยู่

คำขอให้จัดการโดย Frontend

ด้านล่างนี้คือคำขอที่เราจะทำกับแบ็กเอนด์จากฟรอนท์เอนด์ของเราซึ่งเราต้องการให้เซิร์ฟเวอร์จัดการ

  • /videos
    ส่งกลับอาร์เรย์ของข้อมูลจำลองวิดีโอที่จะใช้เพื่อเติมรายการวิดีโอบน Home ในส่วนหน้าของเรา
  • /video/:id/data
    ส่งคืนข้อมูลเมตาสำหรับวิดีโอเดียว ใช้โดยหน้า Player ในส่วนหน้าของเรา
  • /video/:id
    สตรีมวิดีโอด้วย 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 และใช้ express router เพื่อสร้างเส้นทางของเรา

 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

เราต้องการวิดีโอสามรายการ ดังนั้นให้คัดลอกวิดีโอตัวอย่างจากซอร์สโค้ดของบทช่วยสอนไปยังไดเร็กทอรี asset 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 ซึ่งหมายความว่าการตอบสนองมีเนื้อหาบางส่วน ซึ่งหมายความว่าเบราว์เซอร์จะทำการขอต่อไปจนกว่าจะดึงชิ้นส่วนของวิดีโอทั้งหมด

จะเกิดอะไรขึ้นกับการเชื่อมต่อที่ไม่เสถียร

หากผู้ใช้ใช้การเชื่อมต่อที่ช้า สตรีมเครือข่ายจะส่งสัญญาณโดยขอให้แหล่ง I/O หยุดชั่วคราวจนกว่าไคลเอ็นต์จะพร้อมสำหรับข้อมูลเพิ่มเติม นี้เรียกว่า แรงดันย้อนกลับ เราสามารถยกตัวอย่างนี้ไปอีกขั้นหนึ่งและดูว่าการขยายสตรีมนั้นง่ายเพียงใด เพิ่มการบีบอัดได้อย่างง่ายดายด้วย!

 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 ใน repo และดาวน์โหลดคำอธิบายภาพ

มาสร้างเส้นทางใหม่ที่จะจัดการกับคำขอคำบรรยาย:

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

การสร้าง Frontend ของเรา

ในการเริ่มต้นในส่วนที่มองเห็นได้ของระบบของเรา เราจะต้องสร้างโครงนั่งร้านส่วนหน้าของเรา

หมายเหตุ : คุณต้องใช้ vue-cli เพื่อสร้างแอปของเรา หากคุณไม่ได้ติดตั้งไว้บนคอมพิวเตอร์ คุณสามารถเรียกใช้ npm install -g @vue/cli เพื่อติดตั้งได้

การติดตั้ง

ที่รูทของโปรเจ็กต์ มาสร้างโฟลเดอร์ front-end กัน:

 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 ที่แสดง Streaming App โดยมีรูปแบบเล็กน้อย

มานำเข้า 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
การสตรีมวิดีโอเริ่มต้นเมื่อผู้ใช้คลิกที่ภาพขนาดย่อ (ตัวอย่างขนาดใหญ่)

การเพิ่มไฟล์คำบรรยายของเรา

ในการเพิ่มไฟล์แทร็ก เราต้องแน่ใจว่าไฟล์ . .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 ได้ที่นี่
  • คุณสามารถรับซอร์สโค้ดบน Github

ทรัพยากร

  • “การเพิ่มคำบรรยายในวิดีโอ HTML5” MDN Web Docs
  • “การทำความเข้าใจคำบรรยายและคำบรรยาย” Screenfont.ca