# Nodered Text-to-Speech in Windows

**URL:** <https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395>\
**Category:** General\
**Created:** [22 September 2021 14:26 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395 "2021-09-22T14:26:13Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![sergiobaiao](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sergiobaiao/32/46997_2.png) [@sergiobaiao](https://discourse.nodered.org/u/sergiobaiao)\
**Post date:** [22 September 2021 14:26 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/1 "2021-09-22T14:26:13Z")

</div>

Hi there guys,

I'm trying to setup a simple text-to-speech function in Windows using powershell, but i'm somehow failing miserably.

I've managed to create a flow that works:

```auto
[
    {
        "id": "8fc0ac7099b7175f",
        "type": "change",
        "z": "73264e222aeaf471",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "\"powershell -NoProfile -command \\\"Add-Type -AssemblyName System.speech; $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.SpeakSsml(\" & $.payload & \")\\\"\"",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 520,
        "y": 320,
        "wires": [
            [
                "d0814fabfbee02ef"
            ]
        ]
    },
    {
        "id": "d0814fabfbee02ef",
        "type": "exec",
        "z": "73264e222aeaf471",
        "command": "",
        "addpay": "payload",
        "append": "",
        "useSpawn": "",
        "timer": "",
        "winHide": false,
        "name": "TTS",
        "x": 750,
        "y": 320,
        "wires": [
            [
                "ef75f9ba76381361"
            ],
            [
                "ef75f9ba76381361"
            ],
            [
                "ef75f9ba76381361"
            ]
        ]
    },
    {
        "id": "ef75f9ba76381361",
        "type": "debug",
        "z": "73264e222aeaf471",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "false",
        "x": 950,
        "y": 320,
        "wires": []
    },
    {
        "id": "84d2cfb3f19d50b9",
        "type": "inject",
        "z": "73264e222aeaf471",
        "name": "",
        "props": [
            {
                "p": "payload",
                "v": "",
                "vt": "str"
            },
            {
                "p": "topic",
                "v": "",
                "vt": "string"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "str",
        "x": 170,
        "y": 320,
        "wires": [
            [
                "ca096792549bd376"
            ]
        ]
    },
    {
        "id": "ca096792549bd376",
        "type": "template",
        "z": "73264e222aeaf471",
        "name": "set payload",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "plain",
        "template": "'<speak version=\\\"1.0\\\" xmlns=\\\"http://www.w3.org/2001/10/synthesis\\\" xml:lang=\\\"pt-BR\\\"><voice name=\\\"pt-BR-FranciscaNeural\\\"><prosody rate=\\\"1\\\"><p><prosody pitch=\\\"x-high\\\"> Testing TTS </prosody></p></prosody></voice></speak>'",
        "output": "str",
        "x": 330,
        "y": 320,
        "wires": [
            [
                "8fc0ac7099b7175f"
            ]
        ]
    }
]

```

But this has the message built inside the payload. I want to inject the message from another node, like an inject node, for example, but then the command fails:

```auto
[
    {
        "id": "ac2b24e822dd8318",
        "type": "exec",
        "z": "73264e222aeaf471",
        "command": "",
        "addpay": "payload",
        "append": "",
        "useSpawn": "",
        "timer": "",
        "winHide": false,
        "name": "TTS",
        "x": 750,
        "y": 440,
        "wires": [
            [
                "d22a6033c7d23a0f"
            ],
            [
                "d22a6033c7d23a0f"
            ],
            [
                "d22a6033c7d23a0f"
            ]
        ]
    },
    {
        "id": "d22a6033c7d23a0f",
        "type": "debug",
        "z": "73264e222aeaf471",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "false",
        "x": 930,
        "y": 440,
        "wires": []
    },
    {
        "id": "ef038e214b8a2065",
        "type": "change",
        "z": "73264e222aeaf471",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "\"'<speak version=\\\"1.0\\\" xmlns=\\\"http://www.w3.org/2001/10/synthesis\\\" xml:lang=\\\"pt-BR\\\"><voice name=\\\"pt-BR-FranciscaNeural\\\"><prosody rate=\\\"1\\\"><p><prosody pitch=\\\"x-high\\\"> \" & $.payload & \"</prosody></p></prosody></voice></speak>'\"",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 380,
        "y": 440,
        "wires": [
            [
                "ab199d7bb8d6aec8"
            ]
        ]
    },
    {
        "id": "7cf28b0fe0bda564",
        "type": "inject",
        "z": "73264e222aeaf471",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "Testing TTS",
        "payloadType": "str",
        "x": 190,
        "y": 440,
        "wires": [
            [
                "ef038e214b8a2065"
            ]
        ]
    },
    {
        "id": "ab199d7bb8d6aec8",
        "type": "change",
        "z": "73264e222aeaf471",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "\"powershell -NoProfile -command \\\"Add-Type -AssemblyName System.speech; $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.SpeakSsml(\" & $.payload & \")\\\"\"",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 580,
        "y": 440,
        "wires": [
            [
                "ac2b24e822dd8318"
            ]
        ]
    }
]

```

When executing this flow, it shows in the debug panel:

```auto
Exception calling "SpeakSsml" with "1" argument(s): "XML content not valid."
At line:1 char:102
+ ... ynthesizer; $speak.SpeakSsml('<speak version=1.0 xmlns=http://www.w3. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : FormatException

```

and also:

```auto
Command failed: powershell -NoProfile -command "Add-Type -AssemblyName System.speech; $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.SpeakSsml('<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="pt-BR"><voice name="pt-BR-FranciscaNeural"><prosody rate="1"><p><prosody pitch="x-high"> Testing TTS</prosody></p></prosody></voice></speak>')"
Exception calling "SpeakSsml" with "1" argument(s): "XML content not valid."
At line:1 char:102
+ ... ynthesizer; $speak.SpeakSsml('<speak version=1.0 xmlns=http://www.w3. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : FormatException

```

What am i doing wrong?

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [22 September 2021 14:48 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/2 "2021-09-22T14:48:55Z")

</div>

I am not at my PC at the moment, but the first thing to do is to add a debug node showing what is going into the node in each case. There must be a difference. If you can't see it then post the two messages here.

---

<div class="post-metadata">

**Author:** ![sergiobaiao](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sergiobaiao/32/46997_2.png) [@sergiobaiao](https://discourse.nodered.org/u/sergiobaiao)\
**Post date:** [22 September 2021 15:04 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/3 "2021-09-22T15:04:44Z")

</div>

Hi Colin,

Both nodes have a debug log. The working one doesn't show any output, but the one that's not working shows the errors i've shown in the first post.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [22 September 2021 15:12 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/4 "2021-09-22T15:12:22Z")

</div>

> [@sergiobaiao](#):
>
> The working one doesn't show any output,

In that case it isn't showing what is going _into_ the exec node.

---

<div class="post-metadata">

**Author:** ![sergiobaiao](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sergiobaiao/32/46997_2.png) [@sergiobaiao](https://discourse.nodered.org/u/sergiobaiao)\
**Post date:** [22 September 2021 15:17 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/5 "2021-09-22T15:17:55Z")

</div>

This works:

```auto
[
    {
        "id": "8fc0ac7099b7175f",
        "type": "change",
        "z": "73264e222aeaf471",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "\"powershell -NoProfile -command \\\"Add-Type -AssemblyName System.speech; $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.SelectVoice('Microsoft Daniel'); $speak.SpeakSsml(\" & $.payload & \")\\\"\"",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 520,
        "y": 320,
        "wires": [
            [
                "d0814fabfbee02ef"
            ]
        ]
    },
    {
        "id": "d0814fabfbee02ef",
        "type": "exec",
        "z": "73264e222aeaf471",
        "command": "",
        "addpay": "payload",
        "append": "",
        "useSpawn": "false",
        "timer": "",
        "winHide": false,
        "name": "TTS",
        "x": 750,
        "y": 320,
        "wires": [
            [
                "ef75f9ba76381361"
            ],
            [
                "ef75f9ba76381361"
            ],
            [
                "ef75f9ba76381361"
            ]
        ]
    },
    {
        "id": "ef75f9ba76381361",
        "type": "debug",
        "z": "73264e222aeaf471",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "false",
        "x": 950,
        "y": 320,
        "wires": []
    },
    {
        "id": "84d2cfb3f19d50b9",
        "type": "inject",
        "z": "73264e222aeaf471",
        "name": "",
        "props": [
            {
                "p": "payload",
                "v": "",
                "vt": "str"
            },
            {
                "p": "topic",
                "v": "",
                "vt": "string"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "str",
        "x": 170,
        "y": 320,
        "wires": [
            [
                "ca096792549bd376"
            ]
        ]
    },
    {
        "id": "ca096792549bd376",
        "type": "template",
        "z": "73264e222aeaf471",
        "name": "set payload",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "plain",
        "template": "'<speak version=\\\"1.0\\\" xmlns=\\\"http://www.w3.org/2001/10/synthesis\\\" xml:lang=\\\"pt-BR\\\"><voice name=\\\"pt-BR\\\"><prosody rate=\\\"1\\\"><p><prosody pitch=\\\"x-high\\\"> Testing TTS </prosody></p></prosody></voice></speak>'",
        "output": "str",
        "x": 330,
        "y": 320,
        "wires": [
            [
                "8fc0ac7099b7175f"
            ]
        ]
    }
]

```

But when i click on the inject node, it only shows this:

![Screenshot 2021-09-22 121712](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/7/9714a3e2bdc78a6faa7bf916dcad81e145352078.png)

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [22 September 2021 16:12 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/6 "2021-09-22T16:12:01Z")

</div>

Do you not understand what I mean when I say connect a debug node showing what is going into the exec node? I mean this

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/c/1c7b7ddb917f07052e41dcc6d68baf10579c881a.png)

Do that for the working and non-working and see what the difference is.

By the way, using JSONata just to insert a payload into a string (if that is what you are doing) is horribly inefficient. Use a Template node instead.

---

<div class="post-metadata">

**Author:** ![Gunner](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gunner/32/43582_2.png) [@Gunner](https://discourse.nodered.org/u/Gunner)\
**Post date:** [22 September 2021 22:22 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/7 "2021-09-22T22:22:59Z")

</div>

> [@sergiobaiao](#):
>
> I'm trying to setup a simple text-to-speech function in Windows

I just use the `ui_audio` node and it works with the browser's TTS support

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/c/ac993f93cbbd785729d3e586707ab6036db548d8.png)

```auto
[{"id":"4a9cfcb35995b223","type":"inject","z":"e152a286a73e145c","g":"fe95e26d99960854","name":"Play","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":470,"y":200,"wires":[["bd2b5049605f09d1"]]},{"id":"bd2b5049605f09d1","type":"ui_button","z":"e152a286a73e145c","g":"fe95e26d99960854","name":"","group":"a7ee5c63.381f8","order":1,"width":0,"height":0,"passthru":true,"label":"OK, OK, I am speaking","tooltip":"","color":"","bgcolor":"","icon":"","payload":"\"OK, OK, I am speaking\"","payloadType":"str","topic":"topic","topicType":"msg","x":540,"y":240,"wires":[["f2c3327bec1fb7d4"]]},{"id":"545c506dc2fe1bcd","type":"inject","z":"e152a286a73e145c","g":"fe95e26d99960854","name":"Reset","props":[{"p":"reset","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":470,"y":280,"wires":[["f2c3327bec1fb7d4"]]},{"id":"f2c3327bec1fb7d4","type":"ui_audio","z":"e152a286a73e145c","g":"fe95e26d99960854","name":"","group":"a7ee5c63.381f8","voice":"Google UK English Female","always":true,"x":500,"y":320,"wires":[]},{"id":"a7ee5c63.381f8","type":"ui_group","name":"Speech","tab":"bb93b1da.ab821","order":2,"disp":true,"width":"6","collapse":false},{"id":"bb93b1da.ab821","type":"ui_tab","name":"Tests","icon":"build","order":11,"disabled":false,"hidden":false}]

```

---

<div class="post-metadata">

**Author:** ![sergiobaiao](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sergiobaiao/32/46997_2.png) [@sergiobaiao](https://discourse.nodered.org/u/sergiobaiao)\
**Post date:** [23 September 2021 11:19 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/8 "2021-09-23T11:19:52Z")

</div>

this is a browser independent setup...it must always work, not only when a browser is open

---

<div class="post-metadata">

**Author:** ![sergiobaiao](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sergiobaiao/32/46997_2.png) [@sergiobaiao](https://discourse.nodered.org/u/sergiobaiao)\
**Post date:** [23 September 2021 11:25 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/9 "2021-09-23T11:25:34Z")

</div>

sorry about that, i really didn't understand before...  
here is the output from the working node:

```auto
powershell -NoProfile -command "Add-Type -AssemblyName System.speech; $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.SelectVoice('Microsoft Daniel'); $speak.SpeakSsml('<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"pt-BR\"><voice name=\"pt-BR\"><prosody rate=\"1\"><p><prosody pitch=\"x-high\"> Testing TTS </prosody></p></prosody></voice></speak>')"

```

and here from the non-working node (it differs because the other part of the command is in the exec node, but the xml inside is supposed to be the same):

```auto
<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="en-US">
    <voice name="pt-BR-AntonioNeural">
        <prosody rate="0%" pitch="0%">Testing!</prosody>
</voice>
</speak>

```

and also:

```auto
The string is missing the terminator: '.
    + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

```

```auto
{"code":1,"message":"Command failed: powershell -NoProfile -command \"Add-Type -AssemblyName System.speech; $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.SpeakSsml(' <speak xmlns=\"http://www.w3.org/2001/10/synthesis\" xmlns:mstts=\"http://www.w3.org/2001/mstts\" xmlns:emo=\"http://www.w3.org/2009/10/emotionml\" version=\"1.0\" xml:lang=\"en-US\">\n <voice name=\"pt-BR-AntonioNeural\">\n <prosody rate=\"0%\" pitch=\"0%\">Testing!!</prosody>\n</voice>\n</speak> ')\"\nThe string is missing the terminator: '.\r\n + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException\r\n ..."}

```

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [23 September 2021 15:22 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/10 "2021-09-23T15:22:18Z")

</div>

Is it valid to have new lines in the xml in the powershell command?

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [23 September 2021 15:28 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/11 "2021-09-23T15:28:50Z")

</div>

Also, show us how you have configured the exec node in the non-working case.

---

<div class="post-metadata">

**Author:** ![Gunner](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gunner/32/43582_2.png) [@Gunner](https://discourse.nodered.org/u/Gunner)\
**Post date:** [23 September 2021 20:35 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/12 "2021-09-23T20:35:50Z")

</div>

> [@sergiobaiao](#):
>
> it must always work, not only when a browser is open

Got it. My browser is ALWAYS open on anything I have Node-Red working with (displays & controls, etc), so "simply works" is good'nuf for me.

---

<div class="post-metadata">

**Author:** ![mickeycumt](https://avatars.discourse-cdn.com/v4/letter/m/278dde/32.png) [@mickeycumt](https://discourse.nodered.org/u/mickeycumt)\
**Post date:** [19 October 2021 08:30 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/13 "2021-10-19T08:30:48Z")

</div>

Hi Gunner,

Could you kindly share the download link for the brower's TTS support?

---

<div class="post-metadata">

**Author:** ![Gunner](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gunner/32/43582_2.png) [@Gunner](https://discourse.nodered.org/u/Gunner)\
**Post date:** [20 October 2021 01:12 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/14 "2021-10-20T01:12:19Z")

</div>

There was no "link" to provide... I use Chrome and it "just worked" with the `ui_audio` node.

Note: even though there is no actual "visible" widget in the dashboard for this node, the dashboard must be open for it to work.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [19 December 2021 01:12 UTC](https://discourse.nodered.org/t/nodered-text-to-speech-in-windows/51395/15 "2021-12-19T01:12:35Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
