Building an audio repository: playing *any* song with the Raspberry Pi

Photo by Nevit Dilmen (2006)

There is a elegant solution to making an universal music player that can play almost any song you want (for free) with the Raspberry Pi. The key is to use YouTube, which just happens to almost every song uploaded, even rare ones! To get a song you simply have to query YouTube, get the right URL and play it. It turns out getting the URL is easy with an API and playing it is easy with VLC. It works almost everytime, as long as the song you want is at the top of the queue.

The key to this is using the YouTube API provided through Google. Simply follow the directions to get an API code and register the application.

def playMusic(query):
	pattern = re.compile('([^\s\w]|_)+')
	b_string = re.sub(pattern, '', query)
	phrase=b_string
	pattern = re.compile("\\b(some|play)\\W", re.I)
	query = [pattern.sub("", phrase)]
	query = query[0]
	print query
	url = "https://www.googleapis.com/youtube/v3/search?part=snippet&key="+keyring.get_password('google','api_secret')+"&q="+urllib.quote_plus(query)+"&type=video"
	response = urllib2.urlopen(url)
	jsonResp = response.read()
	decoded = json.loads(jsonResp)
	url = 'http://youtube.com/watch?v=' + decoded['items'][0]['id']['videoId']
	theSongName = decoded['items'][0]['snippet']['title']
	pattern = re.compile("([^a-zA-Z\d\s:,.']|_)+")
	theSongName = re.sub(pattern, '', theSongName)
	permission = getUserPermission("Do you want to hear " + theSongName)
	if permission:
		vlc = 'cvlc --no-video --volume 270 -A alsa,none --alsa-audio-device hw:1' + ' ' + url + ' --play-and-exit &'
		print url
		os.system(vlc)
		print "started music.."
		return "Sure I'll play " + theSongName
	else:
		return "Okay, I will play nothing."

The code is mostly self-explanatory. The query can be something like "Play some Beethoven". However you don’t want to search the noise words [play,some] so they are removed with regular expressions to get better search results. This code also assumes that you have your API secret in a keyring, but you can simply paste your own API in there. The rest simply probes the website and returns the results using JSON. It is possible to return a whole list of results and make a VLC queue, but this code just takes the top result.

Another trick I added to the code was that the AI will find the result and ask if it is correct. For this to work you need the following function that will use getUsersVoice for a short interval to get a Yes/No response to play the song (getUsersVoice is found here).

def getUserPermission(question):
	answer = 0
	saySomething(question,"en")
	response = getUsersVoice(2)
	if "yes" in response or "sure" in response or "okay" in response:
		answer = 1
	return answer

After everything seems good, the program will play the song in the background using cvlc. One note is that this uses a significant fraction of the CPU (20-70%) so it might slow down things a bit. I’m looking for a way around this, but maybe I just need to overclock my Pi. Let me know if you find a better way for this.

Leave a comment