Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Ability to use a script for TTS. #86

Closed
Chaotic opened this issue Feb 19, 2019 · 8 comments
Closed

[Feature Request] Ability to use a script for TTS. #86

Chaotic opened this issue Feb 19, 2019 · 8 comments
Labels
enhancement New feature or request

Comments

@Chaotic
Copy link

Chaotic commented Feb 19, 2019

I'd love if I could have the TTS function call the sonos_says script so that it would resume any music that happened to be playing on the sonos.

I'm not sure how challenging this change would be through.

@kalkih
Copy link
Owner

kalkih commented Feb 19, 2019

Hmm, I'm not sure how well that would work, seems like you need to specify a delay (basically how long the tts message is and when to resume playback, I guess?). This works ok for predefined messages.

Not sure how we would calculate the delay, and if we set a predefined delay, messages could get cut off, etc.

@kalkih kalkih added the enhancement New feature or request label Feb 19, 2019
@Chaotic
Copy link
Author

Chaotic commented Feb 19, 2019

It looks like there is a way to have the script calc the delay but I haven't tested that out yet.

https://community.home-assistant.io/t/sonos-tts-script/8896/21

I'll play around with it and see if I can get it to actually work and report back.

@kalkih
Copy link
Owner

kalkih commented Feb 19, 2019

Cool, thanks, should be easy to implement if the delay is calculated correctly.

@Chaotic
Copy link
Author

Chaotic commented Feb 20, 2019

Yeah that code seems to calculate the delay correctly

sonos_say:
  alias: "Sonos TTS script"
  sequence:
    - service: media_player.sonos_snapshot
      data_template:
        entity_id: "{{ 'media_player.' ~ sonos_entity }}"
    - service: media_player.sonos_unjoin
      data_template:
        entity_id:  "{{ 'media_player.' ~ sonos_entity }}"
    - service: media_player.volume_set
      data_template:
        entity_id:  "{{ 'media_player.' ~ sonos_entity }}"
        volume_level: "{{ volume }}"
    - service: tts.google_say
      data_template:
        entity_id:  "{{ 'media_player.' ~ sonos_entity }}"
        message: "{{ message }}"
    - delay: '00:00:01'
    - delay: >-
        {% set duration = states.media_player[sonos_entity].attributes.media_duration %}
        {% if duration > 0 %}
          {% set duration = duration - 1 %}
        {% endif %}
        {% set seconds = duration % 60 %}
        {% set minutes = (duration / 60)|int % 60 %}
        {% set hours = (duration / 3600)|int %}
        {{ [hours, minutes, seconds]|join(':') }}
    - service: media_player.sonos_restore
      data_template:
        entity_id:  "{{ 'media_player.' ~ sonos_entity }}"

That's the code I ended up using only difference from the one in the link is it takes a volume input too.

I'd think the TTS from your card could just pass along whatever volume the player is set to.

@kalkih
Copy link
Owner

kalkih commented Mar 7, 2019

Now available with the latest release, wasn't able to actually test it since I don't own any sonos devices. Let me now if you have any issues.

# example
- type: custom:mini-media-player
  entity: media_player.example
  tts:
    platform: sonos
    volume: 0.75 # volume level for tts

@kalkih kalkih closed this as completed Mar 7, 2019
@sandman32
Copy link

FYI the script listed here wasn't working for me, it wouldn't resume after the TTS message was delivered. However this script worked. I got it from arsaboo here: https://github.com/arsaboo/homeassistant-config/blob/master/scripts.yaml . I then modified it to list one of my Sonos devices instead of the device he listed, and I increased the first delay from 00:00:00 to 00:00:01. 00:00:00 was cutting off my tts message.

    alias: "Sonos TTS script"
    sequence:
      - service: media_player.sonos_snapshot
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"
      - service: media_player.sonos_unjoin
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"
      - service: media_player.volume_set
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"
          volume_level: "{{ volume|default(0.5) }}"
      - service: tts.google_say
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"
          message: "{{ message }}"
      - delay: "{{ delay|default('00:00:01') }}"
      - wait_template: "{{ is_state(sonos_entity|default('media_player.family_room'), 'playing') }}"
        timeout: '00:00:05'
      - service: media_player.sonos_restore
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"     ```

