Skip to content

Instantly share code, notes, and snippets.

@scargill
Last active May 5, 2024 19:38
Show Gist options
  • Save scargill/9676603a432f2074a91fe5ff2a88fd6e to your computer and use it in GitHub Desktop.
Save scargill/9676603a432f2074a91fe5ff2a88fd6e to your computer and use it in GitHub Desktop.
My RPI4 native audio flow
// Comments not allowed in JSON - do NOT copy these comments
// No comments in Github please - I don't visit that often
// https://tech.scargill.net/aws-polly-speech-on-rpi4-and-rpi5-using-node-red/
[
{
"id": "c75889b6.c114a8",
"type": "subflow",
"name": "Volume 0-100",
"info": "",
"in": [
{
"x": 64,
"y": 98,
"wires": [
{
"id": "228f7ec0.797752"
}
]
}
],
"out": []
},
{
"id": "bf061a13.249d78",
"type": "exec",
"z": "c75889b6.c114a8",
"command": "amixer cset numid=1 -- ",
"addpay": true,
"append": "",
"useSpawn": "",
"name": "Volume",
"x": 380,
"y": 100,
"wires": [
[],
[],
[]
]
},
{
"id": "228f7ec0.797752",
"type": "function",
"z": "c75889b6.c114a8",
"name": "Non-linear",
"func": "msg.payload/=3;\nif (msg.payload>0) msg.payload+=66;\nmsg.payload+=\"%\";\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 210,
"y": 100,
"wires": [
[
"bf061a13.249d78"
]
]
},
{
"id": "5c625079.35e59",
"type": "comment",
"z": "c75889b6.c114a8",
"name": "Amixer control for audio",
"info": "",
"x": 170,
"y": 40,
"wires": []
},
{
"id": "676931a1.872fc",
"type": "subflow:c75889b6.c114a8",
"z": "947f7b4d.ee6ef8",
"x": 770,
"y": 160,
"wires": []
},
{
"id": "1738bb65.3471d5",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "50%",
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"payload": "50",
"payloadType": "str",
"x": 570,
"y": 180,
"wires": [
[
"676931a1.872fc"
]
]
},
{
"id": "10e04ec3.32a121",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "25%",
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"payload": "25",
"payloadType": "str",
"x": 570,
"y": 140,
"wires": [
[
"676931a1.872fc"
]
]
},
{
"id": "8f283f57.3b399",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "Red Alert",
"repeat": "",
"crontab": "",
"once": false,
"topic": "amy",
"payload": "red alert",
"payloadType": "str",
"x": 980,
"y": 100,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "2b461c2.7bd40e4",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "Comms beep",
"props": [
{
"p": "payload",
"v": "comms beep",
"vt": "str"
},
{
"p": "topic",
"v": "amy",
"vt": "string"
}
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "amy",
"payload": "comms beep",
"payloadType": "str",
"x": 990,
"y": 140,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "e928e8.25ad7718",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "Hailing frequencies open",
"repeat": "",
"crontab": "",
"once": false,
"topic": "amy",
"payload": "hailing frequencies open",
"payloadType": "str",
"x": 1030,
"y": 180,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "2d98b3aa.d7284c",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "Keypress",
"props": [
{
"p": "payload",
"v": "keypress",
"vt": "str"
},
{
"p": "topic",
"v": "amy",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "amy",
"payload": "keypress",
"payloadType": "str",
"x": 980,
"y": 220,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "b0d13aff.e60fd8",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "Unable to comply",
"props": [
{
"p": "payload",
"v": "unable to comply",
"vt": "str"
},
{
"p": "topic",
"v": "amy",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "amy",
"payload": "unable to comply",
"payloadType": "str",
"x": 1000,
"y": 260,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "7e2cec04.b03ee4",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "0%",
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"payload": "0",
"payloadType": "str",
"x": 570,
"y": 100,
"wires": [
[
"676931a1.872fc"
]
]
},
{
"id": "e4d915f1.5aaea8",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "100%",
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"payload": "100",
"payloadType": "str",
"x": 570,
"y": 260,
"wires": [
[
"676931a1.872fc"
]
]
},
{
"id": "b98733e4.20171",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "75%",
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"payload": "75",
"payloadType": "str",
"x": 570,
"y": 220,
"wires": [
[
"676931a1.872fc"
]
]
},
{
"id": "3134692e.250326",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "Wind Chimes One",
"props": [
{
"p": "payload",
"v": "wind chimes one",
"vt": "str"
},
{
"p": "topic",
"v": "amy",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "amy",
"payload": "wind chimes one",
"payloadType": "str",
"x": 1011,
"y": 301,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "94bb09db.a9bad8",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "100%",
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": "1",
"topic": "",
"payload": "100",
"payloadType": "str",
"x": 130,
"y": 80,
"wires": [
[
"4e7da40d.4cef4c"
]
]
},
{
"id": "4e7da40d.4cef4c",
"type": "subflow:c75889b6.c114a8",
"z": "947f7b4d.ee6ef8",
"x": 300,
"y": 80,
"wires": []
},
{
"id": "14222a13.e6f206",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "thunder",
"props": [
{
"p": "payload",
"v": "thunder",
"vt": "str"
},
{
"p": "topic",
"v": "amy",
"vt": "string"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": "",
"topic": "amy",
"payload": "thunder",
"payloadType": "str",
"x": 970,
"y": 60,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "7f84915b.077af",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "amy",
"payload": "dogs barking",
"payloadType": "str",
"x": 1010,
"y": 340,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "1ec9a4f724dff8c4",
"type": "exec",
"z": "947f7b4d.ee6ef8",
"command": "sudo mpg123",
"addpay": true,
"append": "",
"useSpawn": "",
"timer": "",
"oldrc": false,
"name": "Mp3 player",
"x": 1610,
"y": 220,
"wires": [
[
"2cc43b1538cd8d17"
],
[],
[]
]
},
{
"id": "e8f1df220b9a0e3b",
"type": "function",
"z": "947f7b4d.ee6ef8",
"name": "Clr creating",
"func": "global.set(\"create_speech_busy\",0);\nmsg.payload=\"\";\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 1450,
"y": 80,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "c6b58278606d97a5",
"type": "function",
"z": "947f7b4d.ee6ef8",
"name": "process text",
"func": "if (typeof context.arr == \"undefined\" || !(context.arr instanceof Array)) context.arr = [];\nif (typeof global.get(\"speech_busy\") == \"undefined\") global.set(\"speech_busy\", 0);\nif (typeof global.get(\"create_speech_busy\") == \"undefined\") global.set(\"create_speech_busy\", 0);\n\nif (msg.payload !== \"\") context.arr.push(msg.payload);\nif (context.arr.length) {\n msg.payload = context.arr.shift();\n if (msg.payload.indexOf(\".mp3\") == -1) {\n var fs = global.get(\"fs\");\n var mess = msg.payload;\n mess = mess.replace(/'/g, \"\");\n var messfile = mess.toLowerCase();\n messfile = messfile.replace(/[.,\\/#!$%\\^&\\*;:{}=\\-_`~()]/g, \"\");\n messfile = messfile.replace(/ /g, \"_\");\n messfile = \"/home/pi/audio/\" + messfile + \".mp3\";\n\n if (fs.existsSync(messfile)) {\n if (global.get(\"speech_busy\")==1) { context.arr.unshift(msg.payload); return [null, null]; }\n else { global.set(\"speech_busy\", 1); msg.payload = messfile; return [null, msg]; }\n }\n else {\n if (global.get(\"create_speech_busy\")==1) { context.arr.unshift(msg.payload); return [null, null]; } else\n {\n context.arr.unshift(msg.payload);\n global.set(\"create_speech_busy\",1);\n var voice = \"Amy\";\n msg.payload = 'polly synthesize-speech --engine \"neural\" --region eu-west-2 --output-format mp3 --voice-id ' + voice + ' --text \"' + mess + '\" ' + messfile;\n return [msg, null];\n }\n }\n }\n if (global.get(\"speech_busy\")==1) context.arr.unshift(msg.payload); \n else { global.set(\"speech_busy\", 1); return [null, msg]; } // mp3 or synth \n}\n",
"outputs": "2",
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1430,
"y": 180,
"wires": [
[
"f26c3a4e0246fb10"
],
[
"1ec9a4f724dff8c4"
]
]
},
{
"id": "2cc43b1538cd8d17",
"type": "function",
"z": "947f7b4d.ee6ef8",
"name": "Clr playing",
"func": "global.set(\"speech_busy\",0);\nmsg.payload=\"\"; return msg;",
"outputs": "1",
"noerr": 0,
"x": 1450,
"y": 300,
"wires": [
[
"c6b58278606d97a5"
]
]
},
{
"id": "f26c3a4e0246fb10",
"type": "exec",
"z": "947f7b4d.ee6ef8",
"command": "aws",
"addpay": "payload",
"append": "",
"useSpawn": "false",
"timer": "",
"winHide": false,
"name": "aws create",
"x": 1610,
"y": 160,
"wires": [
[
"e8f1df220b9a0e3b"
],
[],
[]
]
},
{
"id": "af813dae06f48d2e",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "Power up clear speech busy",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 200,
"y": 40,
"wires": [
[
"dc4cc669d013eb9f"
]
]
},
{
"id": "dc4cc669d013eb9f",
"type": "function",
"z": "947f7b4d.ee6ef8",
"name": "Clr creating",
"func": "global.set(\"create_speech_busy\",0);\nglobal.set(\"speech_busy\",0);",
"outputs": 0,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 40,
"wires": []
},
{
"id": "a46305c0988fdf5e",
"type": "inject",
"z": "947f7b4d.ee6ef8",
"name": "new",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "amy",
"payload": "new speech",
"payloadType": "str",
"x": 1250,
"y": 340,
"wires": [
[
"c6b58278606d97a5"
]
]
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment