Hi, I made some progress with parsing song requests of the form: “play (album|track|song|) {album|track} by (artist|band|) {artist}”. Here is the crux of a function to do that (I’m at the stage of calling the Emby RESTful APIs):
def parse_phrase(phrase):
album = "unknown-album"
artist = "unknown-artist"
found_by = "yes" # assume "by" is in the phrase
intent_type = "unknown" # album, album-artist, artist, music, track, track-artist or unknown
music = "" # used if not known to be "album", "track" or "artist"
track = "unknown-track" # synonymous with "song"
print("phrase = " + phrase)
# remove leading "play" if found then split the request on the word "by"
key = re.split("^play ", phrase) # remove play if first word
if len(key) == 2: # found first word "play"
key = re.split(" by ", str(key[1]))
else:
key = re.split(" by ", phrase)
if len(key) == 1: # did not find "by"
music = str(key[0])
if music == "any music" or music == "all music" or music == "my music" or music == "music":
intent_type = "music"
found_by = "no"
elif len(key) == 2: # found one "by"
music = str(key[0])
artist = str(key[1])
elif len(key) == 3: # found "by" twice - assume first one is in music
music = str(key[0]) + " by " + str(key[1]) # paste the track or album back together
artist = str(key[2])
else: # punt
music = str(key[0])
# look for (album|track|song|artist) in music
key = re.split("^album ", music) # remove "album" if first word
if len(key) == 2: # found first word "album"
album = str(key[1]) # save album name
if found_by == "yes":
intent_type = "album-artist"
else:
intent_type = "album"
else: # leading "album" not found
key = re.split("^track |^song ", music) # remove "track" or "song" if first word
if len(key) == 2: # leading "track" or "song" found
track = str(key[1])
if found_by == "yes":
intent_type = "track-artist"
else: # assume track
intent_type = "track"
else: # leading keyword not found
key = re.split("^artist |^band ", music) # remove "artist" or "band" if first word
if len(key) == 2: # leading "artist" or "band" found
artist = str(key[1])
if found_by == "yes":
intent_type = "track-artist"
else:
intent_type = "artist"
else: # no leading keywords found
track = music
if found_by == "yes":
intent_type = "track-artist"
...
Here are some tests - most of them work:
$ testparse.py
phrase = play album let it be by the beatles
==> call get_albums_by_artist(the beatles) then search for album 'let it be'
-------------------------
phrase = play down by the seaside by led zeppelin
==> call get_songs_by_artist(led zeppelin) and search for track 'down by the seaside'
-------------------------
phrase = play track down by the seaside
==> call get_songs_by_artist(the seaside) and search for track 'down'
-------------------------
phrase = play track let it be by artist the beatles
==> call get_songs_by_artist(artist the beatles) and search for track 'let it be'
-------------------------
phrase = play track let it be by band the beatles
==> call get_songs_by_artist(band the beatles) and search for track 'let it be'
-------------------------
phrase = play let it be by the beatles
==> call get_songs_by_artist(the beatles) and search for track 'let it be'
-------------------------
phrase = play let it be
==> call get_random_songs()
-------------------------
phrase = play song hey jude
==> call find_songs(hey jude)
-------------------------
phrase = play artist the beatles
==> call search_artist(the beatles) and play songs
-------------------------
phrase = play some music
==> call get_random_songs()
-------------------------
The test “play down by the seaside by led zeppelin” suceeds as it assumes the first “by” is in the track name. However, “play down by the seaside” fails as it assumes the track is “down” and the band is “by the seaside”. There could be code added to try a second call with just the entire track name.
I’m assuming this shouldn’t be moved into the common play skill, but rather, into the music playing skill,
emby.rickyphewitt, in my case. Is Ricky P Hewitt still involved with that skill?
Also, it’s hard coded to English. Supporting other languages should be doable, but would probably be tricky…
Anybody have any suggestions?
Thanks.
-Mike Mac