rtsp 流媒体播放、nodejs服务部署完整方案

前言: 虽然已经有许多前人踩过这个坑了,可惜的是虽然分享了,但并没有那么分享0.0。至少我看的那篇没有:::所以这里也就不贴那篇文章的链接了。看我这篇就足够了。

效果

请添加图片描述

整体思路

后端取流,实时转换成flv格式,推流到前端通过flv.js进行播放。

后端

后端在这里采用 NodeJS。在你想创建的目录下 npm init 一下,安装如下四个包·
1、express
2、express-ws
3、fluent-ffmpeg
4、websocket-stream
在后端,只做一件事:将拉取到的rtsp流转换成flv格式,如此我们需要在前端先吧rtsp地址传过来。
观察下面代码,忽略其他所有代码,关注于setFfmpegPath
详细说明:
在这里插入图片描述
上图摘自fluent-ffmpeg的npm README中, 简单翻译下,如果FFMPEG_PATH 跟FFPROBE_PATH的环境变量都被设置了,则会取这个完整路径取执行ffmpeg。

  • ffmpeg是什么东西?
    ffmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

也就是说,这个fluent-ffmpeg 依赖于ffmpeg,你得先下载 ffmpeg
ffmpeg下载地址
在这里插入图片描述
也就是说 windows 用户 假使你不想像下方代码一样显示的设置也可以,在你的环境变量中,声明FFMPEG_PATH 的位置 以及 FFPROBE_PATH的位置就好。当然 不管从哪里来说,能够省去一堆操作,直接写完整路径肯定轻松多了。尤其对于我这种前端码农来说。
在这里插入图片描述
上图目录如下代码所示
给没有用过node的靓仔靓女温馨提示:node执行js文件的命令 为 node ?.js
这个? 在当前表示为index
在这里插入图片描述

以下为项目的依赖
在这里插入图片描述

const express = require('express');
const expressWebSocket = require('express-ws');
const ffmpeg = require('fluent-ffmpeg')
const webSocketStream = require('websocket-stream/stream')
ffmpeg.setFfmpegPath(`D:\\Program Files\\rtspDemo\\ffmpeg-2022-07-18-git-cb22d5ea3c-full_build\\bin\\ffmpeg`);
ffmpeg.setFfprobePath(`D:\\Program Files\\rtspDemo\\ffmpeg-2022-07-18-git-cb22d5ea3c-full_build\\bin\\ffprobe`);
function localServer() {
    let app = express();
    app.use(express.static(__dirname));
    expressWebSocket(app, null, {
        perMessageDeflate: true
    });
    app.ws("/rtsp/:id/", rtspRequestHandle)
    app.listen(8888);
    console.log("express listened")
}
function rtspRequestHandle(ws, req) {
    console.log("rtsp request handle");
    const stream = webSocketStream(ws, {
        binary: true,
        browserBufferTimeout: 1000000
    }, {
        browserBufferTimeout: 1000000
    });
    let url = req.query.url;
    console.log("rtsp url:", url);
    console.log("rtsp params:", req.params);
    try {
        ffmpeg(url)
            // buffer_size 字节长度  如果你需要存储与发送更多的流 将102400 继续加!
            .addInputOption("-rtsp_transport", "tcp", "-buffer_size", "102400")  // 这里可以添加一些 RTSP 优化的参数
            .on("start", function () {
                console.log(url, "Stream started.");
            })
            .on("codecData", function () {
                console.log(arguments);
                console.log(url, "Stream codecData.")
                // 摄像机在线处理
            })
            .on("error", function (err) {
                console.log(url, "An error occured: ", err.message);
            })
            .on("end", function () {
                console.log(url, "Stream end!");
                // 摄像机断线的处理
            })
            .outputFormat("flv").videoCodec("copy").noAudio().pipe(stream);
    } catch (error) {
        console.log(error);
    }
}
localServer()

如上,后端的转换就已经处理好了,接着我们要按照后端这里设置的规则**/rtsp/:id/** 去处理。实际这样命名的含义也很简单,我们需要确定传输的对应流数据,给唯一确定的ID 发送对应处理的flv格式的流数据。

其中noAudio是可以更改的,这里仅表示禁用音频流。以及addInputOption 的buffer-size ,这里意味着服务器这里为存储转换的缓冲流的大小。当服务器从流媒体服务器中获取到的流数据大于当前设置的存储大小时会报错,并且停止转换。

前端

经过前面从流媒体服务器获取并且实时的对这个流数据处理成flv,websocket发送返回前端,我们得到了一个实时传输的flv流数据。

npm install flv.js --save

安装完之后就简单了

以刚建的vue2 为例子
APP.VUE

<template>
  <div id="app">
    <button @click="playVideo">
      加载
    </button>
    <div v-for="(item,index) in rtspList" :key="index">
      <HelloWorld :canPlay="canPlay" :id="item.id" :rtsp="item.url" />
    </div>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data(){
    return {
      rtspList: [
        {
          id: '1',
          url: 'rtsp://?/Streaming/Channels/501'
        },
        {
          id: '2',
          url: 'rtsp://?/Streaming/Channels/601'
        },
        {
          id: '3',
          url: 'rtsp://?/Streaming/Channels/801'
        }
      ],
      canPlay: false,
    }
  },
  methods:{
    playVideo(){
      this.canPlay = true;
    }
  }
}
</script>

<style>
html,body{
  margin: 0;
  padding: 0;
}
#app{
  height: 100%;
  width: 100%;
}
</style>

HelloWorld.vue

<template>
  <div>
    <video class="demo-video" ref="player"></video>
  </div>
</template>
<script>
import flvjs from "flv.js";
export default {
  props: {
    rtsp: String,
    id: String,
    canPlay: Boolean
  },
  watch:{
    canPlay(){
      if(this.canPlay){
        console.log('OK');
        this.player.play()
      }
    }
  },
  /**
   * @returns {{player: flvjs.Player}}
   */
  data() {
    return {
      player: null,
    };
  },
  mounted() {
    if (flvjs.isSupported()) {
      let video = this.$refs.player;
      if (video) {
        this.player = flvjs.createPlayer({
          type: "flv",
          isLive: true,
          url: `ws://localhost:8888/rtsp/${this.id}/?url=${this.rtsp}`,
          hasVideo: true,
        });
        this.player.attachMediaElement(video);
        try {
          // 【重要事件监听】http请求建立好后,该事件会一直监听flvjs实例
          this.player.on(flvjs.Events.STATISTICS_INFO, (res) => {
            console.log("请求数据信息");
          });

          this.player.load();
          // this.player.play();
        } catch (error) {
          console.log(error);
        }
      }
    }
  },
  beforeDestroy() {
    this.player.destory();
  },
};
</script>
<style>
.demo-video {
  max-width: 480px;
  max-height: 360px;
}
</style>

代码不多,重在实现。尽管比较粗糙:没有太多的处理,毕竟我这的需求很简单,在页面上能播放rtsp流就可以,而不是出于盈利的直播等,对播放的处理要求不多。

部署

如果有过pm2 的使用可以直接跳过,不必在下文浪费时间。

pm2是node应用的进程管理器。

首先 确保 服务器机子上安装有node 环境。

npm install pm2 -g

全局安装完pm2 之后,命令行

pm2 --version
pm2 ls

一个是查看版本,一个是服务列表。

到后台服务代码的src目录下 入口文件 例如:
在这里插入图片描述
终端输入命令

pm2 start index.js --name rtspToFlvService --watch

简单说明含义: 启动一个 名为rtspToFlvService 的node服务 , 同时监听文件的修改,热部署。

Linux环境部署

linux环境下部署需要注意将代码里的绝对路径那两行删除,前文已经有提到如果手动的设置了ffmpeg的路径这里会优先使用此路径。

将那相关的setPath两行代码删掉,同时在本机上 还需要安装好ffmpeg ,以及配置好环境变量。

也许可能有的疑问

为何需要按下加载才开始动呢?
原因在于现在来说基本浏览器有默认的防噪音策略的限制。 所以理论上来说,直接加载就播放也是可行的,只是你得先把video 标签设置muted属性,表示静音。不过最好还是点一下再说,毕竟又不是什么流氓软件不是,嘿嘿。

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值