IP camera: stream and record a fragment

happy new year,
at the moment i dnt use github

what I am doing to the streamer is passing the rtsp recording to a websocket for the stream:

For this I use ffmpeg.exe with a code like the following:
ffmpeg -f rtsp -i "rtsp: // user: pass@192.168.xx: port / cameradirection" -vf scale = 320: 240 -f mpegts -codec: v mpeg1video -bf 0 -codec: a mp2 -r 30 http://127.0.0.1: 8081/password

[{"id":"18a7750b.88455b","type":"exec","z":"fdaddf2e.250df","command":"ffmpeg  -f rtsp -i \"rtsp://\" -vf scale=320:240 -f mpegts  -codec:v mpeg1video -bf 0 -codec:a mp2 -r 30 http://127.0.0.1:8081/password","addpay":false,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"Decode RTSP stream","x":560,"y":980,"wires":[["652938f2.df8da8"],["652938f2.df8da8"],["652938f2.df8da8"]]},{"id":"6bd761d4.db37b","type":"inject","z":"fdaddf2e.250df","name":"Start stream","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":980,"wires":[["18a7750b.88455b"]]},{"id":"a38dafa2.5778","type":"change","z":"fdaddf2e.250df","name":"","rules":[{"t":"set","p":"kill","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":1020,"wires":[["18a7750b.88455b"]]},{"id":"a195c6d3.fd4378","type":"inject","z":"fdaddf2e.250df","name":"Stop all streams","topic":"","payload":"SIGTERM","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":1020,"wires":[["a38dafa2.5778"]]},{"id":"652938f2.df8da8","type":"debug","z":"fdaddf2e.250df","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":830,"y":1000,"wires":[]}]

I get "http://127.0.0.1: 8081/password" with the code that I found on the web:

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 = true;

// Websocket Server
var socketServer = new WebSocket.Server({port: WEBSOCKET_PORT, perMessageDeflate: false});
socketServer.connectionCount = 0;
socketServer.on('connection', function(socket, upgradeReq) {
	socketServer.connectionCount++;
	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) {
	socketServer.clients.forEach(function each(client) {
		if (client.readyState === WebSocket.OPEN) {
			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);
		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 = "C:/Users/anxo-vilar/Desktop/rtspvideo/videostest.mp4"//'recordings/' + Date.now() + '.mp4';
		request.socket.recording = fs.createWriteStream(path);
	}
}).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+'/');

this also gives me the websocket that I will use in my template node
This is where I use jsmpeg.js

[{"id":"eb71cfa0.28cf3","type":"http in","z":"fdaddf2e.250df","name":"","url":"/video","method":"get","upload":false,"swaggerDoc":"","x":140,"y":820,"wires":[["8d9361ec.50783"]]},{"id":"ff0a5078.64a7b","type":"http response","z":"fdaddf2e.250df","name":"","statusCode":"","headers":{},"x":490,"y":820,"wires":[]},{"id":"8d9361ec.50783","type":"template","z":"fdaddf2e.250df","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n\t<title>JSMpeg Stream Client</title>\n\t<style type=\"text/css\">\n\t\thtml, body {\n\t\t\tbackground-color: #111;\n\t\t\ttext-align: center;\n\t\t}\n\t</style>\n\t\n</head>\n<body>\n\t<canvas id=\"video-canvas\"></canvas>\n\t<script type=\"text/javascript\" src=\"lib/jsmpeg/jsmpeg.min.js\"></script>\n\t<script type=\"text/javascript\">\n\t\tvar canvas = document.getElementById('video-canvas');\n\t\tvar url = 'ws://127.0.0.1:8082/';\n\t\tvar player = new JSMpeg.Player(url, {canvas: canvas});\n\t</script>\n</body>\n</html>\n","output":"str","x":340,"y":820,"wires":[["ff0a5078.64a7b"]]}]

in summary: for the stream I use fmpeg.exe for an http address. then I use websocket and jsmpeg for visualization

For the recorder i use fluent-ffmpeg with the following code

var ffmpeg = require('fluent-ffmpeg');

var record=ffmpeg('rtsp://admin:C0P0Admin@192.168.1.242:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif')
   // .setDuration("0:05")
  .on('end', function() { console.log('saved'); })
  .on('progress', (progress) => {
    console.log('Processing: ' + progress.targetSize + ' KB converted');
})
  .on('error', function(err) { console.log('error: ' +  err); })
  .save('video/output3.mp4');
  console.log (record)

/*const stop = (movie) => {
  return movie.ffmpegProc.stdin.write('q');
*/

/*
if(x==5){
  stop(record);}*/
  

U can see I was trying several things but I can't stop when I want to. I can only give it a predetermined duration

try to write a Q to stop the process but it doesn't work either

now im trying some like this more directly to the record, but i cant stop it with node-red :sweat_smile::
(be carefull, with this code, u may need restart node-red)

[{"id":"fc490d83.be496","type":"inject","z":"fdaddf2e.250df","name":"Start Rec","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":1500,"wires":[["db9ec27c.598b9"]]},{"id":"db9ec27c.598b9","type":"function","z":"fdaddf2e.250df","name":"","func":"\nvar exec=global.get('child_process').exec\ncontext.set(\"child\",child||null);\n\nvar child= context.get(\"child\")\nchild=exec('ffmpeg -i \"rtsp://xxxxxxxx\"  -acodec copy -vcodec copy \"C:/Users/anxo-vilar/Desktop/rtspvideo/myvideotest.mp4\" -y')\nnode.send({payload:'Timeout'});\nif (msg.kill) {    child.stdin.pause();\n    child.kill();}\nsetTimeout(function(){\n    node.send({payload:'kill'});\n    child.stdin.pause();\n    child.kill();\n}, 1200);\n\nchild.stdout.on('data', function(data){\n    node.send({payload:'stdout:'+data});\n});\n\nchild.stderr.on('data', function(data){\n    node.send({payload:'stderr:'+data});\n});\n\nchild.stdin.on('data', function(data){\n    node.send({payload:'stdin:'+data});\n});","outputs":1,"noerr":0,"x":570,"y":1500,"wires":[["4bff50d9.051aa"]]},{"id":"4bff50d9.051aa","type":"debug","z":"fdaddf2e.250df","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":770,"y":1480,"wires":[]},{"id":"910e1e23.fb5cb","type":"inject","z":"fdaddf2e.250df","name":"Stop rec","topic":"","payload":"SIGINT","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":1540,"wires":[["ad2aa4a2.427f88"]]},{"id":"ad2aa4a2.427f88","type":"change","z":"fdaddf2e.250df","name":"","rules":[{"t":"set","p":"kill","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":1540,"wires":[["db9ec27c.598b9"]]}]

Hi, I'm trying to follow your step but I cannot figure it out. Coulld you please summarize in a flow exemple the solution for showing an rtsp camera on dashboard?
Thank a lot

Hi. Hope you are well. I have a question. I tried to convert rtsp stream to mp4 using exec node. I put this as command ffmpeg -rtsp_transport tcp -i rtsp://user:password@192.168.1.23:554//h264Preview_01_main -r 10 -t 60 -vcodec copy -acodec copy -y /home/pi/video.mp4. But when open the video file, no video was shown. Can help me on this? Much appreciated. Thank you

Check all three outputs of the exec node to see if there are is any relevant information. Set the debug nodes to show Complete Message.

Does the command run if you run it in a terminal on the machine running node-red?

What shows that on the terminal? Do you mean when you run it in a terminal? If so then that does not tell us whether it works.

you asked me did the command run if run in a terminal. So i tried run it in terminal & the terminal gave that long output. I just answering your question

Debug node information

Command failed: ffmpeg -rtsp_transport tcp -i rtsp://@192.168.1.23:554//h264Preview_01_main -r 10 -t 5 -vcodec copy -acodec copy -y /home/pi/video.mp4 1616463631133ffmpeg version 4.1.6-1~deb10u1+rpt1 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 8 (Raspbian 8.3.0-6+rpi1) configuration: --prefix=/usr --extra-version='1~deb10u1+rpt1' --toolchain=hardened --incdir=/usr/include/arm-linux-gnueabihf --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-li...

Before you start with ffmpeg, try it out in VLC to find the working video stream. Have you tried to open the rtsp in VLC?

rtsp://user:password@192.168.1.23:554//h264Preview_01_main

You could have meant that you see that in the node red log in the terminal when the command is run from the exec node.
Also you have not told us whether it worked. In other words does it produce a good video file.

Is it not obvious that the output you posted tells us nothing other than that the command failed?

Which output of the exec node is that appearing on? Did you set the debug nodes to show Complete Message? What is appearing on the other outputs?
If you set the debug nodes to output to the console then the full output will appear in the node red log. Make sure you give the debug nodes names so you can identify this in the log.

no video at all being saved.

yes. it shows the live stream from the ip camera

Once again you have been vague in your answer. If you mean that when you run the command in a terminal that it does not produce a good file then the problem is nothing to do with node red. You need to fix the command first.

I may be wrong but I slightly remember I also failed when trying to create a mp4 file
Try to change the extension to .mkv

This type of command as example works for me (with a http stream)

ffmpeg -re -i http://192.168.0.237:8889/?action=stream /home/pi/video.mkv

But as @Colin writes, this is NOT a node-RED issue

i dont know how the right way to answer ur question. I already stated my full problem statement earlier. Then u asked another question along with suggestion. Then i tried ur suggestion and gave feedback. it is basically a continuous thread based on ur questions.

okay thank you. if it is not a node red issue, how can i fix those error? anything to do with configuration?

Unless someone gives you a better reply, you have to search the answers to your configuration in other places where ffmpeg is discussed. Google with some key words is a good start. The ffmpeg has it owns site where you can find and read the online documentation

That is because you have not answered questions clearly.
The solution is

  1. Run the ffmpeg command in a terminal and find the command which correctly outputs a good file.
  2. Call that command in node red. If it does not work then show us the full output from all the outputs of the exec node as I suggested earlier.

This might be an access rights problem you have. Try to start ffmpeg with sudo

"sudo ffmpeg ..."