<img width="300" height="200" ng-src="{{msg.payload}}"><div ng-bind-html="msg.payload"></div><img width="16" height="16" src="data:image/jpg;base64,{{msg.payload}}" />[{"id":"1c60ecf2.a26cf3","type":"base64","z":"47b91ceb.38a754","name":"Encode","x":1214,"y":205,"wires":[["8d1aa3c.19ce66"]]},{"id":"2216d2e0.8bbd0e","type":"http request","z":"47b91ceb.38a754","name":"","method":"GET","ret":"bin","url":"http://192.168.1.200/SnapshotJPEG?Resolution=320x240&Quality=High","tls":"","x":1031.6354484558105,"y":204.3958396911621,"wires":[["1c60ecf2.a26cf3"]]},{"id":"4dd2a66a.face28","type":"interval","z":"47b91ceb.38a754","name":"interval","interval":"1","onstart":false,"msg":"ping","showstatus":false,"unit":"seconds","statusformat":"YYYY-MM-D HH:mm:ss","x":876.5902976989746,"y":203.82205200195312,"wires":[["2216d2e0.8bbd0e"]]},{"id":"8d1aa3c.19ce66","type":"ui_template","z":"47b91ceb.38a754","group":"4f44306b.c5a07","name":"Display image","order":1,"width":"6","height":"6","format":"<img width=\"16\" height=\"16\" alt=\"mjpeg test...\" src=\"data:image/jpg;base64,{{msg.payload}}\" />\n","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":1391.256923675537,"y":205.4166660308838,"wires":[[]]},{"id":"4f44306b.c5a07","type":"ui_group","z":"47b91ceb.38a754","name":"Keuken","tab":"72e36c60.254134","order":1,"disp":true,"width":"6"},{"id":"72e36c60.254134","type":"ui_tab","z":"47b91ceb.38a754","name":"Cameras","icon":"camera_alt","order":2}]
That is a very simple approach, which is sufficient in a lot of use cases.
But it is not usable when you require good performance:
Keep in mind that the images keep being pushed to the dashboard, even if the 'cameras' tab is not active! This is very inconvenient when you open your dashboard e.g. on a smartphone, because you might be paying for lots of useles data that is being transmitted. I have already raised an issue for this in the past, but you need to solve this yourself in your flow.
Following steps are executed for each IP camera:
<img width="16" height="16" src="data:image/jpg;base64,{{msg.payload}}" />
Now indeed the browser doesn't seem to freeze: all camera's run at full speed.
So my theory was that the browser seems to have a separate thread for each source (src) ...
However now your dashboard gets the images directly from the camera's: nothing passes via the Node-Red flow.
You can have two options: