0.0.4 • Published 1 year ago

videoflvjs v0.0.4

Weekly downloads
-
License
-
Repository
-
Last release
1 year ago

这里遇到的问题是如何在前端播放rtsp视频流

HTML 并不标准支持 RTSP 流, 经过网上各种查资料并一番讨论后初步拟定如下方案,node + ffmpeg + websocket + flv.js

  • 在node服务中建立websocket
  • 通过fluent-ffmpeg转码,将RTSP 流转为flv格式
  • 前端通过flv.js连接websocket,并对获取的flv格式视频数据进行渲染播放

node服务的搭建

首先是新建一个项目,配置基础的webpack和babel,并安装websocket相关的两个库 wswebsocket-stream 。 然后新建一个index.js文件,搭建websocket服务:

import WebSocket from 'ws'
import webSocketStream from 'websocket-stream/stream'

// 建立WebSocket服务
const wss = new WebSocket.Server({ port: 8888, perMessageDeflate: false })

// 监听连接
wss.on('connection', handleConnection)

// 连接时触发事件
function handleConnection (ws, req) {
  console.log('一个客户端连接进来啦')
}

一个简单的websocket服务就搭建好了,可启动websocket服务,端口是8888。可在前端通过websocket连接该地址,测试是否连接成功。

ffmpeg转码

fluent-ffmpeg这个库类似语法糖,本质上就是通过nodejs在终端中执行ffmpeg的命令,它将繁琐的ffmpeg命令进行封装,转化成易于理解的链式调用,让我们不需要花费太多的时间去了解ffmpeg命令中琐碎的细节,只需通过封装好的一些显而易见的方法就可以操作视频转码。

import WebSocket from 'ws'
import webSocketStream from 'websocket-stream/stream'
import ffmpeg from 'fluent-ffmpeg'

// 建立WebSocket服务
const wss = new WebSocket.Server({ port: 8888, perMessageDeflate: false })

// 监听连接
wss.on('connection', handleConnection)

// 连接时触发事件
function handleConnection (ws, req) {
  // 获取前端请求的流地址(前端websocket连接时后面带上流地址)
  const url = req.url.slice(1)
  // 传入连接的ws客户端 实例化一个流
  const stream = webSocketStream(ws, { binary: true })
  // 通过ffmpeg命令 对实时流进行格式转换 输出flv格式
  const ffmpegCommand = ffmpeg(url)
    .addInputOption('-analyzeduration', '100000', '-max_delay', '1000000')
    .on('start', function () { console.log('Stream started.') })
    .on('codecData', function () { console.log('Stream codecData.') })
    .on('error', function (err) {
      console.log('An error occured: ', err.message)
      stream.end()
    })
    .on('end', function () {
      console.log('Stream end!')
      stream.end()
    })
    .outputFormat('flv').videoCodec('copy').noAudio()

  stream.on('close', function () {
    ffmpegCommand.kill('SIGKILL')
  })

  try {
    // 执行命令 传输到实例流中返回给客户端
    ffmpegCommand.pipe(stream)
  } catch (error) {
    console.log(error)
  }
}

这样,简单的websocket和流转码服务就搭建好了,运行起来。如果后续投入生产环境时,也可以通过docker进行服务端部署,开机自运行。

前端flv.js获取视频数据并渲染

服务端搭建完,接下来就等前端连接服务器上的websocket,获取转码后的flv格式数据,然后渲染出来就行了。我们通过flv.js这个库来便捷的实现它。 安装flv.js,在vue中使用:

<template>
  <div class="page-container">
    <span class="title">{{ props.title }}</span>
    <div class="video-container">
      <video
        ref="videoElementRef"
        class="centeredVideo"
        controls
        autoplay
        muted
        v-bind="$attrs"
      ></video>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted,  } from "vue";
import FlvJs from "flv.js";

const videoElementRef = ref(null);

const props = defineProps({
  url: {
    type: String,
    required: true,
  },
  wsUrl: {
    type: String,
    required: true,
    default: "ws://localhost:8888/",
  },
  title: {
    type: String,
    default: "title",
  },
});

onMounted(() => {
  flv_load(props.url);
});

const flv_load = (url: string) => {
  if (FlvJs.isSupported()) {
    let videoElem = videoElementRef.value;
    let flvPlayer = FlvJs.createPlayer(
      {
        type: "flv", //媒体类型
        url: props.wsUrl + url, //flv格式媒体URL
        isLive: true, //数据源是否为直播流,
      },
      {
        enableWorker: false, // 是否启用分离的线程进行转换
        enableStashBuffer: false, //关闭IO隐藏缓冲区
        autoCleanupSourceBuffer: true, //自动清除缓存
        fixAudioTimestampGap: false,
      }
    );
    flvPlayer.attachMediaElement(videoElem);
    flvPlayer.load();
    flvPlayer.play();
  }
};


</script>

上传组件到npm库,方便一会使用直接调用

https://www.npmjs.com/package/videoflvjs

把node服务直接打包到docker镜像库中,主机可以直接下载运行

https://hub.docker.com/r/luabucn/nodewsrtsp

若有疑问 联系 武汉食铁兽科技有限公司 邮箱 zhangchenlinluabu@163.com

0.0.4

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago

0.0.1

1 year ago