Audio File Upload

Hello,

I am trying to understand the best way to upload an audio file using the dashboard to be able to save to the local system running Node-RED.

I am running the latest version of Node-RED (v3.0.0) on a Raspberry Pi 4. I would like the user to have a traditional upload interface that allows them to upload an audio file that I can then send to a write file node to store locally on the Pi.

I have used the node-red-contrib-ui-upload node to do this successfully but in my opinion the presentation is not what I am after.

I have followed some other examples I have found on the forum but the end result creates an empty .wav file. Most of these examples involve using http and a ui-template node.

I have attached my flow below that has made the most progress. In this flow I am able to upload and retrieve the file, but it appears only the filename is retrieved. A .wav file is created, but trying to open it results in an empty VLC player window.

I saw this post on the forum which seems simple enough, but I am doing something wrong. Thank you for the help!

[
    {
        "id": "1ea6e4f0e888d171",
        "type": "http in",
        "z": "44b69cc2e6eb114f",
        "name": "",
        "url": "/upload",
        "method": "post",
        "upload": true,
        "swaggerDoc": "",
        "x": 430,
        "y": 320,
        "wires": [
            [
                "5534efc82dd10822"
            ]
        ]
    },
    {
        "id": "736323d67c0bc447",
        "type": "http response",
        "z": "44b69cc2e6eb114f",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 810,
        "y": 320,
        "wires": []
    },
    {
        "id": "893db8f378e89032",
        "type": "ui_template",
        "z": "44b69cc2e6eb114f",
        "group": "dfb4a60f.d788f8",
        "name": "",
        "order": 9,
        "width": 0,
        "height": 0,
        "format": "<form action=\"/upload\" method=\"POST\">\n    <input type=\"file\" name=\"myFile\" />\n    <input type=\"submit\" />\n</form>",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 600,
        "y": 400,
        "wires": [
            []
        ]
    },
    {
        "id": "46e3c59d0d4a7d61",
        "type": "debug",
        "z": "44b69cc2e6eb114f",
        "name": "debug 1",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 620,
        "y": 220,
        "wires": []
    },
    {
        "id": "5534efc82dd10822",
        "type": "file",
        "z": "44b69cc2e6eb114f",
        "name": "",
        "filename": "/home/mtg/fire.wav",
        "filenameType": "str",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "binary",
        "x": 630,
        "y": 320,
        "wires": [
            [
                "736323d67c0bc447"
            ]
        ]
    },
    {
        "id": "dfb4a60f.d788f8",
        "type": "ui_group",
        "name": "Data Export",
        "tab": "48418b79.0f5834",
        "order": 1,
        "disp": true,
        "width": "12"
    },
    {
        "id": "48418b79.0f5834",
        "type": "ui_tab",
        "name": "Dashboard",
        "icon": "dashboard",
        "order": 1,
        "disabled": false,
        "hidden": false
    }
]

You need to move the buffer from the request to msg.payload in order for the file write to occur. Try this

/home/mtg/fire.wav

look at the template and see the other change.

in the debug output look at the msg.req.file

I'm not sure if there was supposed to be some code attached but I'm not sure what you mean by "look at the template and see the other change"? Also I could be overlooking it but I don't see a buffer in msg.req.file. I saw this in another thread as well and I used the same pathing they did as well as a couple of others to try to find the buffer but it appears mine doesn't have it. It's almost as if it is only uploading the name of the file and not the contents of the file.

oops :flushed:, yes there was suppose to be a flow. Here it is:

