M3U Playlists in Media Browser

normally the spaces and dashes are no problem. you would have to test by copy the file name and directly send it to the media player if works or not. there is “#” or very few chars won’t be played.
If you are not using Google Home/Nest, I’m not sure if once it ends a song would be “off status”, if so, you might need to change the checking status code in N-R of mine.

A big thanks for your help with this BTW.
It looks like I am close to getting it working but am trying to do it remotely so perhaps its better if I wait until I am home and be sure of what the player is doing. The player is a Google Home Mini.
I will post back here when I have done more testing.

np, once it working with 1st song, it should be working with all the rest :grinning:

Hmm not sure what I am doing wrong. Turning the media player card from off to on puts the player state to idle. Pressing the player’s play button does nothing even though a track is shown as selected.
The only way I can get the player to start playing is with the Media Browser and then when the selected track is finished the next song is selected but the player goes to Idle. ??

the URL of the mp3 post to Google Home Mini is incorrect, it turns to idle status and do nothing.
there are errors in core logs.
as I’m not sure about the media_content_id path what would be if you changed the folder or media_dirs conf in HA, it is an unknown area to me.

  • I would like to suggest that if you not family with JS and debugging, just simply use my folder struct to stores the MP3 files, with the same HA media_dirs conf with mine, it should be working without problem.
  • otherwise, you may need to figure what path and filename should be set in media_content_id, then the problem should be solved.

Hi robb, good news, I’ve done the settings which working with your current setup.
I’ve added a playlist selection which you may need to pre-define it in node-red and input_select.

New Feature

  • Added playlist selection based on different folders in media files.
  • Music can be played with different playlists, not just one folder.

Steps

Based on the old version, below are the new steps to adds the playlist feature.
Currently, my folder likes

  • config/
    • media/
      • mp3/
        • a.mp3
      • favorite_mp3/
        • b.mp3
        • c.mp3

@robb, you can simply consider your Mp3 folder is a playlist, which name could be “My Music” and path in dir2files is “/config/media/Mp3” in steps 4, also you can add more folder under “/config/media” to make more playlist.

  1. Add new input_select in HA → Configuration → Helpers.
  2. Add the entity to lovelace.

3rd version node-red will override step 3 to 5, also 3rd version will more friendly, just one node modifying for mapping, no more path need to be set, 3rd version on next reply below.

  1. Modify the playlist name mapping to yours, once you have more than 2 playlists, just insert one more then output to a new dir2files.
  2. Modify the dir2files folder to your sub folder path.
  3. Modify the replace function in “deal with url” function in node-red, just the red box in below image.
    微信截图_20210308145636

NOTICE

For the minimal changes, and can be working without additional work, make sure your media_dirs in HA config same as mine (the “media” section).
微信截图_20210308150459

N-R

[{"id":"143859dc.b68516","type":"function","z":"13ac7585.18210a","name":"deal with url","func":"file_name = msg.payload;\nsong_title = file_name\n    .replace(\"/config/\",\"\")\n        .replace(\"media/\",\"\")\n        .replace(\"mp3/\",\"\")\n        .replace(\"favorite_mp3/\",\"\")\n            .replace(\".mp3\",\"\")\nfile_name = file_name.replace(\"/config/\",\"/media/\")\nmsg.post_data = {\"media_content_id\":file_name,\"media_content_type\":\"audio/mp3\"}\nmsg.post_data[\"extra\"] ={\"metadata\": {\"metadataType\":3,\"title\":song_title}}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":730,"y":140,"wires":[["a1220b1d.bf98d8"]]}]

node-red and playlist feature has been tested and working in my env.

Hi robb, good news, I’ve published the 3rd version which including favorite button that can copy/delete the songs you like in fav folder.

New Feature

  • Added favorite button that can make it likes a rich functional media player.
  • Favorite songs can be added or delete by press the Favorite button

Steps

  1. Add the favorite button with the same name in pic below. (make sure you have “My Favorite” “in Music Playlist” for favorite function working)
  2. Add the button into lovelace.
  3. Install node-red-contrib-fs-ops in node-red.
  4. Parse/Replace the node-red flow into yours.
  5. Modify the playlist to your path. Please notice that not to modify “My Favorite” (path can be modified), as it fixed in other nodes, or you willing to modify the name, FS nodes as an additional step.

Then you will have a perfect favorite/like playlist working with all your other playlists. :grinning:

N-R

[{"id":"13ac7585.18210a","type":"tab","label":"media player","disabled":false,"info":""},{"id":"58ff70b9.a6b58","type":"random-item","z":"13ac7585.18210a","name":"","input":"payload","inputType":"msg","output":"payload","outputType":"msg","number":1,"x":730,"y":80,"wires":[["143859dc.b68516"]]},{"id":"a1220b1d.bf98d8","type":"api-call-service","z":"13ac7585.18210a","name":"","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"media_player","service":"play_media","entityId":"media_player.home_group","data":"post_data","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":790,"y":320,"wires":[[]]},{"id":"143859dc.b68516","type":"function","z":"13ac7585.18210a","name":"deal with url","func":"file_name = msg.payload;\nsong_title = file_name.replace(\".mp3\",\"\")\nfile_name = msg.playlist_path.replace(\"/config/\",\"/media/\")\n    + file_name;\nmsg.file_name = msg.payload;\nmsg.song_title = song_title;\nmsg.post_data = {\"media_content_id\":file_name,\"media_content_type\":\"audio/mp3\"}\nmsg.post_data[\"extra\"] ={\"metadata\": {\"metadataType\":3,\"title\":song_title}}\nglobal.set(\"hohoFavoriteSong\",msg);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":730,"y":140,"wires":[["7b2ec18b.535d5"]]},{"id":"3c129312.d5241c","type":"server-state-changed","z":"13ac7585.18210a","name":"media player device","server":"f25fc2a7.50d81","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"media_player.home_group","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"idle","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":140,"y":280,"wires":[["f4ccfdb9.d779d"],["3c06a1df.f5ea0e"]]},{"id":"f4ccfdb9.d779d","type":"api-current-state","z":"13ac7585.18210a","name":"Check music time button state","server":"f25fc2a7.50d81","version":1,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_boolean.music_time","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":170,"y":180,"wires":[["d0b8c29b.4f194"],[]]},{"id":"49b79303.897c5c","type":"server-state-changed","z":"13ac7585.18210a","name":"music time button state","server":"f25fc2a7.50d81","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.music_time","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"on","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":150,"y":340,"wires":[["d0b8c29b.4f194"],["52d23ddf.ff4954"]]},{"id":"52d23ddf.ff4954","type":"api-call-service","z":"13ac7585.18210a","name":"","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"media_player","service":"turn_off","entityId":"media_player.home_group","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":780,"y":380,"wires":[[]]},{"id":"3c06a1df.f5ea0e","type":"switch","z":"13ac7585.18210a","name":"device state","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"paused","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":410,"y":240,"wires":[["d0b8c29b.4f194"],["a232d975.043968"]]},{"id":"a232d975.043968","type":"api-call-service","z":"13ac7585.18210a","name":"off music","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_off","entityId":"input_boolean.music_time","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":720,"y":440,"wires":[[]]},{"id":"d0b8c29b.4f194","type":"api-current-state","z":"13ac7585.18210a","name":"load playlist","server":"f25fc2a7.50d81","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_select.music_playlist","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":130,"y":100,"wires":[["40412deb.dc30c4"]]},{"id":"51c126bf.dcea28","type":"server-state-changed","z":"13ac7585.18210a","name":"favorite song button state","server":"f25fc2a7.50d81","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.favorite_song","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":170,"y":440,"wires":[["89eb5dc0.898a2"]]},{"id":"89eb5dc0.898a2","type":"function","z":"13ac7585.18210a","name":"check","func":"\nvar data = global.get(\"hohoFavoriteSong\");\nif (data === undefined ||data === null ){\n    return [null,null];\n}\ndata.set_fav = msg.payload;\nreturn [data,null];","outputs":2,"noerr":0,"initialize":"","finalize":"","x":110,"y":500,"wires":[["44dc0761.893fd8"],[]]},{"id":"3187d62c.ad0c5a","type":"fs-ops-dir","z":"13ac7585.18210a","name":"mp3 folder","path":"playlist_path","pathType":"msg","filter":"*.mp3","filterType":"str","dir":"payload","dirType":"msg","x":530,"y":100,"wires":[["58ff70b9.a6b58"]]},{"id":"40412deb.dc30c4","type":"function","z":"13ac7585.18210a","name":"PLAYLIST mapping","func":"playlist_mapping = {\n    \"Mp3\":\"/config/media/mp3/\",\n    \"My Favorite\":\"/config/media/favorite_mp3/\",\n};\nmsg.playlist_mapping = playlist_mapping;\npath = playlist_mapping[msg.payload];\nmsg.playlist_path = path;\nmsg.playlist_name = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":330,"y":100,"wires":[["3187d62c.ad0c5a"]]},{"id":"7b2ec18b.535d5","type":"fs-ops-access","z":"13ac7585.18210a","name":"is fav file exists","path":"playlist_mapping[\"My Favorite\"]","pathType":"msg","filename":"file_name","filenameType":"msg","read":true,"write":false,"throwerror":false,"x":660,"y":200,"wires":[["57cfe80c.d29f58"],["dde1a78a.b45c58"]]},{"id":"57cfe80c.d29f58","type":"api-call-service","z":"13ac7585.18210a","name":"fav button on","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_on","entityId":"input_boolean.favorite_song","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":950,"y":160,"wires":[["a1220b1d.bf98d8"]]},{"id":"dde1a78a.b45c58","type":"api-call-service","z":"13ac7585.18210a","name":"fav button on","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_off","entityId":"input_boolean.favorite_song","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":950,"y":240,"wires":[["a1220b1d.bf98d8"]]},{"id":"44dc0761.893fd8","type":"api-current-state","z":"13ac7585.18210a","name":"only playing","server":"f25fc2a7.50d81","version":1,"outputs":2,"halt_if":"playing","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"media_player.home_group","state_type":"str","state_location":"media_state","override_payload":"msg","entity_location":"media_data","override_data":"msg","blockInputOverrides":false,"x":270,"y":500,"wires":[["bf0b29c2.989458"],[]]},{"id":"b794607c.368ff","type":"fs-ops-delete","z":"13ac7585.18210a","name":"","path":"playlist_mapping[\"My Favorite\"]","pathType":"msg","filename":"file_name","filenameType":"msg","x":670,"y":600,"wires":[["5844b77.4f36e48"]]},{"id":"bf0b29c2.989458","type":"switch","z":"13ac7585.18210a","name":"copy or delete","property":"set_fav","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":260,"y":580,"wires":[["63d31658.fd04a8"],["c4f81d55.595be"]]},{"id":"63d31658.fd04a8","type":"fs-ops-access","z":"13ac7585.18210a","name":"is fav file exists","path":"playlist_mapping[\"My Favorite\"]","pathType":"msg","filename":"file_name","filenameType":"msg","read":true,"write":false,"throwerror":false,"x":460,"y":540,"wires":[[],["9128b2f4.04a31"]]},{"id":"9128b2f4.04a31","type":"fs-ops-copy","z":"13ac7585.18210a","name":"copy to fav folder","sourcePath":"playlist_path","sourcePathType":"msg","sourceFilename":"file_name","sourceFilenameType":"msg","destPath":"playlist_mapping[\"My Favorite\"]","destPathType":"msg","destFilename":"file_name","destFilenameType":"msg","link":false,"overwrite":true,"x":680,"y":540,"wires":[["5844b77.4f36e48"]]},{"id":"5844b77.4f36e48","type":"debug","z":"13ac7585.18210a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1070,"y":380,"wires":[]},{"id":"c4f81d55.595be","type":"fs-ops-access","z":"13ac7585.18210a","name":"is fav file exists","path":"playlist_mapping[\"My Favorite\"]","pathType":"msg","filename":"file_name","filenameType":"msg","read":true,"write":false,"throwerror":false,"x":460,"y":600,"wires":[["b794607c.368ff"],[]]},{"id":"f25fc2a7.50d81","type":"server","name":"Home Assistant"}]

Updates

  • Removed dir2files component in node-red.
  • Merged most customized scripts/vars into easy modifying js array.
  • No more “deal with url” or other nodes need to be modified during setup.
1 Like

Mate your are on a roll. Great work!
I have found that my problem is more basic. I am not getting the media player to play even from the Services Developer Tool. I need to get this sorted out before any of your good work will work for me.

If you can get the music playing from “Media Player Browser”, then it is no problem.
You don’t need to know the URL or path of my 3rd version N-R, no replace functions need to be changed.
Just the physical path to the location of your mp3 files.
p.s. If you have the same settings in HA conf with me, the media_content_id of yours is “/media/media/mp3/xxx.mp3”, you can try it in Services Developer Tool.

This is working now ok in the Services Developer Tool:

entity_id: media_player.living_room_speaker_2
media_content_id: "/media/media/Music/filename.mp3"
media_content_type: music

I currently have this in the function node:

file_name = msg.payload;
song_title = file_name
    .replace("/media/","")
        .replace("media/","")
            .replace("Music/","")        
                .replace(".mp3","")
file_name = file_name.replace("/media/","/media/","/Music/")

but it is only parsing

"/media/Music/filename.mp3"
to the Call Service Node instead of “/media/media/Music/filename.mp3” so it goes idle. I need to add another line to the function.

Hi @robb1 try version 3 and later, there is no need to do path modification yourself.
Update for N-R would be:

  1. make sure all input_* (HA -> Configuration -> Helpers) been set.
  2. parse the latest N-R content.

Now I’m publishing version 4, which contains the ID3 metadata in mp3 file with image, the media player box will have the image inside the mp3 file.
微信截图_20210308211829

Version 4

Feature

Steps

  1. Upgrading from version 3, just replace the N-R code.
  2. Modify the “PLAYLIST mapping” as version 3.
  3. For version 4, there are msg.album_cover_temp_file and msg.album_cover_temp_url need to be set in “PLAYLIST mapping”, don’t worry, there are pre-set as dummy content for understanding.

N-R

[{"id":"13ac7585.18210a","type":"tab","label":"media player","disabled":false,"info":""},{"id":"58ff70b9.a6b58","type":"random-item","z":"13ac7585.18210a","name":"","input":"payload","inputType":"msg","output":"payload","outputType":"msg","number":1,"x":730,"y":80,"wires":[["143859dc.b68516"]]},{"id":"a1220b1d.bf98d8","type":"api-call-service","z":"13ac7585.18210a","name":"","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"media_player","service":"play_media","entityId":"media_player.home_group","data":"post_data","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":890,"y":600,"wires":[[]]},{"id":"143859dc.b68516","type":"function","z":"13ac7585.18210a","name":"deal with url","func":"file_name = msg.payload;\nsong_title = file_name.replace(\".mp3\",\"\")\nmsg.filename = msg.playlist_path + file_name;\nfile_name = msg.playlist_path.replace(\"/config/\",\"/media/\")\n    + file_name;\nmsg.file_name = msg.payload;\nmsg.song_title = song_title;\nmsg.post_data = {\"media_content_id\":file_name,\"media_content_type\":\"audio/mp3\"}\nmsg.post_data[\"extra\"] ={\"metadata\": {\"metadataType\":3,\"title\":song_title}}\nglobal.set(\"hohoFavoriteSong\",msg);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":910,"y":80,"wires":[["b4a41b7a.44c238"]]},{"id":"3c129312.d5241c","type":"server-state-changed","z":"13ac7585.18210a","name":"media player device","server":"f25fc2a7.50d81","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"media_player.home_group","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"idle","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":140,"y":280,"wires":[["f4ccfdb9.d779d"],["3c06a1df.f5ea0e"]]},{"id":"f4ccfdb9.d779d","type":"api-current-state","z":"13ac7585.18210a","name":"Check music time button state","server":"f25fc2a7.50d81","version":1,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_boolean.music_time","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":170,"y":180,"wires":[["d0b8c29b.4f194"],[]]},{"id":"49b79303.897c5c","type":"server-state-changed","z":"13ac7585.18210a","name":"music time button state","server":"f25fc2a7.50d81","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.music_time","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"on","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":150,"y":340,"wires":[["d0b8c29b.4f194"],["52d23ddf.ff4954"]]},{"id":"52d23ddf.ff4954","type":"api-call-service","z":"13ac7585.18210a","name":"","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"media_player","service":"turn_off","entityId":"media_player.home_group","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":880,"y":660,"wires":[[]]},{"id":"3c06a1df.f5ea0e","type":"switch","z":"13ac7585.18210a","name":"device state","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"paused","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":410,"y":240,"wires":[["d0b8c29b.4f194"],["a232d975.043968"]]},{"id":"a232d975.043968","type":"api-call-service","z":"13ac7585.18210a","name":"off music","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_off","entityId":"input_boolean.music_time","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":820,"y":720,"wires":[[]]},{"id":"d0b8c29b.4f194","type":"api-current-state","z":"13ac7585.18210a","name":"load playlist","server":"f25fc2a7.50d81","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"input_select.music_playlist","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":130,"y":100,"wires":[["40412deb.dc30c4"]]},{"id":"51c126bf.dcea28","type":"server-state-changed","z":"13ac7585.18210a","name":"favorite song button state","server":"f25fc2a7.50d81","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.favorite_song","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":170,"y":440,"wires":[["89eb5dc0.898a2"]]},{"id":"89eb5dc0.898a2","type":"function","z":"13ac7585.18210a","name":"check","func":"\nvar data = global.get(\"hohoFavoriteSong\");\nif (data === undefined ||data === null ){\n    return [null,null];\n}\ndata.set_fav = msg.payload;\nreturn [data,null];","outputs":2,"noerr":0,"initialize":"","finalize":"","x":110,"y":500,"wires":[["44dc0761.893fd8"],[]]},{"id":"3187d62c.ad0c5a","type":"fs-ops-dir","z":"13ac7585.18210a","name":"mp3 folder","path":"playlist_path","pathType":"msg","filter":"*.mp3","filterType":"str","dir":"payload","dirType":"msg","x":530,"y":100,"wires":[["58ff70b9.a6b58"]]},{"id":"40412deb.dc30c4","type":"function","z":"13ac7585.18210a","name":"PLAYLIST mapping","func":"playlist_mapping = {\n    \"Mp3\":\"/config/media/mp3/\",\n    \"My Favorite\":\"/config/media/favorite_mp3/\",\n};\nmsg.album_cover_temp_file = \"/config/www/album_cover_temp.jpg\";\nmsg.album_cover_temp_url = \"https://[YOUR HA DOMAIN]/local/album_cover_temp.jpg?\" + Math.random();\n\n\n//msg.album_cover_temp_file = \"/config/media/album_cover_temp.jpg\";\nmsg.playlist_mapping = playlist_mapping;\npath = playlist_mapping[msg.payload];\nmsg.playlist_path = path;\nmsg.playlist_name = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":330,"y":100,"wires":[["3187d62c.ad0c5a"]]},{"id":"7b2ec18b.535d5","type":"fs-ops-access","z":"13ac7585.18210a","name":"is fav file exists","path":"playlist_mapping[\"My Favorite\"]","pathType":"msg","filename":"file_name","filenameType":"msg","read":true,"write":false,"throwerror":false,"x":640,"y":480,"wires":[["57cfe80c.d29f58"],["dde1a78a.b45c58"]]},{"id":"57cfe80c.d29f58","type":"api-call-service","z":"13ac7585.18210a","name":"fav button on","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_on","entityId":"input_boolean.favorite_song","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":830,"y":460,"wires":[["a1220b1d.bf98d8"]]},{"id":"dde1a78a.b45c58","type":"api-call-service","z":"13ac7585.18210a","name":"fav button on","server":"f25fc2a7.50d81","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_off","entityId":"input_boolean.favorite_song","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":830,"y":520,"wires":[["a1220b1d.bf98d8"]]},{"id":"44dc0761.893fd8","type":"api-current-state","z":"13ac7585.18210a","name":"only playing","server":"f25fc2a7.50d81","version":1,"outputs":2,"halt_if":"playing","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"media_player.home_group","state_type":"str","state_location":"media_state","override_payload":"msg","entity_location":"media_data","override_data":"msg","blockInputOverrides":false,"x":270,"y":500,"wires":[["bf0b29c2.989458"],[]]},{"id":"b794607c.368ff","type":"fs-ops-delete","z":"13ac7585.18210a","name":"","path":"playlist_mapping[\"My Favorite\"]","pathType":"msg","filename":"file_name","filenameType":"msg","x":490,"y":620,"wires":[[]]},{"id":"bf0b29c2.989458","type":"switch","z":"13ac7585.18210a","name":"copy or delete","property":"set_fav","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":140,"y":580,"wires":[["63d31658.fd04a8"],["c4f81d55.595be"]]},{"id":"63d31658.fd04a8","type":"fs-ops-access","z":"13ac7585.18210a","name":"is fav file exists","path":"playlist_mapping[\"My Favorite\"]","pathType":"msg","filename":"file_name","filenameType":"msg","read":true,"write":false,"throwerror":false,"x":320,"y":560,"wires":[[],["9128b2f4.04a31"]]},{"id":"9128b2f4.04a31","type":"fs-ops-copy","z":"13ac7585.18210a","name":"copy to fav folder","sourcePath":"playlist_path","sourcePathType":"msg","sourceFilename":"file_name","sourceFilenameType":"msg","destPath":"playlist_mapping[\"My Favorite\"]","destPathType":"msg","destFilename":"file_name","destFilenameType":"msg","link":false,"overwrite":true,"x":510,"y":560,"wires":[[]]},{"id":"c4f81d55.595be","type":"fs-ops-access","z":"13ac7585.18210a","name":"is fav file exists","path":"playlist_mapping[\"My Favorite\"]","pathType":"msg","filename":"file_name","filenameType":"msg","read":true,"write":false,"throwerror":false,"x":320,"y":620,"wires":[["b794607c.368ff"],[]]},{"id":"b4a41b7a.44c238","type":"get media tags","z":"13ac7585.18210a","name":"","filename":"","x":1100,"y":80,"wires":[["45a93ed0.bd55a"]]},{"id":"45a93ed0.bd55a","type":"function","z":"13ac7585.18210a","name":"","func":"if (msg.payload != undefined && msg.payload.error != undefined){\n    return msg;\n}\nmetadata = msg.post_data[\"extra\"][\"metadata\"];\nif (msg.payload.tags != undefined){\n    tags = msg.payload.tags;\n    if (tags.title != undefined)\n        metadata['title'] = tags.title;\n        \n    if (tags.artist != undefined)\n        metadata['artist'] = tags.artist;\n        \n    if (tags.album != undefined)\n        metadata['albumName'] = tags.album;\n        \n    if (tags.track != undefined)\n        metadata['trackNumber'] = tags.track;\n        \n    if (tags.year != undefined)\n        metadata['releaseDate'] = tags.year;\n        \n    if (tags.picture != undefined){\n        msg.image = \"yes\";\n        msg.payload = new Buffer(tags.picture.data);\n        msg.filename = msg.album_cover_temp_file;\n        metadata['images'] = [{\"url\":msg.album_cover_temp_url}];\n    }\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":720,"y":160,"wires":[["772e70e0.a6915"]]},{"id":"772e70e0.a6915","type":"switch","z":"13ac7585.18210a","name":"","property":"image","propertyType":"msg","rules":[{"t":"nnull"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":850,"y":160,"wires":[["a0d08060.d0d02"],["7b2ec18b.535d5"]]},{"id":"a0d08060.d0d02","type":"file","z":"13ac7585.18210a","name":"","filename":"","appendNewline":false,"createDir":true,"overwriteFile":"true","encoding":"none","x":1010,"y":160,"wires":[["7b2ec18b.535d5"]]},{"id":"f25fc2a7.50d81","type":"server","name":"Home Assistant"}]


2 Likes

@robb1 I put the final version to https://github.com/nov30th/ha-hoho-google-media-center, and steps. :grin:
I may add an auto rename function later which music file can not be played.
Let me know if you still can not get this work or not, you are the 1st person who trying the man-made node-red of me. :rofl:

2 Likes

the file name issue has been found and located.
https://github.com/home-assistant/core/issues/47663

Total Node-Red newbie. First time install.

Going through the code and importing it into Node-Red, I noticed that palette node-red-contrib-random-item also needs to be installed.

Thanks

Thanks @ArunGupta , I’ve added this palette into the installation steps.

Followed all the steps on the github page. Could not get it to work. Any link to a tutorial?

You may need to paste the debug info which contains the error message in node-red that I would figure out what the problem is.
There is no tutorial video as it is a simply node-red flow, and can be customized to the requirements you need. The basic reason I made this is simply a random music player for my Google home, you could install the 3rd part video/music player which connects to HA that you don’t familiar with node-red.

I can’t get this to work. The following works in Developer tools, but in Node-red I get a “File could not be accessed” error from the File lister node.

service: media_player.play_media
data:
  entity_id: media_player.bedroom_speaker
  media_content_id: "/media/local/mp3/example.mp3"
  media_content_type: music

I assume I need to change the path in node-red, but I can’t work out what it’s supposed to be

You might need to attach a debug node before the node which throws the error and see the path to the File lister node whether correct.

Well it was a struggle to get this working with your github version i got there.

Playlist mapping

playlist_mapping = {
“Mp3”:“mp3/”,
“My Favorite”:“favorite_mp3/”,
“Pink Floyd”:“Pink-Floyd”,
“Dark Side of the Moon”:“DarkSideOfTheMoon”,
};

Here I have added two more entries my folder structure is based on iTunes so its itunesmedia/Music/Artist/Album/tracks

what I have done is create soft links to particular folders so the Pink Floyd soft link goes to the artist folder and the Dark Side of the Moon entry goes to the soft link for the album.

In the drop down helper i added two new options. “Pink Floyd” and “Dark Side of the Moon” i created soft links in config/media/ :“Pink-Floyd” and :“DarkSideOfTheMoon” The name in the drop down doesn’t matter as long as it matches the entry in the dictionary the folder mapping must match to a folder or soft link in /config/media
You have a choice as to creating a folder with the softlink in it or just creating the softlink in /config/media That may make a difference.

Playlist mapping goes to file lister and then to random item which feeds deal with url
the process is:
select the media folder to play
file lister get the files on that path
pick a random file
deal with the URL

Now if you bypass pick a random file (just disconnect it from the flow and wire from file lister to deal with the url and deploy that it disables the shuffle function and now it plays the tracks iin order (probably helps the file name starts 01 , 02 , ect) well at least thats how it works for dark side of the moon.

It gets a bit weird when it gets into sub folders. E.g i put a soft link for the album train spotting in Mp3 with random track bypassed and here it played the first track and then played the first track again and again…

I think it should be fairly easy to create a shuffle button to select via random track or not.

Anyway thats where i am for now. I will see if I can do that.

I’ve found with a lot of tracks there are a lot of errors with tracks not found and huge delays between tracks but it mostly works :slight_smile: