Combine two media players on condition

Hi,

I’m using the Sony Bravia TV integration which more or less does exactly what I need. The only exception being information about played media in apps, which only shows as “Smart TV”. According to this issue on GitHub it’s a limitation of the API. The Chromechast integration on the other hand provides exactly that missing bit, but (obviously) doesn’t provide information about TV channels etc. So my goal is to combine the two media players into one which uses the sony entity as base and uses the source data from chromchast when sony reports “Smart TV”.

So far I’ve used a conditional card to display either of the media players, however I now have some automation relying on the data so having one merged entity would be quite helpful. Is there any way to have eg an universal media player with this kind of logic?

Conditional card configuration for reference:

  - type: custom:state-switch
    entity: >
      {% if not is_state("media_player.sony_bravia_tv", 'off') and not
      is_state("media_player.tv", "off") and
      is_state_attr('media_player.sony_bravia_tv', 'media_title', "Smart TV")
      and not is_state_attr('media_player.tv', 'app_name', "Netflix") %}
        cast
      {% else %}
        sony
      {% endif %}
    states:
      cast:
        type: media-control
        entity: media_player.tv
      sony:
        type: media-control
        entity: media_player.sony_bravia_tv

Look at the template media player integration.

I think its universal media player you want Universal Media Player - Home Assistant

1 Like

For those also searching this: The Universal Media Player got a new attribute in 2023.7 called active_child_template which now allows to properly handle this case, apparently exactly because of the sony integration. The docs provide a minimal solution, based on that I created a little more detailed one:

- platform: universal
  name: Sony Bravia
  unique_id: sony_bravia
  children:
    - media_player.sony_bravia_cast
    - media_player.sony_bravia_psk
  active_child_template: >
    {% if not is_state("media_player.sony_bravia_psk", 'off') and not is_state("media_player.sony_bravia_cast", "off") and is_state_attr('media_player.sony_bravia_psk', 'media_title', "Smart TV") and not is_state_attr('media_player.sony_bravia_cast', 'app_name', "Netflix") %}
      media_player.sony_bravia_cast
    {% else %}
      media_player.sony_bravia_psk
    {% endif %}
  browse_media_entity: media_player.sony_bravia_psk
  commands:
    turn_on:
      service: media_player.turn_on
      target:
        entity_id: media_player.sony_bravia_psk
    turn_off:
      service: media_player.turn_off
      target:
        entity_id: media_player.sony_bravia_psk
    volume_up:
      service: media_player.volume_up
      target:
        entity_id: media_player.sony_bravia_psk
    volume_down:
      service: media_player.volume_down
      target:
        entity_id: media_player.sony_bravia_psk
    volume_set:
      service: media_player.volume_set
      target:
        entity_id: media_player.sony_bravia_psk
      data:
        volume_level: "{{ volume_level }}"
    volume_mute:
      service: media_player.volume_mute
      target:
        entity_id: media_player.sony_bravia_psk
    select_source:
      service: media_player.select_source
      target:
        entity_id: media_player.sony_bravia_psk
      data:
        source: "{{ source }}"

  attributes:
    is_volume_muted: media_player.sony_bravia_psk|is_volume_muted
    volume_level: media_player.sony_bravia_psk|volume_level
    source_list: media_player.sony_bravia_psk|source_list

The differences:

  • All commands/attributes except the source are always taken from the integration (gives some more option and “turning off” the cast player would only end the cast instead of turning off the tv)
  • Netflix is using the integration instead of the cast. The reason here is that while netflix identifies as “Netflix” using cast, it doesn’t provide any additional information and ignores any commands like pausing so while using the integration displays “Smart TV” instead of “Netflix” at least pausing/resuming works
2 Likes

Would you be able to help me out with this? I have a Nuvo whole home audio amplifier that has 6 zones. I have it integrated into HA and I now have 6 different media player entities. I can create the universal media player no problem but in doing so I lose independent control over the 6 different media players. How would I go about setting up the universal media player to only control the media players that have their input source on 1.

I don’t think you can do that.

Hey @JN_Jones, thanks for posting your config. I tweaked it a little bit with new functionalities and some adjustments.