[{"id":"1ea6e4f0e888d171","type":"http in","z":"74944670f8a16aaf","name":"","url":"/upload","method":"post","upload":true,"swaggerDoc":"","x":230,"y":240,"wires":[["46e3c59d0d4a7d61","90d398f90b54eb2f"]]},{"id":"736323d67c0bc447","type":"http response","z":"74944670f8a16aaf","name":"","statusCode":"","headers":{},"x":950,"y":240,"wires":[]},{"id":"893db8f378e89032","type":"ui_template","z":"74944670f8a16aaf","group":"dfb4a60f.d788f8","name":"","order":9,"width":0,"height":0,"format":"<form action=\"/upload\" method=\"post\" enctype=\"multipart/form-data\">\n    <input type=\"file\" name=\"myFile\" />\n    <input type=\"submit\" value=\"upload\"/>\n</form>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","className":"","x":480,"y":320,"wires":[[]]},{"id":"46e3c59d0d4a7d61","type":"debug","z":"74944670f8a16aaf","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":480,"y":160,"wires":[]},{"id":"5534efc82dd10822","type":"file","z":"74944670f8a16aaf","name":"","filename":"/home/mtg/fire.wav","filenameType":"str","appendNewline":false,"createDir":true,"overwriteFile":"true","encoding":"binary","x":710,"y":240,"wires":[["736323d67c0bc447"]]},{"id":"90d398f90b54eb2f","type":"change","z":"74944670f8a16aaf","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"req.files[0].buffer","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":240,"wires":[["5534efc82dd10822"]]},{"id":"dfb4a60f.d788f8","type":"ui_group","name":"Data Export","tab":"48418b79.0f5834","order":1,"disp":true,"width":"12"},{"id":"48418b79.0f5834","type":"ui_tab","name":"Dashboard","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

We're making some progress because with your new template code I now have a msg.req.files and even a buffer with information in it. However I'm getting a strange result as the payload of the change node is empty, therefore no file is written. The resulting webpage I'm taken to after pressing upload simply shows "{}" as if it's empty as well.

What do you see in the debug sidebar? copy the whole object and paste it to a response
Screen Shot 2022-07-28 at 11.49.40 AM

{"_msgid":"acc7f8d109b6c478","payload":{},"req":{"_readableState":{"objectMode":false,"highWaterMark":16384,"buffer":{"head":null,"tail":null,"length":0},"length":0,"pipes":[],"flowing":false,"ended":true,"endEmitted":true,"reading":false,"constructed":true,"sync":false,"needReadable":false,"emittedReadable":false,"readableListening":false,"resumeScheduled":false,"errorEmitted":false,"emitClose":true,"autoDestroy":true,"destroyed":true,"errored":null,"closed":true,"closeEmitted":true,"defaultEncoding":"utf8","awaitDrainWriters":null,"multiAwaitDrain":false,"readingMore":false,"dataEmitted":true,"decoder":null,"encoding":null},"_events":{},"_eventsCount":1,"socket":"[internal]","httpVersionMajor":1,"httpVersionMinor":1,"httpVersion":"1.1","complete":true,"rawHeaders":["Host","mtg-desk:1880","Connection","keep-alive","Content-Length","1227661","Cache-Control","max-age=0","Upgrade-Insecure-Requests","1","Origin","http://mtg-desk:1880","Content-Type","multipart/form-data; boundary=----WebKitFormBoundary5Bs5BY7PAdO42Ckt","User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36","Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","Referer","http://mtg-desk:1880/ui/","Accept-Encoding","gzip, deflate","Accept-Language","en-US,en;q=0.9"],"rawTrailers":[],"aborted":false,"upgrade":false,"url":"/upload","method":"POST","statusCode":null,"statusMessage":null,"client":"[internal]","_consuming":true,"_dumped":false,"baseUrl":"","originalUrl":"/upload","_parsedUrl":{"protocol":null,"slashes":null,"auth":null,"host":null,"port":null,"hostname":null,"hash":null,"search":null,"query":null,"pathname":"/upload","path":"/upload","href":"/upload","_raw":"/upload"},"params":{},"query":{},"res":"[internal]","body":{},"_sessionManager":{"_key":"passport"},"_passport":{"instance":{"_key":"passport","_strategies":{"session":{"name":"session","_key":"passport"},"bearer":{"name":"bearer","_realm":"Users"},"oauth2-client-password":{"name":"oauth2-client-password"},"anon":{"name":"anon"},"tokens":{"name":"tokens"}},"_serializers":[],"_deserializers":[],"_infoTransformers":[],"_framework":{},"_sm":{"_key":"passport"},"strategies":{},"_userProperty":"user"}},"route":{"path":"/upload","stack":[{"name":"cookieParser","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"httpMiddleware","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"corsMiddleware","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"metricsHandler","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"jsonParser","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"urlencodedParser","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"multipartParser","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"rawBodyParser","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"<anonymous>","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"},{"name":"<anonymous>","keys":[],"regexp":{"__enc__":true,"type":"regexp","data":"/^\\/?$/i"},"method":"post"}],"methods":{"post":true}},"cookies":{},"signedCookies":{},"files":[{"fieldname":"myFile","originalname":"Final Fire Alert.wav","encoding":"7bit","mimetype":"audio/wav","buffer":[82,73,70,70,194,186,18,0,87,65,86,69,102,109,116,32,16,0,0,0,1,0,1,0,68,172,0,0,136,88,1,0,2,0,16,0,100,97,116,97,52,186,18,0,211,255,11,255,197,254,49,255,25,0,253,0,82,1,230,0,227,255,238,254,145,254,38,255,81,0,115,1,167,1,185,0,251,254,152,253,161,253,151,255,139,2,85,4,43,2,223,249,97,235,26,217,246,199,155,189,158,190,97,204,100,228,117,0,240,24,236,38,190,38,21,25,82,2,44,233,216,211,115,198,177,193,144,195,117,200,12,205,102,207,80,207,233,205,136,204,247,203,46,204,121,204,69,204,143,203,230,202,47,203,187,204,0,207,174,208,68,208,57,205,150,200,9,197,36,198,219,206,41,224,102,248,122,19,85,44,147,62,0,72,57,73,25,69,94,63,68,59,52,58,226,59,171,62,217,64,114,65,158,64,63,63,97,62,92,62,224,62,18,63,95,62,236,60,160,59,173,59,148,61,148,64,100,66,23,64,19,55,150,38,19,16,40,247,68,224,63,207,242,197,215,195,116,198,157,202,182,205,156,206,168,205,24,204,30,203,53,203,248,203,146,204,102,204,135,203,183,202,218,202,70,204,108,206,221,207,63,207,32,204,191,199,244,196,60,199,77,209,198,227,138,252,96,23,43,47,239,63,226,71,30,72,160,67,52,62,164,58,31,58,250,59,149,62,98,64,169,64,203,63,174,62,44,62,104,62,210,62,161,62,117,61,200,59,192,58,142,59,94,62,237,65,138,67,251,63,6,53,84,34,56,10,196,240,170,218,105,203,70,196,246,195,146,199,188,203,46,206,51,206,159,204,233,202,63,202,210,202,249,203,179,204,101,204,80,203,92,202,129,202,7,204,49,206,122,207,144,206,47,203,232,198,186,196,31,200,127,211,5,231,31,0,104,26,233,48,15,64,184,70,68,70,254,65,63,61,147,58,142,58,104,60,143,62,191,63,177,63,225,62,58,62,64,62,196,62,1,63,73,62,126,60,147,58,222,57,125,59,73,63,105,67,200,68,18,64,83,51,218,30,141,5,253,235,194,214,20,201,132,195,95,196,88,200,70,204,32,206,159,205,211,203,60,202,207,201,152,202,188,203,78,204,225,203,218,202,38,202,164,202,71,204,53,206,217,206,57,205,122,201,163,197,198,196,46,202,148,215,116,236,182,5,199,30,51,51,14,64,250,68,233,67,252,63,85,60,175,58,58,59,235,60,107,62,234,62,133,62,242,61,229,61,148,62,71,63,55,63,189,61,71,59,51,57,8,57,215,59,203,64,136,69,90,70,0,64,224,48,28,26,105,255,186,229,194,209,24,198,167,194,5,197,146,201,53,205,83,206,20,205,244,202,111,201,102,201,144,202,233,203,119,204,237,203,211,202,63,202,223,202,166,204,95,206,162,206,126,204,138,200,10,197,67,197,52,204,57,219,33,241,128,10,165,34,103,53,118,64,3,68,100,66,189,62,222,59,5,59,2,60,166,61,172,62,179,62,1,62,141,61,225,61,238,62,202,63,140,63,164,61,226,58,178,56,241,56,61,60,165,65,62,70,66,70,136,62,211,45,239,21,199,250,182,225,250,206,221,196,192,194,204,197,116,202,186,205,92,206,217,204,165,202,77,201,98,201,138,202,181,203,18,204,117,203,148,202,82,202,76,203,0,205,83,206,204,205,251,202,224,198,16,196,219,197,221,206,194,223,198,246,250,15,205,38,128,55,118,64,148,66,115,64,60,61,58,59,58,59,151,60,7,62,141,62,1,62,29,61,212,60,150,61,10,63,3,64,127,63,50,61,15,58,244,55,148,56,130,60,69,66,154,70,159,69,57,60,213,41,163,16,49,245,207,220,153,203,62,195,151,194,114,198,43,203,6,206,28,206,54,204,253,201,204,200,39,201,95,202,129,203,172,203,4,203,53,202,65,202,115,203,64,205,66,206,72,205,246,201,217,197,153,195,172,198,56,209,142,227,68,251,63,20,240,41,254,56,104,64,124,65,22,63,62,60,227,58,111,59,242,60,40,62,58,62,84,61,95,60,71,60,104,61,13,63,2,64,50,63,147,60,85,57,117,55,157,56,9,61,225,66,153,70,67,68,30,57,22,37,235,10,133,239,43,216,152,200,0,194,157,194,27,199,193,203,44,206,205,205,164,203,116,201,116,200,237,200,46,202,28,203,49,203,129,202,246,201,85,202,197,203,123,205,8,206,92,204],"size":1227466}],"_body":true},"res":{}}

This is the output of a debug node attached to the output of the change node. The buffer has values in it and is not empty. But the payload stays empty even after the change node is supposed to be setting it.

The issue was on my end. I was working on another section of the program while I was waiting for a reply and something got out of whack and on a restart of Node-RED I now have the buffer in my payload.

But the file still isn't playable. It is creating a fire.wav file in the correct location but when I open it on the Pi using VLC or Windows using the default media player (Groove Music I think), it says the file is not playable. Upon looking at the properties the original file is 1.2MB and the uploaded file being created is 1.1MB. Not sure that makes a difference but I thought it is odd that they aren't the same.

Try a small audio clip and see what happens

This is the error I get when trying to play the file. This one is only 145KB.

image

Let me try on a Pi, I was test on my mac

I'm not sure it matters, but I am uploading from a PC running Windows 10, and I'm running Node-RED v3.0.0 on a Raspberry Pi running Bullseye.

I just tried it havng the flow on the Pi and I get an issue too. The file is 2 bytes shorter than on my Mac and just plays a hiss. So something is getting lost in the transfer.

Is there an alternate way to accomplish what I'm trying to do? The goal is to allow a user to upload a new audio file to play for an alarm scenario. I know using share folders could be a potential way but I want to remove as many steps from the user as possible.

Try this, set the Encoding to default!
encoding

Duh... :man_facepalming: I changed that when I was desparately just trying stuff. Thank you for your help.