创建 Node.js 视频流应用之后端
在本文中,将展示一个非常简单的 Node.js 应用程序,用于在线流媒体视频传输。本文仅涵盖后端,在下一部分中,将使用 Vue.js 创建前端。话不多说,下面开始进入主题。
初始化
创建项目文件夹 vue-video-stream
,进入文件夹,再创建文件夹 express-service
,用户存放后端服务相关代码,进入express-service
,运行 npm init
初始化配置并安装相关依赖项,如下:
npm install express cors --save
npm install -D nodemon
安装完成后修改 package.json
中的调试及启动脚本,如下:
"scripts": {
"start": "node ./index.js",
"debug": "nodemon --trace-warnings --inspect=0.0.0.0:9229 ./index.js"
}
至此完成了后端服务的初始化,接下来完成主体部分。
主体逻辑
主体逻辑的代码主要在文件 index.js
文件中,如下:
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.get("/", (req, res) => {
// 根目录路由
});
const PORT = process.env.PORT || 8100;
app.listen(PORT, () => {
console.log(`服务运行端口:${PORT}`);
});
在流媒体传输视频的目录中 express-service
添加一个新的 index.html
文件。文件的 src
必须指向要继续进行流媒体传输的服务器端点。
注意:这里的
index.html
文件主要用于演示后台服务,后续将会使用 VUE 来替换。
<!DOCTYPE html>
<html lang="zh">
<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>流媒体传输 Express 服务</title>
<style type="text/css">
body {
margin: 0px;
padding: 0px;
background-color: #000;
}
video {
position: absolute;
width: 800px;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<video src="/video/20220315" width="800px" height="auto" controls autoplay id="videoPlayer"></video>
</body>
</html>
现在需要设置 /video
路由和控制器逻辑,作为索引路由,还需要发送这个 HTML
文件进行渲染。接下来更新 index.js
文件代码,如下:
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.get("/", (req, res) => {
// 根目录路由
res.sendFile(__dirname + "/index.html");
});
// 视频路由
app.use("/video", require("./routes/index"));
const PORT = process.env.PORT || 8100;
app.listen(PORT, () => {
console.log(`服务运行端口:${PORT}`);
});
接下来在目录 express-service
创建文件夹 routes
,在文件夹中创建脚本文件 index.js
,代码如下:
const router = require("express").Router();
const videoController = require("../controller/videoController");
router.get("/:videoId", videoController.streamVideo);
module.exports = router;
在目录 express-service
创建文件夹 controller
,在文件夹中创建脚本文件 videoController.js
,代码如下:
const fs = require("fs");
module.exports.streamVideo = (req, res) => {
const range = req.headers.range;
const videoId = req.params.videoId; // ID或者视频文件名称
if (!range) {
res.status(400).send("无效Range");
}
const processPath = process.cwd(); // 获取服务运行路径
const videoPath = `${processPath}/resources/${videoId}.mp4`;
const videoSize = fs.statSync(videoPath).size;
const chunkSize = 10 ** 6; // 1 mb
const start = Number(range.replace(/\D/g, ""));
const end = Math.min(start + chunkSize, videoSize - 1);
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);
const videoStream = fs.createReadStream(videoPath, { start, end });
videoStream.pipe(res);
};
下面就来介绍 videoController
的主要逻辑,在请求 headers
中,提取了 range
( range
是当前在视频缓冲区中的部分)。如果range
不存在,抛出一个错误。否则,在文件系统中找到该文件。
然后,设置要随每个并发请求发送的块大小(代码中设置为 1 MB
, Math.pow(10,6)
或简单的 10 ** 6
)。然后定义开始和结束变量,start
变量决定了发送的视频的起点,对于 end
变量,需要确定 (start +chunk
) 或视频大小长度之间的最小值,避免超出。
最后,确定实际发送的内容长度,内容长度是开始值和结束值之间的差异。然后使用刚刚在它上面计算的值生成的 headers
对象。在代码的最后一部分,发送一个内容响应 (206),它是 express
框架的一部分,并使用 fs
(Node.js 核心)模块将该响应与读取流进行管道传输。
现在来启动服务,执行如下:
npm run start
如果是要调试代码,避免手动重启,可以执行一下命令:
npm run debug
这样在修改 js
代码后服务将会自动重启。
启动后在浏览器中输入 http://127.0.0.1:8100/
,就可以看到如下效果:
在下一部分中,将使用 Vue.js
设计前端,敬请关注。