mcthomas / Apple-Music-CLI-Player

A simple command-line Apple Music controller script which includes a "Now Playing" widget function, a playback function, and a list-out function for your Mac's Music.app library, written in sh.
MIT License
102 stars 10 forks source link

Add albums to library from command-line? #7

Open ajkessel opened 5 months ago

ajkessel commented 5 months ago

This script works well for music already in the user's library. Might you consider expanding it to play content that isn't yet in the library? I think this should be possible with AppleScript. At a minimum, you can open a itms:// item from the shell which will cause that URL to start playing in Music.app, even if it's not currently in the library. These links can be found by web-searching for the album/artist/track name + music.apple.com, and then replacing https:// with itms://

mcthomas commented 5 months ago

This is an interesting idea! I think as a start, if I am following, you could e.g. search for the song "Treefingers" with this program, a secondary script could search a query via google like treefingers site:music.apple.com, grab the first link from the results, replace "https" with "itms", and execute itms://music.apple.com/us/album/everything-in-its-right-place/1097862870?i=1097863108?app=Music. But at that point, it only opens to the album containing the track (while bringing Music.app to the foreground) and there's no real way to target and play the track in that open album view in Music.app given the available AppleScript syntax for Music.app. I am only aware of syntax for doing so with tracks previously added to the user's library.

So from there, some alternative options could be to use GUI scripting with AppleScript, which would really drive Music.app in the foreground instead of the CLI program, or to require a user to have an active browser session with Apple Music and play the music using GUI scripting with AppleScript or Python that touches your browser directly in the foreground.

Even though this program is tethered to Music.app as it is, it currently keeps it in the background. So I wouldn't want to pursue GUI scripting to make this work, however if you know of a way to start playing the track with the url, there could be a way forward (or let me know if I am missing something here).

ajkessel commented 5 months ago

You might be right about GUI-scraping. I had a shell script that accepted a URL (typically via iPhone share sheet-->shortcut-->ssh) that translated https to itms and then, depending on the type of URL, would click in the right place with

click UI Element 8 of group 3 of UI Element 1 of scroll area 1 of group 1 of group 1 of splitter group 1 of window "Music" of application Process "Music"

But this is obviously quite fragile and error-prone.

Is it also not possible to add to the library from the command-line? I wonder if that might be easier than GUI-scraping, and then you could use your existing interface for playing the content in the library.

mcthomas commented 5 months ago

I have not found any way to add to the library from the command-line, but I am basing that assertion on the limitations of AppleScript (open Script Editor.app, then go to File → Open Dictionary and choose Music.app to see what is possible with that API).

There are almost certainly ways to do this by leveraging Apple's MusicKit API, but I haven't yet looked into it. But addressing your original question, I don't think it is possible with AppleScript alone.

ajkessel commented 5 months ago

Can a playlist consist of itms links? I wonder if you could create a local playlist file with the tracks you want to play and then import that via as/add alias? I can do some experimentation if you don't know one way or the other.

ajkessel commented 5 months ago

So you can definitely add a m3u playlist from the command-line via

open filename.m3u -a /System/Applications/Music.app

I haven't yet figured out if there is a syntax for playlist items that will work where those items are streaming rather than local files. I tried just a simple itms:// link as well as an https:// link and it shows up as an item in music.app but isn't playable.

Then I tried exporting a streaming playlist as m3u and you just get an empty file.

But if you export a streaming playlist as an xml, you get a file with full metadata. I tried tweaking one of those and was able to create a new playlist, which I could then add and play from the command-line.

So it might be more work than it's worth, but it seems like if we had a CLI that generates an xml-format playlist based on streaming media URLs, that can then easily be added to the library and played from the command-line, no GUI-scraping requirement.

mcthomas commented 5 months ago

Wow that's an impressive hack, as an alternative to the MusicKit APIs. This sounds like it could be a separate scripting program that the current bash script could kick off as needed. There would still be some decisions to make in whether to allow fuzzy searching with a pre-queried index of songs per links by name, and how to manage the temporary xml-formatted playlist file- but if this is something you're interested in developing, it might serve best in a fork, or possibly a PR if you wanted to. That being said I'm unlikely to take this on, mostly because I think it will be difficult to integrate cohesively with the current cmd set without disallowing fuzzy searching for these songs outside of the user's library, as well as restricting the the List function for songs outside of the user's library.

ajkessel commented 5 months ago

Thanks. I'll continue to poke around on the XML format. I'm not yet sure if it's actually possible to populate the XML playlist file with URIs for tracks that don't currently exist in the user's catalogue. I asked over on Superuser but no dice.

mcthomas commented 5 months ago

AskDifferent might be another place to try. Thanks for exploring this, we can keep this open in case you have any updates you want to share, or maybe someone else will chime in with ideas.