How to play mp3 from media browser folder?

After have tried lots of configuration, nothing has worked. Play web hosted mp3 files is fine but for local files it’s not working.

Workaround : simply set up an apache2 on your hass device (pi, vm, desktop…) or on another device and put your mp3 in /var/www/html/ after a chmod 777 on the folder. This is nasty but no more issue :slight_smile:

I tried this, but it gives me a 401 unauthorized error. How do you configure this?

How do you even use a long lived token? There’s not much documentation how to use it? I used it and replaced everything after authSig= and it gave me a 401 error.

Hi Chris,
Long lived tokens do not work for this case. You need a signed path to access the content, AFAIK you cant create a signed path which never expires. So I created a node red flow which requests a signed path every time I need to access the media. It works perfectly.

[{"id":"970707c9e290e4c5","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"8a9451a1489823ee","type":"switch","z":"970707c9e290e4c5","name":"Short Press","property":"payload.event.args[0]","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":170,"y":100,"wires":[["f95cdc2547c3b160"],[]]},{"id":"f95cdc2547c3b160","type":"ha-api","z":"970707c9e290e4c5","name":"Get AuthSign","server":"76b07c6c.a5b7a4","debugenabled":false,"protocol":"websocket","method":"get","path":"","data":"{   \"type\": \"auth/sign_path\",   \"path\": \"/media/local/private/WhiteNoise.mp4\",   \"expires\": 300 }","dataType":"jsonata","location":"payload","locationType":"msg","responseType":"json","x":390,"y":100,"wires":[["d9f6be0e73519a55"]]},{"id":"d9f6be0e73519a55","type":"function","z":"970707c9e290e4c5","name":"Make Payload","func":"varPath = \"http://192.168.1.190:8123\" + msg.payload.path;\nvarGoogleHome = \"music\";\nmsg.payload.data = {\"media_content_id\" : varPath, \"media_content_type\" : varGoogleHome, }\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":100,"wires":[["c407630b2c25e128"]]},{"id":"c407630b2c25e128","type":"api-call-service","z":"970707c9e290e4c5","name":"Play White Noise","server":"76b07c6c.a5b7a4","version":1,"debugenabled":false,"service_domain":"media_player","service":"play_media","entityId":"media_player.googlehome7491","data":"payload.data","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":750,"y":100,"wires":[[]]},{"id":"76b07c6c.a5b7a4","type":"server","name":"Home Assistant","legacy":false,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

1 Like

I’d like to try this, but I have no idea how to use node red. I installed it, but I don’t know where to type the the script.

It looks like they’re using the websockets Authentication API | Home Assistant Developer Docs

They get a token then use that for the authSig query parameter.

Unfortunately, I don’t know how to directly/easily make a websocket call from within an automation and it seems the auth api is only available via websockets and not HTTP. Node-red on the other hand does seem to have native support for websockets.

Yes, I am using the Signed Paths - Authentication API | Home Assistant Developer Docs
I am not sure how to do this via home assistant automations. Node red makes it really easy.

It is explained in the docs: Media Source - Home Assistant

service: media_player.play_media
target:
  entity_id: media_player.living_room_tv
data:
  media_content_type: "video/mp4"
  media_content_id: "media-source://media_source/local/videos/favourites/Epic Sax Guy 10 Hours.mp4"

For me it worked like this:

service: media_player.play_media
target:
      entity_id: media_player.google_nest_mini
 data:
    media_content_id: "media-source://media_source/local/file.mp3"
    media_content_type: music
6 Likes

This is the script I have and it works perfectly. I didn’t need to whitelist anything.

  - service: media_player.play_media
    target:
      entity_id: media_player.speaker
    data:
      media_content_id: '/media/local/file.mp3'
      media_content_type: audio/mp3

I had “music” as the media_content_type at first, but it wasn’t working with my setup. I found out using audio/mp3 has no issue.

8 Likes

Here is, what worked for me:

service: media_player.play_media
data:
  media_content_id: /media/music_party/Anastacia - Not that kind.mp3
  media_content_type: music
target:
  entity_id: media_player.fernseher

This is going to a Google Chrome Cast built into my Philips TV.

I had some trouble finding the correct URL for media_content_id. I finally found the right path by using the method described by @antimage in post #7.

When it finally worked, I had no idea where HA took that path segment “/music_party” from. The files are really stored in the /media partition of HA and the folder is called “/Party”. Later I found that the path is actually built using the media_dirs key from configuration yaml:

homeassistant:
  media_dirs:
    music_party: /media/Party

As you can see I did NOT have to put any host in front of the media_content_id, so no problem with host name vs. IP. Also all the authSig token generation and handling mechanics are done automatically in the background. No need to touch that. The param media_content_type works for me with both “music” and “audio/mp3”.

3 Likes

Thats weird.
Playing mp3 in /config/www in my home assistant with “music” works perfectely on old Sonos. However, on a new Sonos or Amazon Echo I got the error “sorry tts can only be called with notify.alexa_media service”. When I use “audio/mp3” or “audio” or “mp3” instead of music, I don’t get anything at all.

If anyone needs python code to generate a “signed” URL to an .mp3 (or some other asset), I wrote this:

from websocket import create_connection
import json
import sys

# Python code to get a "signed path" to a Home Assistant asset via the websocket API
# As per docs:
# https://developers.home-assistant.io/docs/api/websocket/
# https://developers.home-assistant.io/docs/auth_api/#signed-paths

# Make sure to substitute your server IP, desired path to sign, and long-lived access token
# You can generate your own in HA, click on your username (bottom left) then "Long-Lived Access Tokens" -> "CREATE TOKEN"

host = "192.168.0.158:8123"
path_to_sign = "/media/local/doorbell.mp3"
protocol = "http"
access_token = "XXXXXXXX"

ws = create_connection("ws://%s/api/websocket" % host)
ws.recv()
ws.send(json.dumps({
    "type": "auth",
    "access_token": access_token
}))
auth_resp = json.loads(ws.recv())
if auth_resp.get('type') != 'auth_ok':
    print('failed to login, check your auth token -- response: %s' % (auth_resp))
else:
    ws.send(json.dumps(
    {
      "type": "auth/sign_path",
      "path": path_to_sign,
      "id": 1,
      "expires": 300
    }))
    result = json.loads(ws.recv())
    if result.get('success') == True:
        signed_path = result.get('result').get('path')
        print('%s://%s%s' % (protocol, host, signed_path))
    else:
        print('ERROR: %s' % result)
ws.close()

The sample above return a URL like:
http://192.168.0.158:8123/media/local/doorbell.mp3?authSig=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkZWU1MzFiNTlkZmY0OTAwYjkxZWMyYTkwZGNlZWEzNCIsInBhdGgiOiIvbWVkaWEvbG9jYWwvZG9vcmJlbGwubXAzIiwicGFyYW1zIjp7fSwiaWF0IjoxNjc2MDg4MTE5LCJleHAiOjE2NzYwODg0MTl9.Fml3y5_NjIwIcnCNq6SUk3s0xmwPXqGnrS7PbMyuryg

Note that the generated URL is only valid for 5 minutes

1 Like

Thanks!
How is it supposed to be used?
Do you have an example?

In my case, I am using at /config/www

So I can use http://IP:8123/local/myfile.mp3

Cons:

Pros:

  • It is in a public folder.
    I can make Alexa to reproduce it.
service: script.run_alexa_custom_skill_notification
data:
  speech: <audio src="https://ha.mydomain.com/local/myfile.mp3" />
  target: media_player.echo_dot_quarto
1 Like

Spent a good two hours pulling my hair out on this one. Soin case anyone else stumbles across this, Jpsy has the solution. There’s no token or auth needed. If you have the media folder set up properly in the config it will work.

2 Likes

Does this only work if you select 1 MP3 or can you also select a folder containing multiple MP3s?

Not sure if this will help you guys, but I just started using an Add-on called “Music assistant”. Works pretty well, and casts to all my Chromecast devices MUCH more reliably than Plex. Just thought I’d toss that out there. The interface is remarkably similar to Plex, but it displays right in HA, which is nice. No switching back and forth between apps. :slight_smile:

This deserves more credit. This is the solution that the docs don’t give you.

I did following and it worked for me. I can also play mp3 files from attached USB external HDD

  1. edit configuration.yaml and enter the following lines

homeassistant:
allowlist_external_dirs:
- /media
media_dirs:
local: /media

  1. I created an automation to play the file. you may be able to use button

action:

  • service: media_player.play_media
    target:
    entity_id: media_player.mpd
    data:
    media_content_type: audio/mp3
    media_content_id: media-source://media_source/local/Dumps/Songs/Bhajans/Hanuman Chalisa/Hanuman Chalisa - Mahendra Kapoor.mp3
    mode: single

You cannot play a folder or playlist without add-ons. This is because HomeAssist does not stream the media files, but only sends a link to the media file to the speaker, and does not process its contents in any way, so HA does not know the current status, i.e. playback duration. And in order to send the next file from a folder or playlist, you need to know that the previous file has finished playing. Something has to keep track of this, which is why media servers and other additional tools are installed for this purpose.

I use the Music Assistant add-on to serve this purpose. Works AWESOME.