Problem with node-red-contrib-mp4frag

I used @kevinGodell node-red-contrib-mp4frag at some point in the past, and I'm now trying to get some camera rtsp streams onto the OG dashboard.

I can get a camera to display, but when I send a stop or restart command to node-red-ffmpeg this downstream mp4frag seems to be still running, which prevents me showing a different camera.

At the moment the only way to clear the problem is to restart NR.

after a restart it looks like this

And I get 1 shot at displaying a stream again.

I was also a bit confused as to which node to use as there is node-red-ffmpeg
and node-red-contrib-ffmpeg-spawn

I tried this flow Node-red-contrib-ffmpeg-spawn, but I'm missing node-red-contrib-ffmpeg-spawn, even though I installed it - npm install kevinGodell/node-red-contrib-ffmpeg-spawn

So if anyone is using these nodes on NR 4.0.9, perhaps you could give me a clue :wink:

Hi there,

It works for me. I have exported the "raw" part from my setup running NR 4.0.5. I don't use the spawn node any longer, I think it is replaced by the ffmpeg node

If you try this flow, edit the rtsp url and maybe some other settings for the ui (it is not pretty, just a setup for testing)

[{"id":"3b31739802050b95","type":"inject","z":"e1e6c493f01ebcd3","name":"stop default","props":[{"p":"action","v":"{\"command\":\"stop\"}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":180,"y":150,"wires":[["41fc52ec86ba5b94"]]},{"id":"a48db3be27e8dda0","type":"inject","z":"e1e6c493f01ebcd3","name":"start default","props":[{"p":"action","v":"{\"command\":\"start\"}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":"1","topic":"","x":180,"y":110,"wires":[["41fc52ec86ba5b94"]]},{"id":"c9d93b5e85c2c3a3","type":"comment","z":"e1e6c493f01ebcd3","name":"Video sources","info":"","x":180,"y":70,"wires":[]},{"id":"812ca8f197dd08d6","type":"ui_template","z":"e1e6c493f01ebcd3","group":"16030ced.45add3","name":"Main Display","order":3,"width":14,"height":8,"format":"<script src=\"//cdn.jsdelivr.net/npm/hls.js@latest\"></script>\n\n<script type=\"text/javascript\">\nhls_m = undefined;\n\n(function(scope) {\n    scope.$watch('msg', function(msg) {\n        if(hls_m!=undefined){hls_m.destroy();}\n        if (msg.url.match('reset')) {\n            $(\"#hls_\"+scope.$id).hide();\n            $(\"#saf_\"+scope.$id).hide();\n            hls_m.destroy();\n        }\n        if (msg.url.match('.m3u8')) {\n            if(isSafari()){\n                $(\"#saf_\"+scope.$id).show();\n                $(\"#hls_\"+scope.$id).hide();\n            }\n            if(!isSafari()){\n                $(\"#hls_\"+scope.$id).show();\n                $(\"#saf_\"+scope.$id).hide();\n                hls_m = new Hls();\n                if (Hls.isSupported()) {\n                    let z = $(\"#hls_\"+scope.$id)[0];\n                    // bind them together\n                    hls_m.attachMedia(z);\n                    hls_m.on(Hls.Events.MEDIA_ATTACHED, function () {\n                      hls_m.loadSource(msg.url);\n                      hls_m.on(Hls.Events.MANIFEST_PARSED, function () {\n                        z.play();  \n                      });\n                    });\n                }\n            }\n        }\n    });\n})(scope);\n\nfunction isSafari() {\n    if (/apple/i.test(navigator.vendor)) {\n        //alert(\"Safari\");\n        return true;\n    }else{\n        return false;\n    } \n}\n\nthis.scope.action = function(event) { return event; }\n\nthis.scope.send({payload:'do_init'});\n\n</script>\n\n<div>\n<center>\n    <table>\n        <tr>\n    \t\t<td style=\"text-align: center\">\n    \t\t<video autoplay muted id=\"{{'hls_'+$id}}\" width='320px' height='240px' type=\"video/mp4\"></video>\n    \t\t</td>\n        </tr>\n    </table>\n</center>\n</div>\n\n<div id=\"{{'saf_'+$id}}\">\n<center>\n    <table>\n        <tr>\n    \t\t<td style=\"text-align: center\">\n    \t\t<video autoplay muted src={{msg.url}} width='320px' height='240px' type=\"video/mp4\"></video>\n    \t\t</td>\n        </tr>\n    </table>\n</center>\n</div>\n\n","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"local","className":"","x":1020,"y":250,"wires":[["b37b7867a71dd2bc","0e3d7db8e3971db7"]]},{"id":"41fc52ec86ba5b94","type":"ffmpeg","z":"e1e6c493f01ebcd3","name":"","outputs":2,"cmdPath":"ffmpeg","cmdArgs":"[\"-loglevel\",\"error\",\"-i\",\"rtsp://xxxxxxx@192.168.0.46:554/stream1\",\"-c:v\",\"copy\",\"-c:a\",\"aac\",\"-f\",\"mp4\",\"-movflags\",\"+frag_keyframe+empty_moov+default_base_moof\",\"pipe:1\"]","cmdOutputs":1,"killSignal":"SIGTERM","x":420,"y":130,"wires":[["c141dfc0bc3486c9"],["c141dfc0bc3486c9"]]},{"id":"3a56257fb28b672c","type":"ui_button","z":"e1e6c493f01ebcd3","name":"Play","group":"16030ced.45add3","order":1,"width":"7","height":"1","passthru":false,"label":"Play","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"play","payloadType":"str","topic":"topic","topicType":"msg","x":160,"y":220,"wires":[["9f6de0392ba567c5"]]},{"id":"96e7d9228d51aa86","type":"change","z":"e1e6c493f01ebcd3","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"payload.hlsPlaylist","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":820,"y":230,"wires":[["812ca8f197dd08d6"]]},{"id":"9be37ea1cc687a19","type":"switch","z":"e1e6c493f01ebcd3","name":"","property":"status","propertyType":"msg","rules":[{"t":"eq","v":"playlist","vt":"str"},{"t":"eq","v":"reset","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":640,"y":250,"wires":[["96e7d9228d51aa86"],["67eb0b5ca617b5e8"]]},{"id":"67eb0b5ca617b5e8","type":"change","z":"e1e6c493f01ebcd3","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"reset","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":820,"y":280,"wires":[["812ca8f197dd08d6"]]},{"id":"09ce7453c4a287c8","type":"ui_button","z":"e1e6c493f01ebcd3","name":"Stop","group":"16030ced.45add3","order":2,"width":"7","height":"1","passthru":false,"label":"Stop","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"stop","payloadType":"str","topic":"topic","topicType":"msg","x":160,"y":280,"wires":[["f0878c8173e11fd1"]]},{"id":"9f6de0392ba567c5","type":"change","z":"e1e6c493f01ebcd3","name":"","rules":[{"t":"set","p":"action","pt":"msg","to":"{\"command\":\"start\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":220,"wires":[["41fc52ec86ba5b94"]]},{"id":"f0878c8173e11fd1","type":"change","z":"e1e6c493f01ebcd3","name":"","rules":[{"t":"set","p":"action","pt":"msg","to":"{\"command\":\"stop\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":280,"wires":[["41fc52ec86ba5b94"]]},{"id":"b37b7867a71dd2bc","type":"debug","z":"e1e6c493f01ebcd3","name":"debug 382","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1210,"y":250,"wires":[]},{"id":"0e3d7db8e3971db7","type":"delay","z":"e1e6c493f01ebcd3","name":"","pauseType":"delay","timeout":"50","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1020,"y":330,"wires":[["82584e32a6e74948"]]},{"id":"82584e32a6e74948","type":"switch","z":"e1e6c493f01ebcd3","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"do_init","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":1020,"y":410,"wires":[["67eb0b5ca617b5e8"]]},{"id":"c141dfc0bc3486c9","type":"mp4frag","z":"e1e6c493f01ebcd3","name":"","outputs":2,"basePath":"c141dfc0bc3486c9","serveHttp":"true","serveIo":"true","hlsPlaylistSize":"10","hlsPlaylistExtra":"5","bufferPool":0,"autoStart":"false","preBuffer":1,"timeLimit":10000,"repeated":"false","statusData":"playlist","x":690,"y":130,"wires":[["9be37ea1cc687a19","fe75a6654966dd4e"],[]]},{"id":"fe75a6654966dd4e","type":"ui_mp4frag","z":"e1e6c493f01ebcd3","name":"","group":"16030ced.45add3","order":1,"width":6,"height":4,"readyPoster":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIiB0ZXh0LXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIiB2aWV3Qm94PSIwIDAgODAwMCA2MDAwIj48dGV4dCBmaWxsPSIjMGYwIiBzdHJva2Utd2lkdGg9IjAiIGR4PSIwIiBkeT0iMCIgZm9udC1mYW1pbHk9IiZxdW90O2UyY3B1d3p4YldsMTo6OlJvYm90byZxdW90OyIgZm9udC1zaXplPSI2MDAiIGZvbnQtd2VpZ2h0PSI3MDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKCAxMDExLjI0IDMyMDQuODgpIj48dHNwYW4geT0iMCIgc3Ryb2tlLXdpZHRoPSIwIiBmb250LXdlaWdodD0iNzAwIj48IVtDREFUQVsKVmlkZW8gUGxheWJhY2sgUmVhZHkKXV0+PC90c3Bhbj48L3RleHQ+PC9zdmc+Cg==","errorPoster":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIiB0ZXh0LXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIiB2aWV3Qm94PSIwIDAgODAwMCA2MDAwIj48dGV4dCBmaWxsPSJyZWQiIHN0cm9rZS13aWR0aD0iMCIgZHg9IjAiIGR5PSIwIiBmb250LWZhbWlseT0iJnF1b3Q7ZW42OXdhSUtnN0MxOjo6Um9ib3RvJnF1b3Q7IiBmb250LXNpemU9IjYwMCIgZm9udC13ZWlnaHQ9IjcwMCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoIDExODMuOTYgMzIwNC44OCkiPjx0c3BhbiB5PSIwIiBzdHJva2Utd2lkdGg9IjAiIGZvbnQtd2VpZ2h0PSI3MDAiPjwhW0NEQVRBWwpWaWRlbyBQbGF5YmFjayBFcnJvcgpdXT48L3RzcGFuPjwvdGV4dD48L3N2Zz4K","hlsJsConfig":"{\"liveDurationInfinity\":true,\"liveBackBufferLength\":5,\"maxBufferLength\":10,\"manifestLoadingTimeOut\":1000,\"manifestLoadingMaxRetry\":10,\"manifestLoadingRetryDelay\":500}","autoplay":"true","unload":"true","threshold":0.1,"controls":"true","muted":"true","players":["socket.io","hls.js","hls","mp4"],"x":1020,"y":80,"wires":[[]]},{"id":"16030ced.45add3","type":"ui_group","name":"Test","tab":"aed64a14.9adfe8","order":1,"disp":true,"width":"16","collapse":false,"className":""},{"id":"aed64a14.9adfe8","type":"ui_tab","name":"Test","icon":"dashboard","order":8,"disabled":false,"hidden":false}]

Thanks Walter,

I just changed the rtsp stream info with mine and your flow works fine.

I will need to digg around in the config and see if I can figure out what is wrong at my end.

1 Like

For the benefit of anyone else confused by the node names :thinking:

My best guess is that the repository for node-red-contrib-ffmpeg-spawn has had its name changed to node-red-ffmpeg.

I think github redirects installation of the old name to the new one, so it is technically the "same" node.

The older example flows in the forum refence the old node name, Installing the old node name, works, but actually installs from the new repository name.

The flows still don't work though as the node name changed in this commit

Phew :exploding_head:

Also just to confirm,

I had forgotten to connect the status output from the ffmpeg node to the mp4frag node.

3 Likes