media_player:
# Templated Android TV media player
  - platform: media_player_template
    media_players:
      sony_bravia_android_templated:
        friendly_name: Sony Bravia Android TV templated
        device_class: tv
        current_source_template: "{{ state_attr('media_player.sony_bravia_psk', 'source') }}"
        current_volume_template: "{{ state_attr('media_player.sony_bravia_psk', 'volume_level') }}"
        current_is_muted_template: "{{ state_attr('media_player.sony_bravia_psk', 'is_volume_muted') }}"
        value_template: >
          {% if is_state("media_player.sony_bravia_android_tv", "on") %}
            {% if is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.google.android.apps.tv.launcherx") or is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.google.android.apps.tv.dreamx") or is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.android.tv.settings") %}
              on
            {% else %}
              playing
            {% endif %}
          {% else %}
            off
          {% endif %}
        turn_on:
          service: media_player.turn_on
          target:
            entity_id: media_player.sony_bravia_psk
        turn_off:
          service: media_player.turn_off
          target:
            entity_id: media_player.sony_bravia_psk
        volume_up:
          service: media_player.volume_up
          target:
            entity_id: media_player.sony_bravia_psk
        volume_down:
          service: media_player.volume_down
          target:
            entity_id: media_player.sony_bravia_psk
        set_volume:
          service: media_player.volume_set
          target:
            entity_id: media_player.sony_bravia_psk
          data:
            volume_level: "{{ volume | float }}"
        mute:
          service: media_player.volume_mute
          target:
            entity_id: media_player.sony_bravia_psk
          data:
            is_volume_muted: "{{ not state_attr('media_player.sony_bravia_psk', 'is_volume_muted') }}"
        play:
          service: media_player.media_play
          target:
            entity_id: media_player.sony_bravia_psk
        pause:
          service: media_player.media_pause
          target:
            entity_id: media_player.sony_bravia_psk
        stop:
          service: media_player.media_stop
          target:
            entity_id: media_player.sony_bravia_psk
        next:
          service: media_player.media_next_track
          target:
            entity_id: media_player.sony_bravia_psk
        previous:
          service: media_player.media_previous_track
          target:
            entity_id: media_player.sony_bravia_psk
        media_content_type_template: "{{ state_attr('media_player.sony_bravia_psk', 'media_content_type') }}"
        title_template: >
          {% if is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.apple.atve.sony.appletv") %}
            Apple TV
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.calibrationmonitor") %}
            Calman for BRAVIA
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.canal.android.canal") %}
            CANAL+
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.dailymotion.dailymotion") %}
            dailymotion
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.disney.disneyplus") %}
            Disney+
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.recapp") %}
            Title List
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.wbd.stream") %}
            Max
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.osat.music") %}
            Music
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.promos") %}
            My BRAVIA
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.netflix.ninja") %}
            Netflix
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.smartmediaapp") %}
            Media Player
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.smarthelp") %}
            Help
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.notificationcenter") %}
            BRAVIA notifications
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.amazon.amazonvideo.livingroom") %}
            Prime Video
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.ecodashboard") %}
            Eco Dashboard
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.skyshowtime.skyshowtime.google") %}
            SkyShowtime
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sonypicturescore") %}
            SONY PICTURES CORE
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.sonyselect") %}
            Sony Select
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.sonytab") %}
            Sony Tab
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.spotify.tv.android") %}
            Spotify
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.timers") %}
            Timers and Clock
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.tvx") %}
            TV
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "org.videolan.vlc") %}
            VLC
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.voice.guide") %}
            Voice Guide
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.google.android.youtube.tv") %}
            YouTube
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.google.android.youtube.tvmusic") %}
            YouTube Music
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.livingfit") %}
            Living Decor
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.sony.dtv.airplayapp") %}
            AirPlay
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.google.android.apps.tv.launcherx") %}
            Home screen
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.google.android.apps.tv.dreamx") %}
            Screensaver
          {% elif is_state_attr('media_player.sony_bravia_android_tv', 'app_id', "com.android.tv.settings") %}
            Settings
          {% else %}
            Smart TV
          {% endif %}
