Make streaming work & much more elegant

This commit is contained in:
2022-04-17 10:12:50 -04:00
parent 76c8876bd8
commit 507d4232f0
14 changed files with 2373 additions and 214 deletions

View File

@@ -1,38 +0,0 @@
/*jshint esversion: 6 */
const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
const child_process = require('child_process');
const EventEmitter = require('events');
const spawn = require('cross-spawn');
class Mpeg1Muxer extends EventEmitter {
constructor(options) {
super(options);
this.url = options.url;
this.width = options.width;
// this.stream = child_process.spawn(ffmpegPath, ['-y', '-loglevel', 'quiet', "-rtsp_transport", "tcp", "-i", this.url, '-vf', 'yadif', '-f', 'mpegts', '-r', '30', '-codec:v', 'mpeg1video', '-codec:a', 'mp2', '-b:a', '128k', '-b:v', '4096k', '-muxdelay', '0', '-', './app/stream/stream.ts'], {
// detached: false
// });
this.stream = child_process.spawn(ffmpegPath, ['-y', '-loglevel', 'quiet', "-rtsp_transport", "tcp", "-i", this.url, '-filter:v', 'scale=1280:-1', '-f', 'mpegts', '-r', '30', '-codec:v', 'mpeg1video', '-codec:a', 'mp2', '-b:a', '128k', '-b:v', '1500k', '-', './app/stream/stream.ts'], {
detached: false
});
this.inputStreamStarted = true;
this.stream.stdout.on('data', (data) => { return this.emit('mpeg1data', data); });
this.stream.stderr.on('data', (data) => { return this.emit('ffmpegError', data); });
}
stop() {
try {
this.stream.stdout.removeAllListeners();
} catch(err) {
console.log("Muxer: " + err);
}
this.stream.kill();
this.stream = undefined;
}
}
module.exports = Mpeg1Muxer;

View File

@@ -0,0 +1,21 @@
const path = require('path');
const express = require('express');
const router = express.Router();
const db = require(path.resolve(__dirname, '../_helpers/db.js'));
const Camera = db.Camera;
const { proxy, scriptUrl } = require('rtsp-relay')(router);
console.log(`Connecting to camera: rtsp://${Camera.rtsp}`);
const handler = proxy({
url: `rtsp://10.0.1.3:554/1`,
// if your RTSP stream need credentials, include them in the URL as above
verbose: false,
additionalFlags: ['-q', '1']
});
router.ws('/', handler);
module.exports = router;

View File

@@ -1,124 +0,0 @@
/*jshint esversion: 6 */
// Thanks to: https://github.com/Wifsimster/node-rtsp-stream-es6
const WebSocket = require('ws');
const EventEmitter = require('events');
const STREAM_MAGIC_BYTES = "jsmp";
const Mpeg1Muxer = require('./mpeg1muxer');
class VideoStream extends EventEmitter {
constructor(options) {
super(options);
this.name = options.name;
this.url = options.url;
this.width = options.width;
this.height = options.height;
this.port = options.port;
this.stream = void 0;
this.stream2Socket();
}
stream2Socket() {
this.server = new WebSocket.Server({
port: this.port
});
this.server.on('connection', (socket) => {
console.log(`New connection: ${this.name}`);
let streamHeader = new Buffer(8);
streamHeader.write(STREAM_MAGIC_BYTES);
streamHeader.writeUInt16BE(this.width, 4);
streamHeader.writeUInt16BE(this.height, 6);
socket.send(streamHeader);
socket.on('close', () => {
console.log(`${this.name} disconnected !`);
if (this.server.clients.length <= 0) {
this.mpeg1Muxer.stop();
this.server.close();
}
});
});
this.on('camdata', (data) => {
for (let i in this.server.clients) {
let client = this.server.clients[i];
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
}
});
}
onSocketConnect(socket) {
let streamHeader = new Buffer(8);
streamHeader.write(STREAM_MAGIC_BYTES);
streamHeader.writeUInt16BE(this.width, 4);
streamHeader.writeUInt16BE(this.height, 6);
socket.send(streamHeader, {
binary: true
});
console.log(`New connection: ${this.name} - ${this.wsServer.clients.length} total`);
return socket.on("close", function(code, message) {
return console.log(`${this.name} disconnected - ${this.wsServer.clients.length} total`);
});
}
start() {
this.mpeg1Muxer = new Mpeg1Muxer({
url: this.url,
width: this.width
});
this.mpeg1Muxer.on('mpeg1data', (data) => {
return this.emit('camdata', data);
});
let gettingInputData = false;
let gettingOutputData = false;
let inputData = [];
let outputData = [];
this.mpeg1Muxer.on('ffmpegError', (data) => {
data = data.toString();
if (data.indexOf('Input #') !== -1) {
gettingInputData = true;
}
if (data.indexOf('Output #') !== -1) {
gettingInputData = false;
gettingOutputData = true;
}
if (data.indexOf('frame') === 0) {
gettingOutputData = false;
}
if (gettingInputData) {
inputData.push(data.toString());
let size = data.match(/\d+x\d+/);
if (size != null) {
size = size[0].split('x');
if (this.width == null) {
this.width = parseInt(size[0], 10);
}
if (this.height == null) {
return this.height = parseInt(size[1], 10);
}
}
}
});
this.mpeg1Muxer.on('ffmpegError', (data) => {
return global.process.stderr.write(data);
});
return this;
}
stop(serverCloseCallback) {
this.server.close(serverCloseCallback);
this.server.removeAllListeners();
this.server = undefined;
this.mpeg1Muxer.stop();
this.mpeg1Muxer.removeAllListeners();
this.mpeg1Muxer = undefined;
}
}
module.exports = VideoStream;