I made a little progress for triggering an mp4 recording. If you are brave enough, you can try the #recorder branch.
npm install kevinGodell/node-red-contrib-mp4frag#recorder
A 2nd output has been added to the node for feeding the video buffer to the file node.
The output can be triggered by passing an object to the input, such as
{
action: {
subject: 'write',
command: 'start',
keyframe: -1,
timeLimit: 5000,
sizeLimit: 2500000
}
Hopefully the settings and help text and example flow here will be good enough to explain how to use it.
flow:
[{"id":"9215bc1c.b408d","type":"inject","z":"28dd399e.972736","name":"Start stream","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"1","topic":"","payload":"true","payloadType":"bool","x":110,"y":100,"wires":[["f001af15.29445"]]},{"id":"f001af15.29445","type":"switch","z":"28dd399e.972736","name":"","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":261,"y":100,"wires":[["40073444.e625bc"],["a1330022.ca53c"]]},{"id":"40073444.e625bc","type":"exec","z":"28dd399e.972736","command":"ffmpeg -re -i http://f24hls-i.akamaihd.net/hls/live/221147/F24_EN_HI_HLS/master_2000.m3u8 -c:v copy -c:a aac -f mp4 -movflags +frag_keyframe+empty_moov+default_base_moof pipe:1","addpay":false,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"france 24 news","x":480,"y":100,"wires":[["1d68b87a.0fefc8"],[],["1d68b87a.0fefc8"]]},{"id":"a1330022.ca53c","type":"function","z":"28dd399e.972736","name":"stop","func":"msg = {\n kill:'SIGHUP',\n payload : 'SIGHUP' \n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":281,"y":149,"wires":[["40073444.e625bc"]]},{"id":"80cd04c4.71b318","type":"inject","z":"28dd399e.972736","name":"Stop stream","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":110,"y":146,"wires":[["f001af15.29445"]]},{"id":"1d68b87a.0fefc8","type":"mp4frag","z":"28dd399e.972736","name":"","migrate":1e-9,"hlsPlaylistSize":"20","hlsPlaylistExtra":"10","basePath":"fr24_2","processVideo":true,"commandPath":"ffmpeg","commandArgs":"[\"-loglevel\",\"quiet\",\"-f\",\"mp4\",\"-i\",\"pipe:0\",\"-f\",\"mp4\",\"-c\",\"copy\",\"-movflags\",\"+faststart+empty_moov\",\"-t\",\"60\",\"-fs\",\"8000000\",\"pipe:1\"]","x":720,"y":100,"wires":[[],["ea3f12ef.4b81f"]]},{"id":"ea3f12ef.4b81f","type":"file","z":"28dd399e.972736","name":"","filename":"","appendNewline":false,"createDir":true,"overwriteFile":"false","encoding":"none","x":770,"y":200,"wires":[[]]},{"id":"d602be42.d4dbc","type":"inject","z":"28dd399e.972736","name":"write start -1, 5000, 2500000","props":[{"p":"action","v":"{\"subject\":\"write\",\"command\":\"start\",\"keyframe\":-1,\"timeLimit\":5000,\"sizeLimit\":2500000}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":460,"y":200,"wires":[["1d68b87a.0fefc8"]]},{"id":"a1640b3b.120f68","type":"inject","z":"28dd399e.972736","name":"write start -5, 5000, 2500000","props":[{"p":"action","v":"{\"subject\":\"write\",\"command\":\"start\",\"keyframe\":-5,\"timeLimit\":5000,\"sizeLimit\":2500000}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":480,"y":240,"wires":[["1d68b87a.0fefc8"]]},{"id":"a965e1bc.5d78d","type":"inject","z":"28dd399e.972736","name":"write start with defaults","props":[{"p":"action","v":"{\"subject\":\"write\",\"command\":\"start\"}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":520,"y":280,"wires":[["1d68b87a.0fefc8"]]},{"id":"b7066f7e.57fd3","type":"inject","z":"28dd399e.972736","name":"write stop","props":[{"p":"action","v":"{\"subject\":\"write\",\"command\":\"stop\"}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":580,"y":320,"wires":[["1d68b87a.0fefc8"]]}]
One point to note, which may not be obvious, when sending a triggering object to start the video output, if sending a start command before the current output finishes, it will extend the currently running process by resetting the current timeLimit and sizeLimit.
For example, if you send this:
{
action: {
subject: 'write',
command: 'start',
keyframe: -1,
timeLimit: 5000,
sizeLimit: 2500000
}
It will cause the video output to run for 5 seconds or 2.5mb, whichever is reached first. If you send that same command after just 3 seconds have passed, then the values are reset per message. You may end up with a 8 second video.
Another scenario for this is that you have some triggering event, such as motion detection, sending many triggers for this to record a video. Each trigger extends the recording time (not cumulatively). If you need to ensure that the resulting file stays within a certain maximum duration or file size, you can pass the -t
or -fs
parameter to ffmpeg and it will exit gracefully at that time.
Don't hesitate to critique or complain before I merge this to the main branch. Nothing is final at this point. Seems like it works ok, but please try to break it.