How to change volume tts.google_say nodered

Tags: #<Tag:0x00007f739028f130>

I am doing some work on my home alarm in nodered. I have google home unit around the house which I make announcements to using the tts.google_say all is working well, however I want to be able to set the volume level when making the announcement to say 70%.


One of my TTS’s

I tried this but it fails.
Annotation%202019-06-22%20160358

I have spent last 2 hours searching forum and google with no luck. All the posts are for doing it in automations.yaml but not nodered.

I think the Google home uses the same volume for music and speech. So you can use media_player.vo!ume_set in a separate call first.

I do something similar for announcements. You can also get the current volume first and set it back afterwards.

That was easy. I just did it. Here is my test layout and code.

[{"id":"f664be79.a8d76","type":"api-call-service","z":"6effacd4.c3c434","name":"TTS - Garage","server":"31325ed1.2c0d02","service_domain":"media_player","service":"volume_set","data":"{\"entity_id\":\"media_player.googlehome0059\",\"volume_level\":\"0.1\"}","mergecontext":"","output_location":"payload","output_location_type":"msg","mustacheAltTags":false,"x":1400,"y":720,"wires":[[]]},{"id":"78ed7b03.0a06e4","type":"inject","z":"6effacd4.c3c434","name":"","topic":"","payload":"on","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1210,"y":680,"wires":[["f664be79.a8d76","98183a11.7dab38"]]},{"id":"98183a11.7dab38","type":"api-call-service","z":"6effacd4.c3c434","name":"TTS - Garage","server":"31325ed1.2c0d02","service_domain":"tts","service":"google_say","data":"{\"entity_id\":\"media_player.googlehome0059\",\"message\":\"Volume 10%\"}","mergecontext":"","output_location":"payload","output_location_type":"msg","mustacheAltTags":false,"x":1400,"y":660,"wires":[[]]},{"id":"31325ed1.2c0d02","type":"server","z":"","name":"HA - Default","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true}]

Screenshot_1


This is certainly something that would be handy, any ideas on what domain/service that function might be hiding around a keyword will make it easier to hunt down.

You could use a current state node to get the volume before you change it, store it in the message and set it back at the end with another volume_set.

You can see the volume in the debug message, you can use it by using {{data.attributes.volume_level}} instead of the fixed 0.1 value in the second volume_set.

How did you get the data in the debug window. Using my google home I threw a debug node on the output

  1. Deployed
  2. Cast some music to google home

and my debug window draws a blank. My google homes are working in nodered with other flows as I use them on tts google_say.

Here is my flow that I use for numerous announcements and the alarm:

  1. Check current volume. If not desired volume, then set it to that volume.
  2. Log the previous volume.
  3. Reinstate previous volume after a set “wait” or a “delay” node.

[{"id":"eead7d9d.051e","type":"api-call-service","z":"f9a8a8ea.c4b0f8","name":"Set volume to 100%","server":"1b36a1cc.1e72ee","service_domain":"media_player","service":"volume_set","data":"{\"entity_id\":\"media_player.bedroom_speaker\",\"volume_level\":1}","mergecontext":"","output_location":"payload","output_location_type":"msg","mustacheAltTags":false,"x":1780,"y":880,"wires":[[]]},{"id":"4494668b.223168","type":"switch","z":"f9a8a8ea.c4b0f8","name":"100%?","property":"data.attributes.volume_level","propertyType":"msg","rules":[{"t":"neq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":1430,"y":880,"wires":[["eead7d9d.051e","e39c7d3f.4ab0b"]]},{"id":"389f0326.13fb6c","type":"api-current-state","z":"f9a8a8ea.c4b0f8","name":"Bedroom Speaker","server":"1b36a1cc.1e72ee","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":true,"entity_id":"media_player.bedroom_speaker","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":1250,"y":880,"wires":[["4494668b.223168"]]},{"id":"e39c7d3f.4ab0b","type":"function","z":"f9a8a8ea.c4b0f8","name":"","func":"msg.payload =\n{\n    \"data\":{\n      \"entity_id\":\"media_player.bedroom_speaker\",\n      \"volume_level\": msg.data.attributes.volume_level\n    }\n}\nreturn msg;","outputs":1,"noerr":0,"x":1430,"y":940,"wires":[["4f516e52.57f07"]]},{"id":"c1afee90.99e03","type":"api-call-service","z":"f9a8a8ea.c4b0f8","name":"Set volume to Previous","server":"1b36a1cc.1e72ee","service_domain":"media_player","service":"volume_set","data":"{}","mergecontext":"","output_location":"payload","output_location_type":"msg","mustacheAltTags":false,"x":1790,"y":940,"wires":[[]]},{"id":"4f516e52.57f07","type":"ha-wait-until","z":"f9a8a8ea.c4b0f8","name":"","server":"1b36a1cc.1e72ee","outputs":1,"entityId":"alarm_control_panel.house","property":"state","comparator":"is","value":"disarmed","valueType":"str","timeout":0,"timeoutUnits":"seconds","entityLocation":"","entityLocationType":"none","checkCurrentState":true,"x":1580,"y":940,"wires":[["c1afee90.99e03"]]},{"id":"1b36a1cc.1e72ee","type":"server","z":"","name":"Home Assistant","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true}]

[{"id":"f9af48c9.471648","type":"api-call-service","z":"63ea4fd.14ed3b","name":"Set volume to 50%","server":"1b36a1cc.1e72ee","service_domain":"media_player","service":"volume_set","data":"{\"entity_id\": \"media_player.living_room_speaker\", \"volume_level\": 0.5 }","mergecontext":"","x":1570,"y":480,"wires":[[]]},{"id":"37589482.af76bc","type":"switch","z":"63ea4fd.14ed3b","name":"50% ?","property":"data.attributes.volume_level","propertyType":"msg","rules":[{"t":"neq","v":"0.5","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":1370,"y":540,"wires":[["f9af48c9.471648","b2037777.2d64a8"]]},{"id":"45c120d4.e132c","type":"api-current-state","z":"63ea4fd.14ed3b","name":"Speaker","server":"1b36a1cc.1e72ee","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":true,"entity_id":"media_player.living_room_speaker","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":1220,"y":540,"wires":[["37589482.af76bc"]]},{"id":"b2037777.2d64a8","type":"function","z":"63ea4fd.14ed3b","name":"","func":"msg.payload =\n{\n    \"data\":{\n      \"entity_id\":\"media_player.living_room_speaker\",\n      \"volume_level\": msg.data.attributes.volume_level\n    }\n}\nreturn msg;","outputs":1,"noerr":0,"x":1510,"y":540,"wires":[["76f78e06.d0958"]]},{"id":"76f78e06.d0958","type":"delay","z":"63ea4fd.14ed3b","name":"","pauseType":"delay","timeout":"6","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1640,"y":540,"wires":[["1d043b26.2af975"]]},{"id":"1d043b26.2af975","type":"api-call-service","z":"63ea4fd.14ed3b","name":"Set volume to Previous","server":"1b36a1cc.1e72ee","service_domain":"media_player","service":"volume_set","data":"{}","mergecontext":"","x":1830,"y":540,"wires":[[]]},{"id":"1b36a1cc.1e72ee","type":"server","z":"","name":"Home Assistant","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true}]
3 Likes

Works a charm, pretty simply to follow.

For anyone reading. The difference between the two examples is the top flow waits for state change (eg the alarm changes to disarm) and then returns volume back.

Whereas the bottom group just has a timer delay (eg 6 seconds) before returning the volume.

I put my output ie Google Home Speaker on the ‘Set volume to… 100%’ service node.

I will roll this out pretty much anywhere I have an announcement in my NodeRed :smiley:.

Here’s my change
Screenshot_3
Before. TTS announcement plays at whatever level speaker is currently set too.


Modified node set to include @onkytonk which now turns up volume to 70% for 5seconds whilst TTS is reading out the announcement to intruder and then goes back to original volume level.

2 Likes

If you’re going to be using this sequence quite regularly, I’d suggest converting it into a subflow.
This will allow you to only have to insert a single “subflow” node whenever you require it. :slight_smile:

You can then access the subflow directly from your palette.

  1. Select all the nodes in the sequence required:

  1. Create subflow from selected nodes:

  1. The subflow is now accesible in your pallete.
    Double click it to access it or make any changes.
    I renamed it to “Volume Adjustment”.

  1. Now you can insert it anywhere you wish, and its much neater!

  1. BONUS STEP:
    Create duplicate subflows with different volume settings.

4 Likes

Great tip… Another one I will implement!!

why do you not use a NR node to directly send the announcement to your google home?

like

I did originally try Cast when I purchased my first Google home and alot more green to NR but I couldn’t get the text to speech to work.

Looking at it again I can see that the quick start guide has been added to now giving examples and I can see now I just needed to put the text on the incoming payload and she/it will read out the incoming payload.

For what I need at the moment in my Alarm flow the TTS with google say and with the added volume level control and return to previous level shown by @onkytonk it is functioning perfectly.

I can see now you have mentioned it that Cast node with more notes looks like its worth having look over and see what features I can adopt for other areas of my node red.

Is there a way, I can wait until TTS finished?
Unfortunately, the flow continues and I have no information when the Say command finished.
The only possible solution I found so far is to set a predefined delay.
But since I want to output a dynamic text which can be either 10 characters long or 200, the duration varies and I cannot simply set a fix delay.

I tried to wait until the media_player_mpd turns “off” which it does sometimes after TTS finished, but not always. And then the volume stays high.

Just because I’m curious, I also can’t get the debug info in the detailed way… how do I get all the info?

Not sure if this helps

  1. Drag out the Debug node
  2. Connect the debug node to where you want to intercept data.
  3. Run your flow so data flows through your circuit you want to see.
  4. In the debug window on the right side you should see the data.
  5. Note some of the data needs to be expanded with the arrows such as my Xiaomi buttons when I click on them.

Hey mate, sorry it’s been awhile, just checking…

Does your original flow still work for you with setting the volume back to the original volume?

I glued a Xiaomi push button next to my front door as door bell and using it to play doorbell mp3s on my google homes.

It sets the volume fine but doesn’t return the volume to the previous volume.

[{"id":"219d9dc2.09e732","type":"debug","z":"d1ff6d76.b90a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":2430,"y":1600,"wires":[]},{"id":"3a0c0487.a8836c","type":"cast-to-client","z":"d1ff6d76.b90a8","name":"Playroom","url":"http://192.168.86.229:8123/local/doorbell.mp3","contentType":"audio","message":"","language":"en","ip":"192.168.86.40","port":"","volume":"","x":2360,"y":1680,"wires":[[]]},{"id":"5401f546.dec15c","type":"api-call-service","z":"d1ff6d76.b90a8","name":"Set volume to 20%","server":"a661f859.8644a8","version":1,"debugenabled":false,"service_domain":"media_player","service":"volume_set","entityId":"media_player.googlehome4405","data":"{\"volume_level\":0.2}","dataType":"json","mergecontext":"","output_location":"payload","output_location_type":"msg","mustacheAltTags":false,"x":1910,"y":1600,"wires":[["ada484de.1a9d58"]]},{"id":"4f748a5f.6c30c4","type":"switch","z":"d1ff6d76.b90a8","name":"20%?","property":"data.attributes.volume_level","propertyType":"msg","rules":[{"t":"neq","v":"0.2","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":1610,"y":1600,"wires":[["5bec789d.b19d48","5401f546.dec15c"]]},{"id":"5a1e3c83.7c7e24","type":"api-current-state","z":"d1ff6d76.b90a8","name":"Playroom Speaker","server":"a661f859.8644a8","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":true,"entity_id":"media_player.googlehome4405","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":1430,"y":1600,"wires":[["4f748a5f.6c30c4"]]},{"id":"5bec789d.b19d48","type":"function","z":"d1ff6d76.b90a8","name":"","func":"msg.payload =\n{\n    \"data\":{\n      \"entity_id\":\"media_player.garage_speaker\",\n      \"volume_level\": msg.data.attributes.volume_level\n    }\n}\nreturn msg;","outputs":1,"noerr":0,"x":1610,"y":1660,"wires":[["422b3aef.040814"]]},{"id":"98acbd33.2546c","type":"api-call-service","z":"d1ff6d76.b90a8","name":"Set volume to Previous","server":"a661f859.8644a8","version":1,"debugenabled":false,"service_domain":"media_player","service":"volume_set","entityId":"media_player.googlehome4405","data":"{}","dataType":"json","mergecontext":"","output_location":"payload","output_location_type":"msg","mustacheAltTags":false,"x":1970,"y":1660,"wires":[[]]},{"id":"ada484de.1a9d58","type":"change","z":"d1ff6d76.b90a8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":2132,"y":1599,"wires":[["3a0c0487.a8836c","219d9dc2.09e732"]]},{"id":"422b3aef.040814","type":"delay","z":"d1ff6d76.b90a8","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1760,"y":1660,"wires":[["98acbd33.2546c"]]},{"id":"a661f859.8644a8","type":"server","z":"","name":"HA - Default","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true}]

ps I chose the cast node at the end as I am using .mp3 rather than tts.

Hey bud,
I’ve been out of the home assistant scene for a while, since we were waiting for our new home to be built. Got HA up and running last week but haven’t implemented any major automations yet, so can’t say if these are working for me or not.
If I get a chance to experiment, I’ll let you know.

Hey,

Did you ever find a solution for this?
I am in need of the exact same thing myself.

I have tried checking for state change to identify when the TTS is done, but I cannot seem to find any clear identification for this.

Unfortunately not. I stopped searching for a soluation short after, but I would definitely be thankful for any ideas.

Allright, good to know.

My plan B now is to try a couple of different messages with different lengths and try to extrapolate the average speech length for a certain length in the message string.
This will obviously vary with different voices and languages, as well as what TTS engine, being used, but I don’t know any other way. I also think it might work well enough, especially if one add a small static delay of 500 milliseconds after the calculated speech length as a buffer.

I’ll make sure to post my flow here when I have tried my hand at this.