@sandman32
Copy link

Sorry that was actually cutting off my tts message if it was longer than a few seconds. This seems to be the correct answer.

sonos_say:
    alias: "Sonos TTS script"
    sequence:
      - service: media_player.sonos_snapshot
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"
      - service: media_player.sonos_unjoin
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"
      - service: media_player.volume_set
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"
          volume_level: "{{ volume|default(0.5) }}"
      - service: tts.google_say
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"
          message: "{{ message }}"
      - delay: "{{ delay|default('00:00:01') }}"
      - wait_template: "{{ is_state(sonos_entity|default('media_player.family_room'), 'playing') }}"
        timeout: '00:00:03'
      - wait_template: "{{ not is_state(sonos_entity|default('media_player.family_room'), 'playing') }}"
        timeout: '00:01:00'        
      - service: media_player.sonos_restore
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.family_room') }}"

@Royal2000H
Copy link

Sorry to revive such an old topic. This is a new solution to help future readers because of the breaking change in HA 0.93 that changed sonos services to the sonos domain (Ex: media_player.sonos_snapshot to sonos.snapshot)

In regards to the above, @Chaotic's script actually worked just fine for me after some tweaks. @sandman32's works fine too after tweaks. They work similarly - the former waits a second, finds the duration of the currently playing item (the tts), sets the delay to that length, waits the delay, then resumes audio. The latter waits a second, makes sure something (the tts) is playing, then waits until that something (the tts) stops playing - upto 1 minute, then resumes audio.
In other words, they're very similar. They have similar performance in my limited experience testing both. @Chaotic's might be more flexible because of the lack of the 1 minute timeout, though that too can be adjusted. But if it doesn't work for you, you can use @sandman32's.

Note: Neither will resume playback of music you play through Spotify app onto your Sonos speaker (Spotify Connect) because the Sonos API has no way that I can find to restart that.

Here are the edited versions of both that have both been tested with HA 0.107.7 and Mini Media Player 1.7.0.

@Chaotic's version (I fixed the domains and also fixed the sonos_entity to assume "media_player." is being passed in the entity name). I chose to use this one.

sonos_say:
    alias: "Sonos TTS script"
    sequence:
    - service: sonos.snapshot
      data_template:
        entity_id: "{{ sonos_entity }}"
    - service: sonos.unjoin
      data_template:
        entity_id:  "{{ sonos_entity }}"
    - service: media_player.volume_set
      data_template:
        entity_id:  "{{ sonos_entity }}"
        volume_level: "{{ volume }}"
    - service: tts.google_say
      data_template:
        entity_id:  "{{ sonos_entity }}"
        message: "{{ message }}"
    - delay: '00:00:01'
    - delay: >-
        {% set duration = states[sonos_entity].attributes.media_duration %}
        {% if duration > 0 %}
          {% set duration = duration - 1 %}
        {% endif %}
        {% set seconds = duration % 60 %}
        {% set minutes = (duration / 60)|int % 60 %}
        {% set hours = (duration / 3600)|int %}
        {{ [hours, minutes, seconds]|join(':') }}
    - service: sonos.restore
      data_template:
        entity_id:  "{{ sonos_entity }}"

@sandman32's version (I fixed the domains and also removed the defaults referencing a random speaker because they are irrelevant)

sonos_say:
    alias: "Sonos TTS script"
    sequence:
      - service: sonos.snapshot
        data_template:
          entity_id: "{{ sonos_entity }}"
      - service: sonos.unjoin
        data_template:
          entity_id: "{{ sonos_entity }}"
      - service: media_player.volume_set
        data_template:
          entity_id: "{{ sonos_entity }}"
          volume_level: "{{ volume|default(0.5) }}"
      - service: tts.google_say
        data_template:
          entity_id: "{{ sonos_entity }}"
          message: "{{ message }}"
      - delay: "{{ delay|default('00:00:01') }}"
      - wait_template: "{{ is_state(sonos_entity, 'playing') }}"
        timeout: '00:00:03'
      - wait_template: "{{ not is_state(sonos_entity, 'playing') }}"
        timeout: '00:01:00'        
      - service: sonos.restore
        data_template:
          entity_id: "{{ sonos_entity }}"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants