Stream Twitch audio to media player

During the day, I enjoy streaming a popular scam-baiter from Twitch to listen in the background. It’s usually really funny, there’s a lot of waiting around, so it’s not disrupting to my work day, and it’s mainly audio based so I don’t need to pay visual attention to it.

image

I’ve put together a combination of inputs on the lovelace front end, and some automations, and now I can stream the audio from Twitch, using media_extractor, to my instance of forked-daapd, which then pushes the audio to whatever remote speaker I choose. If you provide a start time (using the format HH:mm:ss) then it will start to stream from that timestamp.

To implement it, you’ll need to have a media player, media extractor, and the lovelace-text-input-row plugin from the HACS integration.. It involves a lovelace front end, a couple of automations, and a couple of scripts.

Lovelace UI Code

entities:
  - entity: input_text.media_id
    type: 'custom:text-input-row'
  - entity: input_text.start_time
    type: 'custom:text-input-row'
  - action_name: Stream Music
    icon: 'mdi:music'
    name: ' '
    service: script.stream_music
    type: call-service
  - action_name: Update Time
    icon: 'mdi:refresh'
    name: ' '
    service: script.1586984693530
    type: call-service
title: Stream to Music Server
type: entities

Automation
This automation will update the UI with the media stream URL for any source that’s a remote stream (regardless of where you started it), and trigger the script to update the timestamp in the UI.

- id: '1587058178874'
  alias: Populate Music Entities
  description: ''
  trigger:
  - entity_id: media_player.music_server
    platform: state
    to: playing
  condition:
  - condition: template
    value_template: '{{ ''http'' in state_attr(''media_player.music_server'', ''media_content_id'')
      }}'
  - condition: state
    entity_id: input_text.start_time
    state: ''
  action:
  - data_template:
      value: '{{ state_attr(''media_player.music_server'', ''media_content_id'') }}'
    entity_id: input_text.media_id
    service: input_text.set_value
  - data: {}
    entity_id: script.1586984693530
    service: script.turn_on


Scripts
There are three scripts: the first one to begin the stream, on button press. The other two will run repeatedly as long as the stream is being played, in order to update the timestamp in the UI. This will allow me to stop the stream, then pick it back up from the last place I was listening without any need to keep track of the timestamp.

stream_music:
  alias: Stream Music
  sequence:
  - data_template:
      media_content_id: '{{states(''input_text.media_id'')}}'
      media_content_type: video/youtube
    entity_id: media_player.music_server
    service: media_extractor.play_media
  - condition: template
    value_template: '{{ states(''input_text.start_time'') != '''' }}'
  - data_template:
      entity_id: media_player.music_server
      seek_position: '{% set ts = states(''input_text.start_time'').split(":") %}
        {% if (ts|length == 2) %} {{ ((ts[0] | int ) * 60) + (ts[1] | int)}} {% else
        %} {{ ((ts[0] | int ) * 60 * 60) + ((ts[1] | int) * 60) + (ts[2] | int)}}
        {% endif %}'
    service: media_player.media_seek
  - timeout: 00:00:30
    wait_template: '{{ states(''media_player.music_server'') == ''playing''}}'
  - data: {}
    entity_id: script.1586984693530
    service: script.turn_on

'1586984693530':
  alias: Update Timestamp Text Input
  sequence:
  - data_template:
      entity_id: input_text.start_time
      value: '{% set time = (state_attr("media_player.music_server", "media_position").split(":")[0]
        | int) %} {% set seconds = ((time % 60) | int) %} {% set minutes = ((time
        % 3600) / 60) | int %} {% set hours = ((time % 86400) / 3600) | int %} {%
        set days = (time / 86400) | int %} {{ "%02d" | format(hours) ~ ":" ~ "%02d"
        | format(minutes) ~ ":" ~ "%02d" | format(seconds)}}'
    service: input_text.set_value
  - delay: 00:00:05
  - data: {}
    entity_id: script.1586985396087
    service: script.turn_on
'1586985396087':
  alias: Continue Polling Music Server Timestamp
  sequence:
  - condition: state
    entity_id: media_player.music_server
    state: playing
  - data: {}
    entity_id: script.1586984693530
    service: script.turn_on


Thanks for this, I’ve been looking for a similar solution.
Any chance you can elaborate on some of the other things not shown here and fill in the gaps? e.g. Media Extractor config.

This should be all you need. I don’t have anything specific for media_extractor, just followed the instructions in the docs. The other requirements are all listed in the original post, as far as I can tell. I’d be happy to answer any questions you have or help out if you run into any problems.

Good luck! :slight_smile: