PyScript: Smooth media player volume fade with multiple curve functions

Credit

This is based on MaxVRAM’s awesome script originally found here so get check it out first. All major credit goes to him!

Reason

I went ahead and converted it into a pyscript function because my brain, for whatever reason, struggles to code in YAML till this day.

PyScript Code

def fade_volume(target_player, target_volume=0.5, duration=5, curve='logarithmic'):
  # Variables
  steps_per_second = 10
  total_steps = (steps_per_second * duration)
  start_volume = state.get(target_player+'.volume_level')
  start_diff = (target_volume - start_volume)
  # Loop
  i = 0
  while i < total_steps:
    i += 1
    if abs(state.get(target_player+'.volume_level') - target_volume) > 0.001:
      # Algorithm
      t = i / total_steps
      if curve == 'logarithmic':
        volume_level = (start_volume + (t / (1 + (1 - t))) * start_diff)
      elif curve == 'bezier':
        volume_level = (start_volume + (t * t * (3 - 2 * t)) * start_diff)
      else:
        volume_level = (start_volume + t * start_diff)
      # Control
      media_player.volume_set(entity_id=target_player, volume_level=float(volume_level))
      task.sleep(0.1)
    else:
      break
  # Final
  media_player.volume_set(entity_id=target_player, volume_level=float(target_volume))
  return

Usuage examples

I currently use this function for two types of automations. Firstly, I use it to fade in and out of a White Noise loop I play on my Sonos soundbar at night. Secondly, to fade in and out of music being played in a bathroom. When the bathroom door is opened, the Sonos speaker will fade to a lower volume. If the bathroom door is closed again while the music is still playing, the volume will fade back to the volume previously used before the door was opened with the help of a input_number helper.

But why?

This automation is not going to impact your daily life in a huge way, but for me, it’s the little things that HA can do that can make life a little better. Hope this helps or inspires someone else!

1 Like