Table of Contents

About

Along with PVR software such as the arr family consisting in Sonarr, Lidarr, Readarr, Radarr or Whisparr, an additional component is usually added that is able to transcode downloaded videos using a desired codec or quality to match the requirements of things such as storage space, hardware capabilities, and so on.

The alternatives are either Tdarr or FileFlows and, unfortunately, these applications are not really within the arr family, given that they use different display technologies and run on different principles. While Tdarr sometimes seems counter-intuitive and not too stable, FileFlows seems more stable but unfortunately is really a subset of what Node-Red can accomplish.

The problem of both software packages is that they rely on hardcoded preset blocks and with some options, but the presets do not really cover nor reflect the whole capability range of the transcoding software.

Screenshots

Node-Red

Node-Red is a quick-to-deploy, low-requirements dataflow programming environment based on JavaScript and node.js. Node-Red can be installed using npm directly:

npm -g install node-red

and then restarted using a SystemD service file:

[Unit]
Description=Node Red
After=network.target

[Service]
ExecStart=/usr/bin/node-red
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=node-red
User=root
Group=root
Environment=PATH=/usr/bin/:/usr/local/bin/
WorkingDirectory=/opt/node-red

[Install]
WantedBy=multi-user.target

Upon loading the interface, node-red has a preset amount of nodes that can carry out various operations but the system is extensible by installing additional nodes from the node-red addon repository. However, for this walkthrough, no additional node-red nodes will be installed and the whole system will run using the nodes that are distributed with Node-Red by default.

In order to add some persistence, Node-Red can and will be configured to store variables persistently across runs. This can be done by editing the settings.json file in the Node-Red configuration directory that is placed at the root of the user that is running Node-Red. If Node-Red is running as root, the path to the file will be /root/.node-red/settings.json.

The context storage must be changed from memory to the local filesystem:

    contextStorage: {
        default: {
            module:"localfilesystem"
        },
    },

and then Node-Red must be restarted.

Transcoding

In order to transcode videos on demand, as well as pick up files added within a directory and transcode them, the following pipeline shall be established:

with the following remarks:

Programming Notes

The flow essentially relies on two queues that are filled dynamically as files are being detected or scanned:

whilst the scan path is monitored at the same time for new files that get added to the probe queue.

node.js is used just a little and mostly for the implementation of the queues, with some modules being necessary for the flow imported within the function nodes:

The programming of the individual nodes is tricky because everything has to be implemented in an asynchronous, and preferably, event-driven way with even await and promises not being suitable given their side-effect of blocking the main execution thread.

Some parameters are hard-coded, such as the path to the ffmpeg, respectively ffprobe binaries but they can be made configurable in any case. Instead, templates are used to generate the ffmpeg resulting command elegantly, by interpolating settings variables and then reducing the template to one long string of parameters that is passed to ffmpeg.

Similarly, ffmpeg is used to extract the duration of the video clip and then the transcoding output of ffmpeg is monitored in order to display the transcoding progress on the Node-Red user interface.

Node-Red Flow

The following is the Node-Red flow that accomplishes all this:

