上一篇文章介绍了# 监控视频流媒体播放-jsmpeg+ffmpeg[监控视频流媒体播放-jsmpeg+ffmpeg监控视频流有两种类型,包含H264、H265。 尝试过的方法: webRT - 掘金]这种方法支持H264、H265的播放,但只能播放单路流,node服务使用的websocket-relay.js会将收到的ffmpeg转码的流广播给所有与node服务建立链接的客户端,这样播放多路流会出现串流现象。因此需要对websocket-relay.js进行改造。
- 将websocket-relay.js改造如下
// Use the websocket-relay to serve a raw MPEG-TS over WebSockets. You can use
// ffmpeg to feed the relay. ffmpeg -> websocket-relay -> browser
// Example:
// node websocket-relay yoursecret 8081 8082
// ffmpeg -i <some input> -f mpegts http://localhost:8081/yoursecret
var fs = require("fs"),
http = require("http"),
WebSocket = require("ws");
if (process.argv.length < 3) {
console.log(
"Usage: \n" +
"node websocket-relay.js <secret> [<stream-port> <websocket-port>]"
);
process.exit();
}
var STREAM_SECRET = process.argv[2],
STREAM_PORT = process.argv[3] || 8081,
WEBSOCKET_PORT = process.argv[4] || 8082,
RECORD_STREAM = false;
var clients = [];
// Websocket Server
var socketServer = new WebSocket.Server({
port: WEBSOCKET_PORT,
perMessageDeflate: false,
});
socketServer.connectionCount = 0;
socketServer.on("connection", function (socket, upgradeReq) {
socketServer.connectionCount++;
socket.reqUrl = upgradeReq.url
clients.push(socket);
console.log(
"New WebSocket Connection: ",
(upgradeReq || socket.upgradeReq).socket.remoteAddress,
(upgradeReq || socket.upgradeReq).headers["user-agent"],
"(" + socketServer.connectionCount + " total)"
);
socket.on("close", function (code, message) {
socketServer.connectionCount--;
console.log(
"Disconnected WebSocket (" + socketServer.connectionCount + " total)"
);
});
});
socketServer.broadcast = function (data, ffmpeg_url) {
if (clients) {
clients.forEach(client=>{
if (client.readyState === WebSocket.OPEN && ffmpeg_url.includes(client.reqUrl)) {
client.send(data);
}
});
}
};
// HTTP Server to accept incomming MPEG-TS Stream from ffmpeg
var streamServer = http.createServer(function (request, response) {
var params = request.url.substr(1).split("/");
if (params[0] !== STREAM_SECRET) {
console.log(
"Failed Stream Connection: " +
request.socket.remoteAddress +
":" +
request.socket.remotePort +
" - wrong secret."
);
response.end();
}
response.connection.setTimeout(0);
console.log(
"Stream Connected: " +
request.socket.remoteAddress +
":" +
request.socket.remotePort
);
request.on("data", function (data) {
socketServer.broadcast(data, request.url);
if (request.socket.recording) {
request.socket.recording.write(data);
}
});
request.on("end", function () {
console.log("close");
if (request.socket.recording) {
request.socket.recording.close();
}
});
// Record the stream to a local file?
if (RECORD_STREAM) {
var path = "recordings/" + Date.now() + ".ts";
request.socket.recording = fs.createWriteStream(path);
}
});
// Keep the socket open for streaming
streamServer.headersTimeout = 0;
streamServer.listen(STREAM_PORT);
console.log(
"Listening for incomming MPEG-TS Stream on http://127.0.0.1:" +
STREAM_PORT +
"/<secret>"
);
console.log(
"Awaiting WebSocket connections on ws://127.0.0.1:" + WEBSOCKET_PORT + "/"
);
- 使用ffmpeg转码多路流时,需要打开多个cmd窗口,每个流输出的url进行区分
比如对第一个rtsp流rtsp://user:password@ip
ffmpeg -i rtsp://user:password@ip -q 0 -f mpegts -codec:v mpeg1video -s 800x600 http://127.0.0.1:8081/supersecret/live1
对第二个rtsp流rtsp://user:password@ip
ffmpeg -i rtsp://user:password@ip -q 0 -f mpegts -codec:v mpeg1video -s 800x600 http://127.0.0.1:8081/supersecret/live2
- web页面使用jsmpeg进行转码时需要使用对应的url解码
<template>
<div class="right_one_box">
<div class="title"><span></span>蘑菇房视频监控</div>
<div class="box_con">
<div class="con">
<canvas id="video-canvas1" style="height: 500px; wight: 700px"></canvas>
<canvas id="video-canvas2" style="height: 500px; wight: 700px"></canvas>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
path1: 'ws://127.0.0.1:8082/live1', //你拉取视频源地址
canvas1: null,
path2: 'ws://127.0.0.1:8082/live2', //你拉取视频源地址
canvas2: null,
}
},
mounted () {
this.canvas1 = document.getElementById('video-canvas1')
var player1 = new JSMpeg.Player(this.path1, { canvas: this.canvas1 })
this.canvas2 = document.getElementById('video-canvas2')
var player2 = new JSMpeg.Player(this.path2, { canvas: this.canvas2 })
},
methods: {
}
}
</script>