สวัสดีครับทุกคน กลับมาพบกับบทความพื้นฐาน Back-End ง่าย ๆ สไตล์แอดเอฟกันอีกแล้ววว วันนี้เราจะมาสร้างเซิร์ฟเวอร์ที่เอาไว้สตรีมมิ่งวิดีโอด้วย Node.js กัน จะมีวิธีการเป็นยังไงไปดูกัน!
สำหรับโปรเจกต์ที่เราจะมาทำกันจะเป็นหน้าเว็บแบบง่าย ๆ ด้วยการใช้ HTML ที่มี video element โดยไปขอวิดีโอจาก API เส้น “/video” โดยตอนที่ขอวิดีโอไปเบราว์เซอร์จะแจ้งช่วงของข้อมูลที่ต้องการเป็นตัวเลย (เหมือนบอกว่าอยากดูวิดีโอตั้งแต่ตำแหน่งไหน)
ตัวอย่างเช่น ช่วงแรกของวิดีโอจะขอข้อมูลตั้งแต่ตำแหน่งที่ 0 เป็นต้นไป (เขียนว่า 0-) หลังจากนั้น เซิร์ฟเวอร์ก็จะส่ง status code 206 กลับมาเพื่อบอกว่าข้อมูลส่งมาแค่บางส่วน พร้อมทั้งช่วงของข้อมูล และ ขนาดของข้อมูลที่เซิร์ฟเวอร์ response กลับไปด้วย
ช่องของวิดีโอจะรู้ได้ว่าวิดีโอไม่ครบจาก response header แต่มันก็จะเล่นเท่าที่มันดาวน์โหลดมาได้ พอเล่นไปเรื่อย ๆ ช่องที่เล่นวิดีโอจะขอข้อมูลไปเพิ่มอีก เซิร์ฟเวอร์ก็จะส่งข้อมูลที่เบราเซอร์ขอมา ทำแบบนี้วนไปจนครบทั้งวิดีโอ
🚀 มาเริ่มทำโปรเจกต์ไปพร้อมกันเลย!
เปิด Terminal หรือ Command Prompt แล้วพิมพ์คำสั่งต่อไปนี้เพื่อสร้างโฟลเดอร์และเข้าไปในโฟลเดอร์ที่สร้างขึ้นใหม่
mkdir video-streaming
cd video-streaming
สร้างโปรเจกต์ Node.js ด้วย npm init เพื่อสร้างไฟล์ package.json ซึ่งเป็นไฟล์ที่ใช้จัดการ dependencies และข้อมูลของโปรเจกต์
npm init -y
ติดตั้งแพ็คเกจที่จำเป็น โดยในโปรเจกต์นี้ เราจะใช้ express ในการสร้างเซิร์ฟเวอร์
npm install express
สร้าง server โดยการเขียนในไฟล์ server.js ทำการเรียกใช้ Express.js และใช้ fs (file system) เพื่อจัดการกับไฟล์วิดีโอของเรา
const express = require("express");
const app = express();
const fs = require("fs");
จากนั้นเราจะสร้าง route สำหรับ root path (/) เพื่อเสิร์ฟไฟล์ index.html เมื่อมีการเข้าถึงหน้าเว็บ
app.get("/", function (req, res) {
res.sendFile(__dirname + "/index.html");
});
จากนั้นกำหนด route เส้น /video ที่เป็น API หลักสำหรับการทำงานในบทความนี้ โดยเราจะทำการเช็ค header Range เพื่อให้แน่ใจว่ามี Request เพื่อขอช่วงของวิดีโอจาก Client ถ้าไม่มีเราจะส่ง Status Code 400 กลับไป
app.get("/video", function (req, res) {
const range = req.headers.range;
if (!range) {
res.status(400).send("Requires Range header");
}
หลังจากนั้นเราจะกำหนด path ของไฟล์วิดีโอและขนาดของไฟล์วิดีโอ
const videoPath = "video.mp4";
const videoSize = fs.statSync("video.mp4").size;
แล้วก็ทำการคำนวณขนาดของชิ้น (chunk) ที่จะส่งไป โดยเริ่มจากตำแหน่ง start ที่ได้จาก Range header และสิ้นสุดที่ end โดยขนาดเราสามารถกำหนดได้ โดยตัวอย่างนี้จะอยู่ที่ชิ้นละ 1MB
const CHUNK_SIZE = 10 ** 6; // 1MB
const start = Number(range.replace(/\D/g, ""));
const end = Math.min(start + CHUNK_SIZE, videoSize - 1);
จากนั้นเราจะสร้าง headers ที่จำเป็นในการส่ง Response ไปยัง Client โดยใช้ Status Code เป็น 206 ซึ่งหมายถึง Partial Content แบบว่าเนื้อหายังไม่ครบ ยังมีต่อนะ
const contentLength = end - start + 1;
const headers = {
"Content-Range": `bytes ${start}-${end}/${videoSize}`,
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
"Content-Type": "video/mp4",
};
res.writeHead(206, headers);
สุดท้ายเราจะสร้าง stream สำหรับวิดีโอจากตำแหน่ง start ถึง end แล้วทำการส่ง stream นั้นไปยังไคลเอ็นต์
const videoStream = fs.createReadStream(videoPath, { start, end });
videoStream.pipe(res);
});
เป็นอันว่าจบฟังก์ชั่น สตรีมมิ่งวิดีโอเรียบร้อย แล้วก็อย่าลืมใส่ listen เพื่อบอกว่าให้ Server รันอยู่ที่ Port ไหนด้วย
app.listen(8000, function () {
console.log("Listening on port 8000!");
});
โอเค! ฝั่งของ Back-End ก็จบไปเป็นที่เรียบร้อย ตอนรันเราก็สามารถใช้คำสั่ง node แล้วตามด้วยชื่อไฟล์ server.js ได้เลย หรือ ใครจะใช้ท่า nodemon หรืออื่น ๆ ก็ตามถนัด
ฝั่งของหน้าบ้าน
โดยในตัวอย่างนี้จะสร้างไฟล์ HTML ง่าย ๆ พร้อม CSS นิดหน่อยในไฟล์ index.html นี้เลย โค้ดที่มีก็จะประมาณนี้
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Video Streaming With Node</title>
<style>
body {
margin: 5% auto;
max-width: 100%;
background-color: rgb(14, 14, 14);
padding-top: 10%;
padding-left: 35%;
}
</style>
</head>
<body>
<video id="videoPlayer" width="50%" controls muted="muted" autoplay>
<source src="/video" type="video/mp4" />
</video>
</body>
</html>
โดยหลัก ๆ แล้วโค้ดนี้คือเราสร้าง element <video> แล้วก็ไปเรียก /video มาโดยมีการตั้งค่านิด ๆ หน่อย ๆ คือให้มีตัวควบคุม แค่นี้เราก็ได้หน้าเว็บของเราก็จะสามารถเล่นวิดีโอได้แล้วนั่นเอง!
สำหรับใครที่อ่านมาถึงตรงนี้แล้ว อยากทำระบบแบบนี้ไปใช้งานร่วมกับ API ของตัวเอง แต่ยังไม่รู้จะเริ่มต้นยังไง? ตอนนี้หลักสูตร Road to Back-End Developer BootCamp รุ่นที่ 2 เปิดลงทะเบียนแล้ว!