[
    {
        "id": "9f98f36f3385bcd8",
        "type": "tab",
        "label": "Transcoding",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "8c088cb2f7181ba2",
        "type": "group",
        "z": "9f98f36f3385bcd8",
        "name": "ffprobe",
        "style": {
            "label": true,
            "fill": "#bfdbef",
            "fill-opacity": "0.5"
        },
        "nodes": [
            "3e33e76d0e3c0e4d",
            "e42a58c30039d179",
            "c322cf0d03d623b1",
            "81fb8456c8a24bef",
            "01680d728b478aa5",
            "f0d454696f6e547f",
            "d666d15dbafe8395",
            "a4ebe3b65ec64062",
            "60bbd40c3f9d8c0e",
            "1b541b828612bc99",
            "3701809d5b290f02",
            "2098ad1b433ffa26",
            "bb0d09b469240dbb",
            "2d56998ff17d9e44",
            "49b44f05bfa9c6ac",
            "ceccd99cf2a40534",
            "191bead4c0d01b13",
            "914f0e31f40c7895",
            "ad7b379fe92408f3",
            "17b475a2e7ea9516",
            "5d78f655434a6555",
            "98be7c1856cb4c3f",
            "92f3af459ce90aa3",
            "c7abb9a6ba15539c",
            "8781d05a891a5bb1",
            "4b49fa8ec7c43636",
            "d40dc9475eb9ecba"
        ],
        "x": 64,
        "y": 539,
        "w": 1322,
        "h": 542
    },
    {
        "id": "77f59c55d0a9323f",
        "type": "group",
        "z": "9f98f36f3385bcd8",
        "name": "Constants",
        "style": {
            "fill": "#ffffbf",
            "label": true,
            "fill-opacity": "0.5"
        },
        "nodes": [
            "18c7efc706669366",
            "9786c5da6a945358"
        ],
        "x": 924,
        "y": 1719,
        "w": 392,
        "h": 82
    },
    {
        "id": "1a8449d0623e98a6",
        "type": "group",
        "z": "9f98f36f3385bcd8",
        "name": "ffmpeg",
        "style": {
            "label": true,
            "fill": "#bfdbef",
            "fill-opacity": "0.5"
        },
        "nodes": [
            "6314709e0f7c7b6b",
            "b4fd821e4032327a",
            "9c49830979494dbd",
            "07de187c55753134",
            "16c09cad03a240e1",
            "e939e3dc9ef4bb10",
            "b1a1e1fa961decd1",
            "8c2a3f510bba3f91",
            "82d819f90fa8e376",
            "d09426f17ccbd352",
            "a2ce74176e7bb93a",
            "66627cca970092b8",
            "a68ae4599eace14b",
            "8c9ef2a07a0e271b",
            "7a7af815b51f0fd1",
            "a78f6c483e1e2597",
            "1e743f463192bfd3",
            "a49ead80df7d8134",
            "f06ae7fe45bc8ee6",
            "0b74e59054355a3a",
            "db1094061707ac30",
            "5e5ac174da4067e4",
            "1102635d4c82203c",
            "f1897b1f7b56d49d",
            "54b14ea280430dea",
            "41accef666076be8",
            "1bde2da775a09b2b",
            "e45a9ec830c51602",
            "2023c957f816a653"
        ],
        "x": 64,
        "y": 39,
        "w": 1442,
        "h": 462
    },
    {
        "id": "118640a37c2f6bac",
        "type": "group",
        "z": "9f98f36f3385bcd8",
        "name": "User Interface",
        "style": {
            "label": true,
            "fill": "#dbcbe7",
            "fill-opacity": "0.5"
        },
        "nodes": [
            "312a5bcb53309fbd",
            "20c8e2ccfc16300d",
            "8c9fc57260072eb7",
            "a55079a596102a8d",
            "bb0455146846fb45",
            "b0e1d9038e08aad0",
            "e45801f0b7cc3cd4",
            "790c3950a63fa109",
            "68c70fe740f38a81",
            "54efb1e3b0611844",
            "ce11dc4527d4245e",
            "d497ac7322a54f69",
            "188c2940f78ada06",
            "c8c10f76c08795ac",
            "b6c06f50e19f051d",
            "3ea505b539e0b9ad",
            "8073655aeb3b7029",
            "6169a14dcff6f101",
            "dc1ccff0ec482caa",
            "dacd4902bd230787",
            "0e3a3381bc3841f3"
        ],
        "x": 54,
        "y": 1179,
        "w": 1432,
        "h": 462
    },
    {
        "id": "13e7445ef83fcae8",
        "type": "group",
        "z": "9f98f36f3385bcd8",
        "name": "Settings",
        "style": {
            "fill": "#e3f3d3",
            "fill-opacity": "0.5",
            "label": true
        },
        "nodes": [
            "81d7c71da8797959",
            "1e43c0ffb0d80603",
            "0556bead30d14d7a",
            "126582f943f52389",
            "f6172a25a7ac7bca",
            "879ac930e91a750f",
            "891e2e4363a18786",
            "b0bb9aa491c3bd80",
            "bfef60164daf91e3",
            "b23bafe27c4c5b95",
            "5de93c3d896716d6",
            "ae3859e24088c5f2",
            "188dc2f88112d7df",
            "b3b9dcb7075207b1",
            "1de5c48e2d62e5b0",
            "b6686ce43478776f",
            "c3f80d80e84d13ba",
            "436aa2571f967479",
            "8f42b24f5ba8481e",
            "95f8b028b62316d7",
            "8b09525b6f843634",
            "bf2116ae3cbe5b57",
            "90305768b3fc9d1c",
            "06a7100f39e362cc",
            "2a4044a67d1a5f60"
        ],
        "x": 64,
        "y": 1719,
        "w": 812,
        "h": 722
    },
    {
        "id": "6314709e0f7c7b6b",
        "type": "exec",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "command": "",
        "addpay": "payload",
        "append": "",
        "useSpawn": "true",
        "timer": "",
        "winHide": true,
        "oldrc": false,
        "name": "ffmpeg",
        "x": 810,
        "y": 280,
        "wires": [
            [],
            [
                "07de187c55753134",
                "16c09cad03a240e1"
            ],
            [
                "b1a1e1fa961decd1"
            ]
        ]
    },
    {
        "id": "b4fd821e4032327a",
        "type": "template",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "ffmpeg Template",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "{{{flow.ffmpegBinary}}}\n-i \"{{{payload.original}}}\"\n-y\n-map_metadata -1\n-c:v {{{flow._videoCodec}}} \n-filter:v scale={{{flow._videoWidth}}}:-1:flags=lanczos\n-crf 23 \n-c:a {{{flow._audioCodec}}}\n-ac:a 2 \n-b:a 64k \n-preset ultrafast \n-strict experimental \n-tune zerolatency \n-movflags +faststart\n\"{{{payload.temporary}}}\"\n",
        "output": "str",
        "x": 470,
        "y": 280,
        "wires": [
            [
                "9c49830979494dbd"
            ]
        ]
    },
    {
        "id": "9c49830979494dbd",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "function 1",
        "func": "// normalize newlines\nvar regex = context.get('regex')\nmsg.payload = msg.payload.replace(regex, ' ')\n\n// return message\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "var reg = new RegExp(os.EOL, 'g')\ncontext.set('regex', reg)",
        "finalize": "",
        "libs": [
            {
                "var": "os",
                "module": "os"
            }
        ],
        "x": 660,
        "y": 280,
        "wires": [
            [
                "6314709e0f7c7b6b"
            ]
        ]
    },
    {
        "id": "07de187c55753134",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Extract Duration",
        "func": "var regex = context.get('regex')\nvar results = msg.payload.matchAll(regex)\nfor (let result of results) {\n    let { duration } = result.groups\n    var total = moment.duration(duration)\n    flow.set('clipDuration', total)\n    return\n}\n",
        "outputs": 0,
        "noerr": 0,
        "initialize": "var reg = new RegExp(/Duration: (?<duration>[^,]+),/, 'g')\ncontext.set('regex', reg)",
        "finalize": "",
        "libs": [
            {
                "var": "os",
                "module": "os"
            },
            {
                "var": "moment",
                "module": "moment"
            }
        ],
        "x": 1040,
        "y": 80,
        "wires": []
    },
    {
        "id": "16c09cad03a240e1",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Track Progress",
        "func": "var regex = context.get('regex')\nvar results = msg.payload.matchAll(regex)\nfor (let result of results) {\n    let { time } = result.groups\n    var clipTime = moment.duration(time).asMilliseconds()\n    var clipDuration = flow.get('clipDuration').asMilliseconds()\n    msg.payload = Math.round(clipTime / clipDuration * 100)\n    return msg\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "var reg = new RegExp(/time=(?<time>[^ ]+)/, 'g')\ncontext.set('regex', reg)",
        "finalize": "",
        "libs": [
            {
                "var": "moment",
                "module": "moment"
            }
        ],
        "x": 1040,
        "y": 180,
        "wires": [
            [
                "e939e3dc9ef4bb10",
                "8c2a3f510bba3f91",
                "82d819f90fa8e376",
                "1bde2da775a09b2b"
            ]
        ]
    },
    {
        "id": "e939e3dc9ef4bb10",
        "type": "ui_gauge",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "",
        "group": "7c5d8648955e9a1f",
        "order": 0,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "Current File Transcoding Progress",
        "label": "%",
        "format": "{{value}}",
        "min": 0,
        "max": "100",
        "colors": [
            "#ff0000",
            "#e6e600",
            "#80ff00"
        ],
        "seg1": "",
        "seg2": "",
        "diff": false,
        "className": "",
        "x": 1340,
        "y": 180,
        "wires": []
    },
    {
        "id": "b1a1e1fa961decd1",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Success",
        "property": "payload.code",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "0",
                "vt": "num"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 960,
        "y": 300,
        "wires": [
            [
                "1e743f463192bfd3"
            ],
            [
                "a49ead80df7d8134",
                "1102635d4c82203c"
            ]
        ]
    },
    {
        "id": "8c2a3f510bba3f91",
        "type": "ui_text",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "group": "7c5d8648955e9a1f",
        "order": 2,
        "width": "0",
        "height": "0",
        "name": "",
        "label": "Current File",
        "format": "{{msg.transcode.original}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1270,
        "y": 140,
        "wires": []
    },
    {
        "id": "82d819f90fa8e376",
        "type": "ui_text",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "group": "7c5d8648955e9a1f",
        "order": 3,
        "width": "0",
        "height": "0",
        "name": "",
        "label": "Temportary File",
        "format": "{{msg.transcode.temporary}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1280,
        "y": 220,
        "wires": []
    },
    {
        "id": "312a5bcb53309fbd",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Get Folder Contents",
        "func": "var folder = flow.get('_controlFolder')\nif (!folder || !fs.statSync(folder).isDirectory()) {\n    return [null, { \"payload\": folder }]\n}\n\nvar fileExtensionsWhitelist = flow.get('_fileExtensionWhitelist')\n\n/*var walker = walk.walk(folder, {})\n\nwalker.on('file', function (root, fileStats, next) {\n    var run = flow.get('_run')\n    var file = fileStats.name\n    if (!fileExtensionsWhitelist.includes(file.split('.').pop())) {\n        if (run) next()\n        return\n    }\n    node.send([{ \"payload\": file }, null])\n    if (run) next()\n})\n*/\n\nconst walkFunc = async (err, pathname, dirent) => {\n    if(!flow.get('_run')) return\n    if (err) throw err\n    if (dirent.isDirectory()) return\n    var file = path.join(path.dirname(pathname), dirent.name)\n    if (!fileExtensionsWhitelist.includes(file.split('.').pop())) {\n        return\n    }\n    node.send([{ \"payload\": file }, null])\n}\n\nawait walk.walk(folder, walkFunc)\nnode.send([null, {'payload': null}])",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [
            {
                "var": "path",
                "module": "path"
            },
            {
                "var": "fs",
                "module": "fs"
            },
            {
                "var": "walk",
                "module": "@root/walk"
            }
        ],
        "x": 740,
        "y": 1220,
        "wires": [
            [
                "b0e1d9038e08aad0"
            ],
            [
                "0e3a3381bc3841f3"
            ]
        ]
    },
    {
        "id": "20c8e2ccfc16300d",
        "type": "ui_text_input",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "",
        "label": "Folder",
        "tooltip": "",
        "group": "57b96149bd97f3cb",
        "order": 3,
        "width": 0,
        "height": 0,
        "passthru": true,
        "mode": "text",
        "delay": "150",
        "topic": "topic",
        "sendOnBlur": true,
        "className": "",
        "topicType": "msg",
        "x": 390,
        "y": 1280,
        "wires": [
            [
                "68c70fe740f38a81",
                "e45801f0b7cc3cd4",
                "188c2940f78ada06"
            ]
        ]
    },
    {
        "id": "8c9fc57260072eb7",
        "type": "ui_button",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "",
        "group": "57b96149bd97f3cb",
        "order": 1,
        "width": 0,
        "height": 0,
        "passthru": false,
        "label": "Start",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "x": 390,
        "y": 1220,
        "wires": [
            [
                "e45801f0b7cc3cd4",
                "dacd4902bd230787"
            ]
        ]
    },
    {
        "id": "a55079a596102a8d",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Recall Control Folder",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "_controlFolder",
        "payloadType": "flow",
        "x": 200,
        "y": 1280,
        "wires": [
            [
                "20c8e2ccfc16300d",
                "188c2940f78ada06"
            ]
        ]
    },
    {
        "id": "d09426f17ccbd352",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "kill",
        "props": [
            {
                "p": "kill",
                "v": "",
                "vt": "date"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 770,
        "y": 140,
        "wires": [
            [
                "6314709e0f7c7b6b"
            ]
        ]
    },
    {
        "id": "bb0455146846fb45",
        "type": "ui_button",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "",
        "group": "57b96149bd97f3cb",
        "order": 2,
        "width": 0,
        "height": 0,
        "passthru": false,
        "label": "Stop",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "x": 390,
        "y": 1400,
        "wires": [
            [
                "e45801f0b7cc3cd4",
                "dc1ccff0ec482caa"
            ]
        ]
    },
    {
        "id": "b0e1d9038e08aad0",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Add to Probe Queue",
        "func": "var queue = flow.get('_probeQueue')\nif(!Array.isArray(queue)) {\n    queue = []\n}\nqueue.push(msg.payload)\nflow.set('_probeQueue', queue)\n\nreturn msg\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [
            {
                "var": "path",
                "module": "path"
            }
        ],
        "x": 980,
        "y": 1220,
        "wires": [
            [
                "6169a14dcff6f101"
            ]
        ]
    },
    {
        "id": "18c7efc706669366",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "77f59c55d0a9323f",
        "name": "CONSTANTS",
        "rules": [
            {
                "t": "set",
                "p": "workFolder",
                "pt": "flow",
                "to": "/tmp/",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "ffmpegBinary",
                "pt": "flow",
                "to": "/usr/lib/jellyfin-ffmpeg/ffmpeg",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "ffprobeBinary",
                "pt": "flow",
                "to": "/usr/lib/jellyfin-ffmpeg/ffprobe",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1220,
        "y": 1760,
        "wires": [
            []
        ]
    },
    {
        "id": "9786c5da6a945358",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "77f59c55d0a9323f",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 1040,
        "y": 1760,
        "wires": [
            [
                "18c7efc706669366"
            ]
        ]
    },
    {
        "id": "e45801f0b7cc3cd4",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "link out 1",
        "mode": "link",
        "links": [
            "66627cca970092b8",
            "d666d15dbafe8395",
            "9616785c60c44f70"
        ],
        "x": 495,
        "y": 1400,
        "wires": []
    },
    {
        "id": "3e33e76d0e3c0e4d",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "link out 2",
        "mode": "link",
        "links": [
            "a2ce74176e7bb93a"
        ],
        "x": 675,
        "y": 640,
        "wires": []
    },
    {
        "id": "a2ce74176e7bb93a",
        "type": "link in",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "link in 1",
        "links": [
            "3e33e76d0e3c0e4d",
            "1102635d4c82203c",
            "a68ae4599eace14b"
        ],
        "x": 105,
        "y": 280,
        "wires": [
            [
                "f1897b1f7b56d49d"
            ]
        ]
    },
    {
        "id": "66627cca970092b8",
        "type": "link in",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "link in 2",
        "links": [
            "e45801f0b7cc3cd4"
        ],
        "x": 665,
        "y": 200,
        "wires": [
            [
                "7a7af815b51f0fd1",
                "db1094061707ac30"
            ]
        ]
    },
    {
        "id": "d0f52fbe0d6d91e8",
        "type": "exec",
        "z": "9f98f36f3385bcd8",
        "command": "",
        "addpay": "payload",
        "append": "",
        "useSpawn": "false",
        "timer": "",
        "winHide": false,
        "oldrc": false,
        "name": "",
        "x": 2210,
        "y": 640,
        "wires": [
            [],
            [
                "17815b61e1ec70fb"
            ],
            [
                "fa6c9e46602390b8"
            ]
        ]
    },
    {
        "id": "4ae152e4f9923e5f",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "name": "Delete Original File",
        "func": "msg.payload = `rm \"${msg.transcode.path}\"`\nreturn msg\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 2030,
        "y": 640,
        "wires": [
            [
                "d0f52fbe0d6d91e8"
            ]
        ]
    },
    {
        "id": "fa6c9e46602390b8",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "name": "Success",
        "property": "payload.code",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "0",
                "vt": "num"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 2380,
        "y": 640,
        "wires": [
            [
                "dafe5c65a71f08a1"
            ],
            []
        ]
    },
    {
        "id": "dafe5c65a71f08a1",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "name": "Move Temporary File",
        "func": "msg.payload = `mv \"${msg.transcode.temporary}\" \"${msg.transcode.folder}\"`\nreturn msg\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 2020,
        "y": 700,
        "wires": [
            [
                "219a0d7c2b981228"
            ]
        ]
    },
    {
        "id": "219a0d7c2b981228",
        "type": "exec",
        "z": "9f98f36f3385bcd8",
        "command": "",
        "addpay": "payload",
        "append": "",
        "useSpawn": "false",
        "timer": "",
        "winHide": false,
        "oldrc": false,
        "name": "",
        "x": 2210,
        "y": 700,
        "wires": [
            [],
            [
                "17815b61e1ec70fb"
            ],
            [
                "73019a0f8f866a27"
            ]
        ]
    },
    {
        "id": "73019a0f8f866a27",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "name": "Success",
        "property": "payload.code",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "0",
                "vt": "num"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 2380,
        "y": 700,
        "wires": [
            [],
            []
        ]
    },
    {
        "id": "a68ae4599eace14b",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "link out 3",
        "mode": "link",
        "links": [
            "e033200ab27e896d",
            "a2ce74176e7bb93a"
        ],
        "x": 1445,
        "y": 260,
        "wires": []
    },
    {
        "id": "17815b61e1ec70fb",
        "type": "debug",
        "z": "9f98f36f3385bcd8",
        "name": "debug 4",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 2420,
        "y": 540,
        "wires": []
    },
    {
        "id": "8c9ef2a07a0e271b",
        "type": "ui_text",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "group": "7c5d8648955e9a1f",
        "order": 3,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "Transcode Queue Size",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 690,
        "y": 340,
        "wires": []
    },
    {
        "id": "e42a58c30039d179",
        "type": "exec",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "command": "",
        "addpay": "payload",
        "append": "",
        "useSpawn": "false",
        "timer": "",
        "winHide": true,
        "oldrc": false,
        "name": "",
        "x": 210,
        "y": 720,
        "wires": [
            [
                "81fb8456c8a24bef"
            ],
            [
                "ad7b379fe92408f3"
            ],
            [
                "5d78f655434a6555"
            ]
        ]
    },
    {
        "id": "c322cf0d03d623b1",
        "type": "template",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "ffprobe Template (Query)",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "\"{{{flow.ffprobeBinary}}}\"\n-v error \n-show_streams \n-show_entries stream=codec_type,codec_name,width\n-of json \n-v quiet\n-i \"{{{payload}}}\"\n",
        "output": "str",
        "x": 570,
        "y": 840,
        "wires": [
            [
                "01680d728b478aa5"
            ]
        ]
    },
    {
        "id": "81fb8456c8a24bef",
        "type": "json",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "",
        "property": "payload",
        "action": "obj",
        "pretty": false,
        "x": 350,
        "y": 720,
        "wires": [
            [
                "f0d454696f6e547f"
            ]
        ]
    },
    {
        "id": "01680d728b478aa5",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "function 6",
        "func": "// normalize newlines\nvar regex = context.get('regex')\nmsg.payload = msg.payload.replace(regex, ' ')\n\n// return message\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "var reg = new RegExp(os.EOL, 'g')\ncontext.set('regex', reg)",
        "finalize": "",
        "libs": [
            {
                "var": "os",
                "module": "os"
            }
        ],
        "x": 780,
        "y": 840,
        "wires": [
            [
                "e42a58c30039d179"
            ]
        ]
    },
    {
        "id": "f0d454696f6e547f",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "Check Probe matches Template",
        "func": "function traverse(target) {\n    for (const key in target) {\n        const value = target[key]\n        if (typeof value === 'object' && value) {\n            traverse(value)\n            continue\n        }\n        switch (key) {\n            case 'codec_type':\n                switch (value) {\n                    case 'video':\n                        if (target['codec_name'] != flow.get('_videoCodec')) {\n                            node.send([msg, null])\n                            return\n                        }\n                        var width = parseInt(target['width'])\n                        if (width > flow.get('_videoWidth')) {\n                            node.send([msg, null])\n                            return\n                        }\n                        break;\n                    case 'audio':\n                        if (target['codec_name'] != flow.get('_audioCodec')) {\n                            node.send([msg, null])\n                            return\n                        }\n                        break;\n                }\n                break;\n        }\n    }\n}\n\ntraverse(msg.payload)\nnode.send([null, {'payload': null}])\n",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 580,
        "y": 720,
        "wires": [
            [
                "60bbd40c3f9d8c0e"
            ],
            [
                "17b475a2e7ea9516"
            ]
        ]
    },
    {
        "id": "790c3950a63fa109",
        "type": "ui_text",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "group": "57b96149bd97f3cb",
        "order": 3,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "File Count",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1390,
        "y": 1220,
        "wires": []
    },
    {
        "id": "68c70fe740f38a81",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Set Control Folder",
        "func": "flow.set('_controlFolder', msg.payload)\n",
        "outputs": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 570,
        "y": 1280,
        "wires": []
    },
    {
        "id": "d666d15dbafe8395",
        "type": "link in",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "link in 3",
        "links": [
            "e45801f0b7cc3cd4"
        ],
        "x": 105,
        "y": 600,
        "wires": [
            [
                "2098ad1b433ffa26",
                "191bead4c0d01b13"
            ]
        ]
    },
    {
        "id": "a4ebe3b65ec64062",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "Dequeue Probe Queue",
        "func": "flow.set('_probeQueueUnlocked', true)",
        "outputs": 2,
        "noerr": 0,
        "initialize": "setInterval(() => {\n    if (!flow.get('_probeQueueUnlocked')) {\n        return\n    }\n\n    var queue = flow.get('_probeQueue')\n    if (queue.length == 0) {\n        node.send([null, { \"payload\": null }])\n        flow.set('_probeQueueUnlocked', false)\n        return\n    }\n    var first = queue.pop()\n    flow.set('_probeQueue', queue)\n\n    flow.set('_probeQueueUnlocked', false)\n    msg = {}\n    msg.payload = first\n    msg.transcode = first\n    msg.queue = queue\n    \n    node.send([msg, null])\n}, 1000)\n",
        "finalize": "",
        "libs": [],
        "x": 270,
        "y": 840,
        "wires": [
            [
                "c322cf0d03d623b1",
                "8781d05a891a5bb1",
                "4b49fa8ec7c43636"
            ],
            [
                "191bead4c0d01b13",
                "3e33e76d0e3c0e4d"
            ]
        ]
    },
    {
        "id": "60bbd40c3f9d8c0e",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "Set Transcode Queue",
        "func": "var transcodeQueue = flow.get('_transcodeQueue')\nif(!Array.isArray(transcodeQueue)) {\n    transcodeQueue = []\n}\nif (!transcodeQueue.find(element => element == msg.transcode)) {\n    transcodeQueue.push(msg.transcode)\n}\nflow.set('_transcodeQueue', transcodeQueue)\nmsg.payload = transcodeQueue\nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 850,
        "y": 720,
        "wires": [
            [
                "1b541b828612bc99",
                "d40dc9475eb9ecba"
            ]
        ]
    },
    {
        "id": "1b541b828612bc99",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "link out 4",
        "mode": "link",
        "links": [
            "3701809d5b290f02"
        ],
        "x": 1005,
        "y": 720,
        "wires": []
    },
    {
        "id": "3701809d5b290f02",
        "type": "link in",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "link in 4",
        "links": [
            "1b541b828612bc99",
            "85a7ea277d73d0f1",
            "17b475a2e7ea9516",
            "98be7c1856cb4c3f",
            "0e3a3381bc3841f3"
        ],
        "x": 105,
        "y": 840,
        "wires": [
            [
                "a4ebe3b65ec64062",
                "ceccd99cf2a40534"
            ]
        ]
    },
    {
        "id": "2098ad1b433ffa26",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "kill",
                "pt": "msg",
                "to": "",
                "tot": "date"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 230,
        "y": 640,
        "wires": [
            [
                "e42a58c30039d179"
            ]
        ]
    },
    {
        "id": "7a7af815b51f0fd1",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "kill",
                "pt": "msg",
                "to": "",
                "tot": "date"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 790,
        "y": 200,
        "wires": [
            [
                "6314709e0f7c7b6b"
            ]
        ]
    },
    {
        "id": "a78f6c483e1e2597",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "link out 6",
        "mode": "link",
        "links": [
            "9616785c60c44f70"
        ],
        "x": 615,
        "y": 460,
        "wires": []
    },
    {
        "id": "1e743f463192bfd3",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Replace Original File (Delete & Move)",
        "func": "var promise = new Promise((resolve, reject) => {\n    fs.unlink(msg.transcode.original, (error) => {\n        if(error) {\n            reject(error)\n            return\n        }\n        var target = path.join(path.dirname(msg.transcode.original), path.basename(msg.transcode.temporary))\n        fs.copyFile(msg.transcode.temporary, target, (error) => {\n            if(error) {\n                reject(error)\n                return\n            }\n            fs.unlink(msg.transcode.temporary, (error) => {\n                if(error) {\n                    reject(error)\n                    return\n                }\n                resolve(true)\n            })\n        })\n    })\n})\n\nvar result = await promise\nif(result) {\n    return [ { payload: \"success\" }, null ]\n}\n\nreturn [null, { \"payload\": result }]",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [
            {
                "var": "fs",
                "module": "fs"
            },
            {
                "var": "path",
                "module": "path"
            }
        ],
        "x": 1210,
        "y": 300,
        "wires": [
            [
                "a68ae4599eace14b"
            ],
            [
                "a49ead80df7d8134",
                "a68ae4599eace14b"
            ]
        ]
    },
    {
        "id": "a49ead80df7d8134",
        "type": "ui_text",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "group": "7c5d8648955e9a1f",
        "order": 0,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "ffmpeg Errors",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1140,
        "y": 400,
        "wires": []
    },
    {
        "id": "bb0d09b469240dbb",
        "type": "ui_text",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "group": "7c5d8648955e9a1f",
        "order": 0,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "ffprobe Errors",
        "format": "{{msg.payload.message}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 780,
        "y": 980,
        "wires": []
    },
    {
        "id": "2d56998ff17d9e44",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "kill",
        "props": [
            {
                "p": "kill",
                "v": "",
                "vt": "date"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 580,
        "wires": [
            [
                "e42a58c30039d179"
            ]
        ]
    },
    {
        "id": "f06ae7fe45bc8ee6",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Initialize ffmpeg Errors",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "_ffmpegErrorsInitialized",
                "pt": "flow",
                "to": "true",
                "tot": "bool"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 920,
        "y": 400,
        "wires": [
            [
                "a49ead80df7d8134"
            ]
        ]
    },
    {
        "id": "0b74e59054355a3a",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Check ffmpeg Errors Initialized",
        "property": "_ffmpegErrorsInitialized",
        "propertyType": "flow",
        "rules": [
            {
                "t": "false"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 650,
        "y": 400,
        "wires": [
            [
                "f06ae7fe45bc8ee6"
            ],
            []
        ]
    },
    {
        "id": "49b44f05bfa9c6ac",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "Initialize ffprobe Errors",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "_ffprobeErrorsInitialized",
                "pt": "flow",
                "to": "true",
                "tot": "bool"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 560,
        "y": 980,
        "wires": [
            [
                "bb0d09b469240dbb"
            ]
        ]
    },
    {
        "id": "ceccd99cf2a40534",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "Check ffprobe Errors Initialized",
        "property": "_ffprobeErrorsInitialized",
        "propertyType": "flow",
        "rules": [
            {
                "t": "false"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 290,
        "y": 980,
        "wires": [
            [
                "49b44f05bfa9c6ac"
            ],
            []
        ]
    },
    {
        "id": "191bead4c0d01b13",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "Reset Initializations",
        "rules": [
            {
                "t": "set",
                "p": "_ffprobeErrorsInitialized",
                "pt": "flow",
                "to": "false",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "_probeQueue",
                "pt": "flow",
                "to": "[]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 530,
        "y": 640,
        "wires": [
            []
        ]
    },
    {
        "id": "db1094061707ac30",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Reset Initializations",
        "rules": [
            {
                "t": "set",
                "p": "_ffmpegErrorsInitialized",
                "pt": "flow",
                "to": "false",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "_transcodeQueue",
                "pt": "flow",
                "to": "[]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 470,
        "y": 460,
        "wires": [
            []
        ]
    },
    {
        "id": "5e5ac174da4067e4",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "init",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "str",
        "x": 870,
        "y": 460,
        "wires": [
            [
                "f06ae7fe45bc8ee6"
            ]
        ]
    },
    {
        "id": "914f0e31f40c7895",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "init",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "str",
        "x": 370,
        "y": 1040,
        "wires": [
            [
                "49b44f05bfa9c6ac"
            ]
        ]
    },
    {
        "id": "54efb1e3b0611844",
        "type": "ui_switch",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "",
        "label": "Force Transcode",
        "tooltip": "",
        "group": "57b96149bd97f3cb",
        "order": 4,
        "width": 0,
        "height": 0,
        "passthru": true,
        "decouple": "false",
        "topic": "topic",
        "topicType": "msg",
        "style": "",
        "onvalue": "true",
        "onvalueType": "bool",
        "onicon": "",
        "oncolor": "",
        "offvalue": "false",
        "offvalueType": "bool",
        "officon": "",
        "offcolor": "",
        "animate": false,
        "className": "",
        "x": 530,
        "y": 1540,
        "wires": [
            [
                "ce11dc4527d4245e"
            ]
        ]
    },
    {
        "id": "ce11dc4527d4245e",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Store Force Transcode",
        "rules": [
            {
                "t": "set",
                "p": "_forceTranscode",
                "pt": "flow",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 770,
        "y": 1540,
        "wires": [
            []
        ]
    },
    {
        "id": "d497ac7322a54f69",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Recall Force Transcode",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "_forceTranscode",
        "payloadType": "flow",
        "x": 290,
        "y": 1540,
        "wires": [
            [
                "54efb1e3b0611844"
            ]
        ]
    },
    {
        "id": "1e43c0ffb0d80603",
        "type": "ui_dropdown",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "label": "Video Codec",
        "tooltip": "",
        "place": "Select option",
        "group": "85a1a4cd106754fa",
        "order": 0,
        "width": 0,
        "height": 0,
        "passthru": true,
        "multiple": false,
        "options": [
            {
                "label": "",
                "value": "h264",
                "type": "str"
            },
            {
                "label": "",
                "value": "hvec",
                "type": "str"
            }
        ],
        "payload": "",
        "topic": "topic",
        "topicType": "msg",
        "className": "",
        "x": 480,
        "y": 1820,
        "wires": [
            [
                "0556bead30d14d7a"
            ]
        ]
    },
    {
        "id": "f6172a25a7ac7bca",
        "type": "ui_dropdown",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "label": "Audio Codec",
        "tooltip": "",
        "place": "Select option",
        "group": "85a1a4cd106754fa",
        "order": 0,
        "width": 0,
        "height": 0,
        "passthru": true,
        "multiple": false,
        "options": [
            {
                "label": "",
                "value": "aac",
                "type": "str"
            },
            {
                "label": "",
                "value": "avc",
                "type": "str"
            }
        ],
        "payload": "",
        "topic": "topic",
        "topicType": "msg",
        "className": "",
        "x": 480,
        "y": 1960,
        "wires": [
            [
                "126582f943f52389"
            ]
        ]
    },
    {
        "id": "b0bb9aa491c3bd80",
        "type": "ui_text_input",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "label": "Video Width",
        "tooltip": "",
        "group": "85a1a4cd106754fa",
        "order": 2,
        "width": 0,
        "height": 0,
        "passthru": true,
        "mode": "text",
        "delay": 300,
        "topic": "topic",
        "sendOnBlur": true,
        "className": "",
        "topicType": "msg",
        "x": 480,
        "y": 2100,
        "wires": [
            [
                "bfef60164daf91e3"
            ]
        ]
    },
    {
        "id": "81d7c71da8797959",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Recall Video Codec",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "_videoCodec",
        "payloadType": "flow",
        "x": 250,
        "y": 1820,
        "wires": [
            [
                "188dc2f88112d7df"
            ]
        ]
    },
    {
        "id": "0556bead30d14d7a",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store Video Codec",
        "rules": [
            {
                "t": "set",
                "p": "_videoCodec",
                "pt": "flow",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 680,
        "y": 1820,
        "wires": [
            []
        ]
    },
    {
        "id": "879ac930e91a750f",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Recall Audio Codec",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "_audioCodec",
        "payloadType": "flow",
        "x": 250,
        "y": 1960,
        "wires": [
            [
                "8f42b24f5ba8481e"
            ]
        ]
    },
    {
        "id": "891e2e4363a18786",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Recall Video Width",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "_videoWidth",
        "payloadType": "flow",
        "x": 240,
        "y": 2100,
        "wires": [
            [
                "1de5c48e2d62e5b0"
            ]
        ]
    },
    {
        "id": "126582f943f52389",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store Audio Codec",
        "rules": [
            {
                "t": "set",
                "p": "_audioCodec",
                "pt": "flow",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 680,
        "y": 1960,
        "wires": [
            []
        ]
    },
    {
        "id": "bfef60164daf91e3",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store Video Width",
        "rules": [
            {
                "t": "set",
                "p": "_videoWidth",
                "pt": "flow",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 680,
        "y": 2100,
        "wires": [
            []
        ]
    },
    {
        "id": "5de93c3d896716d6",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Recall Output Container",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "_videoContainer",
        "payloadType": "flow",
        "x": 260,
        "y": 2240,
        "wires": [
            [
                "c3f80d80e84d13ba"
            ]
        ]
    },
    {
        "id": "b23bafe27c4c5b95",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store Output Container",
        "rules": [
            {
                "t": "set",
                "p": "_videoContainer",
                "pt": "flow",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 740,
        "y": 2240,
        "wires": [
            []
        ]
    },
    {
        "id": "ae3859e24088c5f2",
        "type": "ui_dropdown",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "label": "Output Container",
        "tooltip": "",
        "place": "Select option",
        "group": "85a1a4cd106754fa",
        "order": 6,
        "width": 0,
        "height": 0,
        "passthru": true,
        "multiple": false,
        "options": [
            {
                "label": "",
                "value": "mp4",
                "type": "str"
            },
            {
                "label": "",
                "value": "mkv",
                "type": "str"
            }
        ],
        "payload": "",
        "topic": "topic",
        "topicType": "msg",
        "className": "",
        "x": 500,
        "y": 2240,
        "wires": [
            [
                "b23bafe27c4c5b95"
            ]
        ]
    },
    {
        "id": "188c2940f78ada06",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Folder Watcher",
        "func": "if (!flow.get('_enableWatching') || flow.get('_watchingBlocked')) {\n    return\n}\n\nvar fileExtensionWhitelist = flow.get('_fileExtensionWhitelist')\n\nvar watcher = context.get('watcher')\nvar watcher = chokidar.watch(msg.payload, {\n    ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\n    persistent: true,\n    ignoreInitial: true\n}).on('add', path => {\n    if (!fileExtensionWhitelist.includes(path.split('.').pop())) {\n        node.send([null, { \"payload\": path }])\n        return\n    }\n    node.send([{ \"payload\": path }, null])\n})\n\ncontext.set('watcher', watcher)",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [
            {
                "var": "chokidar",
                "module": "chokidar"
            }
        ],
        "x": 560,
        "y": 1340,
        "wires": [
            [
                "c8c10f76c08795ac"
            ],
            []
        ]
    },
    {
        "id": "c8c10f76c08795ac",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Add to Probe Queue",
        "func": "var queue = flow.get('_probeQueue')\nif (!Array.isArray(queue)) {\n    queue = []\n}\nqueue.push(msg.payload)\nflow.set('_probeQueue', queue)\n",
        "outputs": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [
            {
                "var": "path",
                "module": "path"
            }
        ],
        "x": 780,
        "y": 1340,
        "wires": []
    },
    {
        "id": "188dc2f88112d7df",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "empty"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 460,
        "y": 1760,
        "wires": [
            [
                "b3b9dcb7075207b1"
            ],
            [
                "1e43c0ffb0d80603"
            ]
        ]
    },
    {
        "id": "b3b9dcb7075207b1",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store Video Codec",
        "rules": [
            {
                "t": "set",
                "p": "_videoCodec",
                "pt": "flow",
                "to": "h264",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "h264",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 680,
        "y": 1760,
        "wires": [
            [
                "1e43c0ffb0d80603"
            ]
        ]
    },
    {
        "id": "8f42b24f5ba8481e",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "empty"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 460,
        "y": 1900,
        "wires": [
            [
                "95f8b028b62316d7"
            ],
            [
                "f6172a25a7ac7bca"
            ]
        ]
    },
    {
        "id": "95f8b028b62316d7",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store Audio Codec",
        "rules": [
            {
                "t": "set",
                "p": "_audioCodec",
                "pt": "flow",
                "to": "aac",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "aac",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 680,
        "y": 1900,
        "wires": [
            [
                "f6172a25a7ac7bca"
            ]
        ]
    },
    {
        "id": "1de5c48e2d62e5b0",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "empty"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 460,
        "y": 2040,
        "wires": [
            [
                "b6686ce43478776f"
            ],
            [
                "b0bb9aa491c3bd80"
            ]
        ]
    },
    {
        "id": "b6686ce43478776f",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store Video Width",
        "rules": [
            {
                "t": "set",
                "p": "_videoWidth",
                "pt": "flow",
                "to": "640",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "640",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 680,
        "y": 2040,
        "wires": [
            [
                "b0bb9aa491c3bd80"
            ]
        ]
    },
    {
        "id": "c3f80d80e84d13ba",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "empty"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 460,
        "y": 2180,
        "wires": [
            [
                "436aa2571f967479"
            ],
            [
                "ae3859e24088c5f2"
            ]
        ]
    },
    {
        "id": "436aa2571f967479",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store Video Container",
        "rules": [
            {
                "t": "set",
                "p": "_videoContainer",
                "pt": "flow",
                "to": "mp4",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "mp4",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 730,
        "y": 2180,
        "wires": [
            [
                "ae3859e24088c5f2"
            ]
        ]
    },
    {
        "id": "b6c06f50e19f051d",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Recall Enable Watching",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "_enableWatching",
        "payloadType": "flow",
        "x": 290,
        "y": 1600,
        "wires": [
            [
                "3ea505b539e0b9ad"
            ]
        ]
    },
    {
        "id": "3ea505b539e0b9ad",
        "type": "ui_switch",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "",
        "label": "Enable Watching Folders for FIles",
        "tooltip": "",
        "group": "57b96149bd97f3cb",
        "order": 4,
        "width": 0,
        "height": 0,
        "passthru": true,
        "decouple": "false",
        "topic": "topic",
        "topicType": "msg",
        "style": "",
        "onvalue": "true",
        "onvalueType": "bool",
        "onicon": "",
        "oncolor": "",
        "offvalue": "false",
        "offvalueType": "bool",
        "officon": "",
        "offcolor": "",
        "animate": false,
        "className": "",
        "x": 580,
        "y": 1600,
        "wires": [
            [
                "8073655aeb3b7029"
            ]
        ]
    },
    {
        "id": "8073655aeb3b7029",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Store Force Transcode",
        "rules": [
            {
                "t": "set",
                "p": "_enableWatching",
                "pt": "flow",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 870,
        "y": 1600,
        "wires": [
            []
        ]
    },
    {
        "id": "8b09525b6f843634",
        "type": "ui_dropdown",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "label": "Process Files",
        "tooltip": "",
        "place": "Select option",
        "group": "85a1a4cd106754fa",
        "order": 6,
        "width": 0,
        "height": 0,
        "passthru": true,
        "multiple": true,
        "options": [
            {
                "label": "",
                "value": "mkv",
                "type": "str"
            },
            {
                "label": "",
                "value": "mp4",
                "type": "str"
            }
        ],
        "payload": "",
        "topic": "topic",
        "topicType": "msg",
        "className": "",
        "x": 490,
        "y": 2400,
        "wires": [
            [
                "90305768b3fc9d1c"
            ]
        ]
    },
    {
        "id": "bf2116ae3cbe5b57",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Recall File Extension Whitelist",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "_fileExtensionWhitelist",
        "payloadType": "flow",
        "x": 240,
        "y": 2400,
        "wires": [
            [
                "2a4044a67d1a5f60"
            ]
        ]
    },
    {
        "id": "90305768b3fc9d1c",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store File Extension Whitelist",
        "rules": [
            {
                "t": "set",
                "p": "_fileExtensionWhitelist",
                "pt": "flow",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 730,
        "y": 2400,
        "wires": [
            []
        ]
    },
    {
        "id": "2a4044a67d1a5f60",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "empty"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 460,
        "y": 2340,
        "wires": [
            [
                "06a7100f39e362cc"
            ],
            [
                "8b09525b6f843634"
            ]
        ]
    },
    {
        "id": "06a7100f39e362cc",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "13e7445ef83fcae8",
        "name": "Store File Extension Whitelist",
        "rules": [
            {
                "t": "set",
                "p": "_fileExtensionWhitelist",
                "pt": "flow",
                "to": "[ \"mp4\", \"mkv\" ]",
                "tot": "jsonata"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "[ \"mp4\", \"mkv\" ]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 730,
        "y": 2340,
        "wires": [
            [
                "8b09525b6f843634"
            ]
        ]
    },
    {
        "id": "ad7b379fe92408f3",
        "type": "debug",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "debug 11",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 390,
        "y": 580,
        "wires": []
    },
    {
        "id": "17b475a2e7ea9516",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "link out 7",
        "mode": "link",
        "links": [
            "3701809d5b290f02"
        ],
        "x": 765,
        "y": 780,
        "wires": []
    },
    {
        "id": "5d78f655434a6555",
        "type": "switch",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "Success",
        "property": "payload.code",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "0",
                "vt": "num"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 330,
        "y": 780,
        "wires": [
            [],
            [
                "bb0d09b469240dbb",
                "98be7c1856cb4c3f"
            ]
        ]
    },
    {
        "id": "98be7c1856cb4c3f",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "link out 8",
        "mode": "link",
        "links": [
            "3701809d5b290f02"
        ],
        "x": 465,
        "y": 780,
        "wires": []
    },
    {
        "id": "1102635d4c82203c",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "link out 9",
        "mode": "link",
        "links": [
            "e033200ab27e896d",
            "a2ce74176e7bb93a"
        ],
        "x": 1075,
        "y": 340,
        "wires": []
    },
    {
        "id": "f1897b1f7b56d49d",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Transcode Queue",
        "func": "flow.set('_transcodeQueueUnlocked', true)\n",
        "outputs": 2,
        "noerr": 0,
        "initialize": "setInterval(() => {\n    if(!flow.get('_transcodeQueueUnlocked')) {\n        return\n    }\n\n    var queue = flow.get('_transcodeQueue')\n    if(queue.length == 0) {\n        node.send([ null, { \"payload\": null }])\n        flow.set('_transcodeQueueUnlocked', false)\n        return\n    }\n    var first = queue.pop()\n    flow.set('_transcodeQueue', queue)\n\n    flow.set('_transcodeQueueUnlocked', false)\n\n    var name = path.basename(first)\n\n    // replace file extension\n    var segments = name.split('.')\n    segments.pop()\n    var videoContainer = flow.get('_videoContainer')\n    segments.push(videoContainer)\n    name = segments.join('.')\n\n    var workFolder = flow.get('workFolder')\n    var temp = path.join(workFolder, name)\n\n    msg = {}\n    var data = {\n        'original': first,\n        'temporary': temp\n    }\n    msg.payload = data\n    msg.transcode = data\n    msg.queue = queue\n    \n    node.send([ msg, null])\n}, 1000)\n",
        "finalize": "",
        "libs": [
            {
                "var": "path",
                "module": "path"
            }
        ],
        "x": 250,
        "y": 280,
        "wires": [
            [
                "b4fd821e4032327a",
                "2023c957f816a653",
                "e45a9ec830c51602"
            ],
            [
                "a78f6c483e1e2597",
                "db1094061707ac30"
            ]
        ]
    },
    {
        "id": "54b14ea280430dea",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "Initialize Queue",
        "rules": [
            {
                "t": "set",
                "p": "_transcodeQueueUnlocked",
                "pt": "flow",
                "to": "true",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "_transcodeQueue",
                "pt": "flow",
                "to": "[]",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 240,
        "y": 220,
        "wires": [
            []
        ]
    },
    {
        "id": "41accef666076be8",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "init",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 210,
        "y": 160,
        "wires": [
            [
                "54b14ea280430dea"
            ]
        ]
    },
    {
        "id": "1bde2da775a09b2b",
        "type": "debug",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "debug 12",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1280,
        "y": 80,
        "wires": []
    },
    {
        "id": "e45a9ec830c51602",
        "type": "debug",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "debug 13",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 460,
        "y": 180,
        "wires": []
    },
    {
        "id": "c7abb9a6ba15539c",
        "type": "change",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "Initialize Queue",
        "rules": [
            {
                "t": "set",
                "p": "_probeQueue",
                "pt": "flow",
                "to": "[]",
                "tot": "jsonata"
            },
            {
                "t": "set",
                "p": "_probeQueueUnlocked",
                "pt": "flow",
                "to": "true",
                "tot": "bool"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1280,
        "y": 900,
        "wires": [
            []
        ]
    },
    {
        "id": "92f3af459ce90aa3",
        "type": "inject",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "init",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 1110,
        "y": 900,
        "wires": [
            [
                "c7abb9a6ba15539c"
            ]
        ]
    },
    {
        "id": "8781d05a891a5bb1",
        "type": "ui_text",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "group": "7c5d8648955e9a1f",
        "order": 6,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "Scanning File",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 340,
        "y": 900,
        "wires": []
    },
    {
        "id": "4b49fa8ec7c43636",
        "type": "ui_text",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "group": "7c5d8648955e9a1f",
        "order": 7,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "Probe Queue Size",
        "format": "{{msg.queue.length}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 620,
        "y": 900,
        "wires": []
    },
    {
        "id": "6169a14dcff6f101",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Count Queue",
        "func": "var queue = flow.get('_probeQueue')\nif(!Array.isArray(queue)) {\n    return\n}\nmsg.payload = queue.length\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1200,
        "y": 1220,
        "wires": [
            [
                "790c3950a63fa109"
            ]
        ]
    },
    {
        "id": "dc1ccff0ec482caa",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Set Run",
        "func": "flow.set('_run', false)",
        "outputs": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 540,
        "y": 1460,
        "wires": []
    },
    {
        "id": "dacd4902bd230787",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "Set Run",
        "func": "flow.set('_run', true)\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 540,
        "y": 1220,
        "wires": [
            [
                "312a5bcb53309fbd"
            ]
        ]
    },
    {
        "id": "0e3a3381bc3841f3",
        "type": "link out",
        "z": "9f98f36f3385bcd8",
        "g": "118640a37c2f6bac",
        "name": "link out 10",
        "mode": "link",
        "links": [
            "3701809d5b290f02"
        ],
        "x": 925,
        "y": 1280,
        "wires": []
    },
    {
        "id": "2023c957f816a653",
        "type": "function",
        "z": "9f98f36f3385bcd8",
        "g": "1a8449d0623e98a6",
        "name": "function 7",
        "func": "msg.payload = msg.queue.length\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 460,
        "y": 340,
        "wires": [
            [
                "8c9ef2a07a0e271b"
            ]
        ]
    },
    {
        "id": "d40dc9475eb9ecba",
        "type": "debug",
        "z": "9f98f36f3385bcd8",
        "g": "8c088cb2f7181ba2",
        "name": "debug 14",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 880,
        "y": 640,
        "wires": []
    },
    {
        "id": "7c5d8648955e9a1f",
        "type": "ui_group",
        "name": "Progress",
        "tab": "a5cec446271eb3ef",
        "order": 1,
        "disp": true,
        "width": "12",
        "collapse": false,
        "className": ""
    },
    {
        "id": "57b96149bd97f3cb",
        "type": "ui_group",
        "name": "Control",
        "tab": "a5cec446271eb3ef",
        "order": 2,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "85a1a4cd106754fa",
        "type": "ui_group",
        "name": "Settings",
        "tab": "a5cec446271eb3ef",
        "order": 5,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "a5cec446271eb3ef",
        "type": "ui_tab",
        "name": "Transcoding",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]