# Universal Media Player
  - platform: universal
    name: Sony Bravia
    unique_id: sony_bravia
    device_class: tv
    children:
      - media_player.sony_bravia_cast
      - media_player.sony_bravia_psk
      - media_player.sony_bravia_android_templated
    active_child_template: >
      {% if not is_state("media_player.sony_bravia_psk", 'off') and not is_state("media_player.sony_bravia_cast", "off") and is_state_attr('media_player.sony_bravia_psk', 'media_title', "Smart TV") %}
        media_player.sony_bravia_cast
      {% elif not is_state("media_player.sony_bravia_psk", 'off') and not is_state("media_player.sony_bravia_android_templated", "off") and is_state_attr('media_player.sony_bravia_psk', 'media_title', "Smart TV") and not is_state_attr('media_player.sony_bravia_android_templated', 'media_title', "Smart TV") %}
        media_player.sony_bravia_android_templated
      {% else %}
        media_player.sony_bravia_psk
      {% endif %}
    browse_media_entity: media_player.sony_bravia_psk
    commands:
      turn_on:
        service: media_player.turn_on
        target:
          entity_id: media_player.sony_bravia_psk
      turn_off:
        service: media_player.turn_off
        target:
          entity_id: media_player.sony_bravia_psk
      toggle:
        service: media_player.toggle
        target:
          entity_id: media_player.sony_bravia_psk
      volume_up:
        service: media_player.volume_up
        target:
          entity_id: media_player.sony_bravia_psk
      volume_down:
        service: media_player.volume_down
        target:
          entity_id: media_player.sony_bravia_psk
      volume_set:
        service: media_player.volume_set
        target:
          entity_id: media_player.sony_bravia_psk
        data:
          volume_level: "{{ volume_level }}"
      volume_mute:
        service: media_player.volume_mute
        target:
          entity_id: media_player.sony_bravia_psk
        data:
          is_volume_muted: "{{ not state_attr('media_player.sony_bravia_psk', 'is_volume_muted') }}"
      media_play_pause:
          service: media_player.media_play_pause
          target:
            entity_id: media_player.sony_bravia_psk
      media_play:
        service: media_player.media_play
        target:
          entity_id: media_player.sony_bravia_psk
      media_pause:
        service: media_player.media_pause
        target:
          entity_id: media_player.sony_bravia_psk
      media_stop:
        service: media_player.media_stop
        target:
          entity_id: media_player.sony_bravia_psk
      media_next_track:
        service: media_player.media_next_track
        target:
          entity_id: media_player.sony_bravia_psk
      media_previous_track:
        service: media_player.media_previous_track
        target:
          entity_id: media_player.sony_bravia_psk
      play_media:
        service: media_player.play_media
        target:
          entity_id: media_player.sony_bravia_psk
        data:
          media_content_id: "{{ media_content_id }}"
          media_content_type: "{{ media_content_type }}"
      select_source:
        service: media_player.select_source
        target:
          entity_id: media_player.sony_bravia_psk
        data:
          source: "{{ source }}"

    attributes:
      is_volume_muted: media_player.sony_bravia_psk|is_volume_muted
      volume_level: media_player.sony_bravia_psk|volume_level
      source: media_player.sony_bravia_psk|source
      source_list: media_player.sony_bravia_psk|source_list

media_player.sony_bravia_cast - Google Cast media player entity
media_player.sony_bravia_psk - Sony Bravia TV media player entity
media_player.sony_bravia_android_tv - Android TV Remote media player entity
sony_bravia_android_templated - media_player.template media player entity

Here are the changes:

Hey there @Dawidox - thanks for this. Trying to use it and I keep getting the following error in the YAML:

bad indentation of a mapping entry (70:11)

 67 |           target:
 68 |             entity_id: media_player.sony_ ...
 69 |         media_content_type_template: "{{  ...
 70 |           {% if is_state_attr('media_play ...
----------------^
 71 |             Apple TV
 72 |           {% elif is_state_attr('media_pl ...

Sorry, I’m a novice. Any idea how to fix?

Hi @hoosiers20, thank you for letting me know about this. It looks like I made a mistake when I was copying my config file and one essential line is missing.

You need to add title_template: > line below media_content_type_template. I have updated my config so it should be all correct now.

If you have anymore questions feel free to ask, I will be happy to help :grinning: