张国伟 发表于 2024-11-18 20:53:11

node通过ffmpeg将多路rtsp、rtmp流媒体转换为多端口websocket流供前端播放

node通过ffmpeg将多路rtsp、rtmp流媒体转换为多端口websocket流供前端播放



1 安装node

node官网下载安装:https://nodejs.org/zh-cn/download/prebuilt-installer
2 安装ffmpeg

ffmpeg官网下载:https://ffmpeg.org/
github下载:https://github.com/FFmpeg/FFmpeg
3 【重要】使用node搭建rtsp、rtmp转码服务器(必须要提前安装ffmpeg)

// 初始化项目并安装插件node-rtsp-stream
npm init -y
npm install express
npm install node-rtsp-stream
npm install get-port
新建index.js作为主文件,代码如下
const Stream = require("node-rtsp-stream"); // 引入node-rtsp-stream模块,rtsp/rtmp转码工具
const express = require("express"); // 引入express模块,http模块封装了http协议
const getPort = require("get-port");
const app = express(); // 创建一个express实例,提供http服务
/* **************************************************http-config************************************************ */

// 设置跨域资源共享
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*"); // 允许任何源
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use((req, res, next) => {
res.setHeader(
    "Content-Security-Policy",
    "default-src https: 'self'; script-src https: 'self' 'unsafe-inline' 'unsafe-eval' http://trusted-domain.com;"
);
next();
});
/* **************************************************var************************************************ */
// ws流使用端口列表
let PostList = [];
/* **************************************************api************************************************ */
/* 关闭组件进程未关闭 */
// Name of the stream, used to identify it in the API
// 定义接口


/* 清除某一端口任务 */
app.get("/cleraWsPort", (req, res) => {
let query = req.query;
if (PostList.length == 0) {
    res.send({ status: "success", message: "未找到该端口" });
    return;
}
PostList.forEach((element, index) => {
    if (element.port == query.port) {
      element.stream.stop();
      PostList.splice(index, 1);
      res.send({ status: "success", message: "关闭成功:" + port });
    } else {
      res.send({ status: "success", message: "未找到该端口" });
    }
});
});

/* 清空所有端口任务 */
app.get("/cleraWsAll", async (req, res) => {
for (let index = 0; index < PostList.length; index++) {
    await PostList.stream.stop();
}
PostList = [];
console.log("PostList->>>", PostList);
res.send({ status: "success", message: "已清空所有端口" });
});

/* rtmp、rtsp转weboscket流 */
app.get("/rtmpToWebsocket", (req, res) => {
let query = req.query; // 获取请求参数
// 获取该端口是否已经存在,存在则返回该端口,不存在则创建可用端口
for (let index = 0; index < PostList.length; index++) {
    const element = PostList;
    if (element.name == query.name) {
      /* 存在则返回该端口 */
      res.send({ port: element.port, message: "已存在该端口" });
      return;
    }
}
// 该视频流为发现,获取可用端口,并进行发布websocket流
getPort({ port: getPort.makeRange(20000, 21000) }) // 获取可用端口
    .then((port) => {
      try {
      // log
      console.log("rtmpUrl->>>", query.rtmpUrl);
      console.log("port->>>", port);
      // 创建一个Stream实例,将rtmpUrl转换为websocket流并发布到(getport)指定的端口
      let stream = new Stream({
          name: "name",
          streamUrl: query.rtmpUrl, //query.rtmpUrl,
          wsPort: port, //18965,随机端口号
          wsPath: "/" + query.name, //暂时无效,如果需要使用效果需要修改videoStram.js中new WebSocket函数
          /* ffmpegOptions,其他配置 */
          ffmpegOptions: {
            // options ffmpeg flags
            "-stats": "", //
            "-r": "60", //key,帧率
            "-s": "1920x1080", //帧像素
          },
      });

      PostList.push({ name: query.name, port, stream });
      } catch (error) {
      console.log("error->>>", error);
      }

      res.send({ port, message: "创建成功" });
    })
    .catch((err) => {
      console.error(`Error: ${err}`);
    });
});

/* ************************************************http_listen************************************************ */
// 监听3000端口
app.listen(9001, () => {
console.log("Server running on http://localhost:9001");
});
// 执行命令为
node ./index.js
传参:
rtmpUrl:‘rtmp或rtsp流媒体路径’
name:‘自己随机定义,唯一标识,name重复的rtmp或rtsp不会举行转码’
哀求样例:
http://127.0.0.1:9001/rtmpToWebsocket?rtmpUrl=‘rtmp://xxx’&name=‘name1’
回参样例:
{
port:‘20000’,
message: “创建成功”
}
可以通过前端播放ws://127.0.0.1:20000了
4 前端(vue3)播放websocket流

// 安装jsmpeg-player
npm i jsmpeg-player
npm i axios
<script setup>
// jsmpeg播放器
import JSMpeg from 'jsmpeg-player'
import axios from 'axios'
...
axios.get(`http://127.0.0.1:9001/rtmpToWebsocket?rtmpUrl='rtmp://xxx'&name='name1'`).then((res) => {
      wsport = res.data.port
                new JSMpeg.Player(`ws://127.0.0.1:` + wsport + `/`, {
      bufferSize: 8,
      videoBufferSize: 20484096,
      canvas: document.getElementById('video')
   })
})

...
</script>
<template>
<canvas :id="video" style="width: 100%; height: 100%"></canvas>
</template>

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: node通过ffmpeg将多路rtsp、rtmp流媒体转换为多端口websocket流供前端播放