Migrating ui template from Dashboard-1 to Dashboard-2

The ui template example above supports hls (.m3u8) and .mp4 so the url you have provided will not work in that example. An example that works is:

http://rbmn-live.akamaized.net/hls/live/590964/BoRB-AT/master_1660.m3u8

If you feed your camera url through the mp4frag node, that will then produce .m3u8 format and that should then be possible to feed into the template (then as .m3u8). To test you could use what you have since before and feed the template with what you currently feed the ui_mp4frag with in the Dahboard 1 setup. To make it work you need to add a change node as a "helper" node, setting the msg.url and a cam nbr in the msg.payload

Check out and test if this flow works

[{"id":"6c9aaef2f8f4cf39","type":"ffmpeg","z":"c66150ba6c5c5715","name":"","outputs":2,"cmdPath":"ffmpeg","cmdArgs":"[\"-version\"]","cmdOutputs":1,"killSignal":"SIGTERM","x":840,"y":240,"wires":[["512079fd81675014"],["512079fd81675014"]]},{"id":"512079fd81675014","type":"mp4frag","z":"c66150ba6c5c5715","name":"","outputs":2,"basePath":"id","serveHttp":"true","serveIo":"true","hlsPlaylistSize":4,"hlsPlaylistExtra":0,"bufferPool":0,"autoStart":"true","preBuffer":1,"timeLimit":10000,"repeated":"false","statusData":"playlist","x":1070,"y":240,"wires":[["8cdd756e8c64f81a","1a249f31b27e436b"],[]]},{"id":"eb4bb64c.4552b8","type":"inject","z":"c66150ba6c5c5715","name":"RedBull","props":[{"p":"action","v":"{\"command\":\"start\",\"args\":[\"-loglevel\",\"error\",\"-nostats\",\"-f\",\"hls\",\"-http_multiple\",\"1\",\"-timeout\",\"1\",\"-re\",\"-i\",\"http://rbmn-live.akamaized.net/hls/live/590964/BoRB-AT/master_1660.m3u8\",\"-c:v\",\"copy\",\"-c:a\",\"aac\",\"-f\",\"mp4\",\"-movflags\",\"+frag_keyframe+empty_moov+default_base_moof\",\"pipe:1\"]}","vt":"json"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"5","topic":"","payload":"cam10","payloadType":"str","x":700,"y":190,"wires":[["6c9aaef2f8f4cf39"]]},{"id":"e6391835.e71298","type":"inject","z":"c66150ba6c5c5715","name":"stop","props":[{"p":"action","v":"{\"command\":\"stop\"}","vt":"json"},{"p":"reset","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":700,"y":290,"wires":[["6c9aaef2f8f4cf39"]]},{"id":"8cdd756e8c64f81a","type":"change","z":"c66150ba6c5c5715","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"payload.hlsPlaylist","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"cam10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1300,"y":290,"wires":[["5552af0ad076c781"]]},{"id":"1a249f31b27e436b","type":"debug","z":"c66150ba6c5c5715","name":"debug 5","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1280,"y":170,"wires":[]},{"id":"5552af0ad076c781","type":"ui-template","z":"c66150ba6c5c5715","group":"b7971684f73a027c","page":"","ui":"","name":"mediaplayer","order":2,"width":0,"height":0,"head":"","format":"<template>\n    <div class=\"nrdb-widget--media-player\">\n        <div v-if=\"loaded && !loading\">\n            <div v-if=\"error_\" class=\"centered\">\n                {{ error_msg || 'Error loading media' }}\n            </div>\n\n            <div v-if=\"def_\" class=\"centered\">\n                <v-img :src=\"def_src\" class=\"main_monitor\" title=\"Default\"></v-img>\n            </div>\n\n            <div v-if=\"pic_\" class=\"centered\">\n                <v-img :src=\"pic_src\" class=\"main_monitor\" title=\"Mediafile\"></v-img>\n            </div>\n\n            <div v-if=\"str_\" class=\"centered\">\n                <v-img :src=\"str_src\" class=\"main_monitor\" title=\"Click for snapshot\" @click=\"send({payload:'snapshot?mainview_url', topic:'Snapshot'})\">\n                </v-img>\n            </div>\n\n            <div v-show=\"vid_\" class=\"centered\">\n                <video\n                    height=\"400\" width=\"100%\"\n                    ref=\"vid_\" autoplay controls :src=\"vid_src\" class=\"main_monitor\" title=\"Main display\"\n                    type=\"video/mp4\"\n                />\n            </div>\n\n            <div v-show=\"hls_\" class=\"centered\">\n                <video\n                    ref=\"hls_\" autoplay muted class=\"main_monitor\"\n                    height=\"400\" width=\"100%\"\n                    title=\"Playing m3u8, click for snapshot\" type=\"video/mp4\"\n                    @click=\"send({payload:'snapshot?mainview_url', topic:'Snapshot'})\"\n                />\n            </div>\n\n            <div v-show=\"saf_\" class=\"centered\">\n                <video\n                    ref=\"saf_\" autoplay muted :src=\"saf_src || ''\" class=\"main_monitor\"\n                    height=\"400\" width=\"100%\"\n                    title=\"Playing m3u8, click for snapshot\" type=\"video/mp4\"\n                    @click=\"send({payload:'snapshot?mainview_url', topic:'Snapshot'})\"\n                />\n            </div>\n\n            <div v-show=\"cap_\" class=\"centered\">\n                <iframe ref=\"cap_\" height=\"400\" width=\"100%\" src=\"\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen></iframe>\n            </div>\n        </div>\n        <div v-else>\n            <v-progress-circular indeterminate />\n        </div>\n    </div>\n</template>\n\n\n<script>\nexport default {\n    name: 'MediaPlayer',\n    data () {\n        return {\n            loaded: false,\n            loading: false,\n            unsupported: false,\n            hls_m: null,\n\n            // simple booleans that reactively show/hide components\n            def_: false,\n            pic_: false,\n            str_: false,\n            vid_: false,\n            hls_: false,\n            saf_: false,\n            cap_: true,\n\n            // the source for each type of media - these are bound to the :src attributes in the template\n            def_src: '',\n            vid_src: '',\n            hls_src: '',\n            saf_src: '',\n            cap_src: ''\n        }\n    },\n    computed: {\n        str_src () {\n            return this.str_ ? (this.msg?.url + '?' + this.msg?._msgid || '') : ''\n        },\n        pic_src () {\n            return this.pic_ ? (this.msg?.url + '?' + this.msg?._msgid || '') : ''\n        }\n    },\n    mounted () {\n        console.log('mounted')\n        // code here when the component is first loaded\n        const interval = setInterval(() => {\n            if (window.Hls) {\n                console.log('Hls has loaded')\n                clearInterval(interval)\n                this.loaded = true\n                this.init()\n            }\n        }, 100)\n    },\n    methods: {\n        init () {\n            console.log('init')\n            this.$socket.on('msg-input:' + this.id, (msg) => {\n                // do stuff with msg. runs only when new messages are received\n                this.onMsg(msg)\n            })\n            this.send({ payload: 'do_init' })\n            this.loaded = true\n        },\n        isSafari () {\n            if (/apple/i.test(navigator.vendor)) {\n                // alert(\"Safari\");\n                return true\n            } else {\n                return false\n            }\n        },\n        stopVideos (prev) {\n            // TODO: not sure what this is supposed to be doing\n        //     if(prev.indexOf('recordings')>-1 || prev.indexOf('youtube')>-1) {\n        //         $(\"iframe\").each(function() {\n        //             var src= $(this).attr('src');\n        //             if(prev.indexOf('youtube')>-1) {\n        //                 $(this).attr('src','');\n        //             }else{\n        //                 $(this).attr('src',src);\n        //             }\n        //         });\n        //     }\n        //     if(prev.indexOf('.mp4')>-1) {\n        //         $(\"[title~='Main']\").trigger('pause');\n        //     }\n        },\n        show (which, src) {\n            console.log('showing', which, src)\n            this.loading = false\n            this.def_src = which !== 'def_' ? '' : (src || '')\n            this.vid_src = which !== 'vid_' ? '' : (src || '')\n            this.hls_src = which !== 'hls_' ? '' : (src || '')\n            this.saf_src = which !== 'saf_' ? '' : (src || '')\n            this.cap_src = which !== 'cap_' ? '' : (src || '')\n            this.error_msg = which !== 'error_' ? '' : (src || '')\n            this.def_ = which === 'def_'\n            this.pic_ = which === 'pic_'\n            this.str_ = which === 'str_'\n            this.vid_ = which === 'vid_'\n            this.hls_ = which === 'hls_'\n            this.saf_ = which === 'saf_'\n            this.cap_ = which === 'cap_'\n            this.error_ = which === 'error_'\n        },\n        stopHls() {\n            this.$refs.hls_?.stop && this.$refs.hls_.stop()\n            if (this.hls_m) {\n                try {\n                    this.hls_m.destroy()\n                } catch (err) {}\n                this.hls_m = null\n            }\n        },\n        onMsg (msg) {\n//            this.send(msg)\n            console.log('msg', msg)\n            if (msg.topic === 'stop') {\n                this.stopHls()\n                this.show('')\n            }\n            if (msg.payload?.indexOf('goback') > -1) {\n                window.history.back()\n            }\n            if (msg.prev?.indexOf('recordings') > -1 || msg.prev?.indexOf('.mp4') > -1 || msg.prev?.indexOf('motions') > -1 || msg.prev?.indexOf('youtube') > -1) {\n                this.stopVideos(msg.prev)\n            }\n            if (msg.payload?.indexOf('snapshots') > -1 || msg.payload?.indexOf('recordings') > -1 || msg.payload?.indexOf('motions') > -1) {\n                const ip = location.host.split(':')[0]\n                this.stopHls()\n                this.show('cap_', 'http://' + ip + msg.url)\n            }\n            if (msg.payload?.indexOf('med') < 0 && msg.payload?.indexOf('default') > -1) {\n                this.stopHls()\n                const ip = location.host.split(':')[0]\n                this.show('def_', 'http://' + ip + msg.url)\n            }\n            if (msg.payload?.indexOf('med') > -1 && msg.payload?.indexOf('default') < 0) {\n                this.stopHls()\n\n                if (msg.url?.indexOf('.mp4') > -1) {\n                    this.show('vid_', msg.url)\n                } else {\n                    this.show('pic_')\n                }\n            }\n            if (msg.payload?.indexOf('cam') > -1 && msg.url?.indexOf('.m3u8') < 0 && msg.url?.indexOf('youtube') < 0) {\n                this.stopHls()\n                this.show('str_')\n            } else if (msg.url?.indexOf('.m3u8') > -1) {\n                    this.stopHls()\n                if (this.isSafari()) {\n                    this.show('saf_', msg.url)\n                } else {\n//                    this.send({ payload: 'show hls' })\n                    this.show('hls_')\n                    if (window.Hls?.isSupported()) {\n                        try {\n                            const video = this.$refs.hls_\n                            const hsl = new window.Hls()\n                            this.hls_m = hsl\n                            console.log('hls is supported')\n                            this.loading = true\n                            \n                            hsl.on(Hls.Events.MEDIA_ATTACHED, function () {\n                                console.log('video and hls.js are now bound together !');\n                            });\n                            hsl.on(Hls.Events.MANIFEST_PARSED, function (event, data) {\n                                console.log(\n                                    'manifest loaded, found ' + data.levels.length + ' quality level',\n                                );\n                            });\n                            hsl.loadSource(msg.url);\n                            hsl.attachMedia(video);\n                            this.loading = false\n                        } catch (err) {\n                            this.show('error_')\n                            node.send( { error: { message: err.message } } )\n                        }\n                    } else {\n                        this.show('error_', 'Hls Error: ' + err.message)\n                        node.send( { error: { message: 'Hls Not supported' } } )\n                    }\n                }\n            } else if (msg.url?.indexOf('youtube') > -1) {\n                this.stopHls()\n                this.$refs.cap_.src = msg.url\n                this.show('cap_')\n            } else if (msg.url?.endsWith('.mp4')) {\n                this.stopHls()\n                this.show('vid_', msg.url)\n            }\n        }\n    }\n}\n</script>\n\n<script type=\"text/javascript\" src=\"https://cdn.jsdelivr.net/npm/hls.js@latest\"></script>\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":1300,"y":350,"wires":[[]]},{"id":"b7971684f73a027c","type":"ui-group","name":"Group 5","page":"f85cf0eee9119058","width":"4","height":"1","order":2,"showTitle":false,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"f85cf0eee9119058","type":"ui-page","name":"Hemma","ui":"72c1e5a9ec204878","path":"/home","icon":"home","layout":"grid","theme":"0d92c765bfad87e6","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":2,"className":"","visible":"true","disabled":"false"},{"id":"72c1e5a9ec204878","type":"ui-base","name":"My Dashboard","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control","ui-chart"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"default","titleBarStyle":"default"},{"id":"0d92c765bfad87e6","type":"ui-theme","name":"Basic Blue Theme","colors":{"surface":"#4d58ff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px","density":"default"}}]
2 Likes