0.0.4 • Published 1 year ago
videoflvjs v0.0.4
这里遇到的问题是如何在前端播放rtsp视频流
HTML 并不标准支持 RTSP 流, 经过网上各种查资料并一番讨论后初步拟定如下方案,node + ffmpeg + websocket + flv.js
- 在node服务中建立websocket
- 通过fluent-ffmpeg转码,将RTSP 流转为flv格式
- 前端通过flv.js连接websocket,并对获取的flv格式视频数据进行渲染播放
node服务的搭建
首先是新建一个项目,配置基础的webpack和babel,并安装websocket相关的两个库 ws
、websocket-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