M3U Playlists in Media Browser

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:

you sir, are a legend ! after a bit of puzzling i got the playlists working on my dashboard and it works so much better than any other solution i came across so far. Finally i can remove the buggy and laggy spotcast integration. Thank you so much.

Good work!
I really appreciate your effort.
It works great with shuffle. but sometime I want to listen music in order.
I tried excluding random-item node, add cycle node and so on, but all failed.
Any idea?

Thank you guys like my coding.

I added the “ordered playing” into this project for you guys, which means now it is supported Shuffling and Ordered two playing modes.

@oakzito @blackest

with prev version, 2 steps for the updating.

  1. Adds the new toggle button as below
Name Entity ID Type Options Icon
Shuffle Music input_boolean.shuffle_music Toggle mdi:shuffle-variant
  1. Updates your node-red code with the newest ones.

v5 version

2 Likes

That’s working pretty well but I have an idea.
I have a folder music and in there is artist album then track its actually a soft link in config/media. now on the media page i can browse to an album and play individual tracks. so i can find the path ok.
now if your media player could take this path in through a texthelper and use that for the playlist :slight_smile: what do you think, maybe automatically adding it to the dropdown.

of course, the function has been added and released. You could simply click the “reload playlist” button and the N-R will put the folders into the playlist dropdown without configures the settings in N-R.
new version: v6

Updates

Update from v5 to v6

  1. Add the toggle in helpers of HA which name “Reload Playlist”
  2. Replace the content of the node-red to the newest ones.
  3. Update the configuration content in PLAYLIST.

Please note that this version you don’t need to adds the playlist and you could simply click the reload toggle in UI to make the N-R do it.